eedb/share/include/tao/json/external/pegtl/contrib/raw_string.hh
2017-02-26 09:32:45 +01:00

165 lines
6.6 KiB
C++

// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/ColinH/PEGTL/
#ifndef TAO_CPP_PEGTL_CONTRIB_RAW_STRING_HH
#define TAO_CPP_PEGTL_CONTRIB_RAW_STRING_HH
#include "../action_input.hh"
#include "../apply_mode.hh"
#include "../nothing.hh"
#include "../internal/must.hh"
#include "../internal/until.hh"
#include "../internal/state.hh"
#include "../internal/skip_control.hh"
#include "../analysis/generic.hh"
namespace tao_json_pegtl
{
namespace internal
{
template< char Open, char Intermediate, char Close >
struct raw_string_tag
{ };
template< typename Tag >
struct raw_string_state
{
template< typename Input, typename ... States >
raw_string_state( const Input & in, States && ... )
: byte( in.byte() ),
line( in.line() ),
byte_in_line( in.byte_in_line() ),
size( in.size( 0 ) )
{ }
template< apply_mode A, template< typename ... > class Action, template< typename ... > class Control, typename Input, typename ... States >
typename std::enable_if< ( ( A == apply_mode::ACTION ) && ( ! is_nothing< Action, Tag >::value ) ) >::type
success( const Input & in, States && ... st ) const
{
using eol_t = typename Input::eol_t;
using action_t = typename Input::action_t;
const auto * const begin = in.begin() - size + in.size( 0 ) + count;
action_t action_in( byte, line, byte_in_line, begin + ( ( * begin ) == eol_t::ch ), in.begin() - count, in.source() );
Action< Tag >::apply( const_cast< const action_t & >( action_in ), st ... );
}
template< apply_mode A, template< typename ... > class Action, template< typename ... > class Control, typename Input, typename ... States >
typename std::enable_if< ! ( ( A == apply_mode::ACTION ) && ( ! is_nothing< Action, Tag >::value ) ) >::type
success( const Input &, States && ... ) const
{ }
raw_string_state( const raw_string_state & ) = delete;
void operator= ( const raw_string_state & ) = delete;
std::size_t byte;
std::size_t line;
std::size_t byte_in_line;
std::size_t size;
std::size_t count = 0;
};
template< typename Tag, char Open, char Intermediate >
struct raw_string_open
{
using analyze_t = analysis::generic< analysis::rule_type::ANY >;
template< apply_mode A, template< typename ... > class Action, template< typename ... > class Control, typename Input >
static bool match( Input & in, raw_string_state< Tag > & ls )
{
if ( in.empty() || ( in.peek_char( 0 ) != Open ) ) {
return false;
}
for ( std::size_t i = 1; i < in.size( i + 1 ); ++i ) {
switch ( const auto c = in.peek_char( i ) ) {
case Open:
ls.count = i + 1;
in.bump( ls.count );
return true;
case Intermediate:
break;
default:
return false;
}
}
return false;
}
};
template< typename Tag, char Intermediate, char Close >
struct raw_string_close
{
using analyze_t = analysis::generic< analysis::rule_type::ANY >;
template< apply_mode A, template< typename ... > class Action, template< typename ... > class Control, typename Input >
static bool match( Input & in, const raw_string_state< Tag > & ls )
{
if ( in.size( ls.count ) < ls.count ) {
return false;
}
if ( in.peek_char( 0 ) != Close ) {
return false;
}
if ( in.peek_char( ls.count - 1 ) != Close ) {
return false;
}
for ( std::size_t i = 0; i < ls.count - 2; ++i ) {
if ( in.peek_char( i + 1 ) != Intermediate ) {
return false;
}
}
in.bump( ls.count );
return true;
}
};
template< typename Tag, char Open, char Intermediate >
struct skip_control< raw_string_open< Tag, Open, Intermediate > > : std::true_type {};
template< typename Tag, char Intermediate, char Close >
struct skip_control< raw_string_close< Tag, Intermediate, Close > > : std::true_type {};
} // namespace internal
// raw_string matches Lua-style long literals.
//
// The following description was taken from the Lua documentation
// (see http://www.lua.org/docs.html):
//
// - An "opening long bracket of level n" is defined as an opening square
// bracket followed by n equal signs followed by another opening square
// bracket. So, an opening long bracket of level 0 is written as `[[`,
// an opening long bracket of level 1 is written as `[=[`, and so on.
// - A "closing long bracket" is defined similarly; for instance, a closing
// long bracket of level 4 is written as `]====]`.
// - A "long literal" starts with an opening long bracket of any level and
// ends at the first closing long bracket of the same level. It can
// contain any text except a closing bracket of the same level.
// - Literals in this bracketed form can run for several lines, do not
// interpret any escape sequences, and ignore long brackets of any other
// level.
// - For convenience, when the opening long bracket is immediately followed
// by a newline, the newline is not included in the string.
//
// Note that unlike Lua's long literal, a raw_string is customizable to use
// other characters than `[`, `=` and `]` for matching. Also note that Lua
// introduced newline-specific replacements in Lua 5.2, which we do not
// support on the grammar level.
template< char Open, char Intermediate, char Close, typename Tag = internal::raw_string_tag< Open, Intermediate, Close > >
struct raw_string : internal::state< internal::raw_string_state< Tag >,
internal::raw_string_open< Tag, Open, Intermediate >,
internal::must< internal::until< internal::raw_string_close< Tag, Intermediate, Close > > > >
{
// This is used to bind an action to the content.
using content = Tag;
// This is used for error-reporting when a raw string is not closed properly.
using close = internal::until< internal::raw_string_close< Tag, Intermediate, Close > >;
};
} // namespace tao_json_pegtl
#endif