165 lines
6.6 KiB
C++
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
|