2
0
mirror of https://github.com/boostorg/spirit.git synced 2026-01-19 04:42:11 +00:00
Files
spirit/test/lex/regression_syntax_error.cpp
Nikita Kniazev 156bd18d17 Narrow Proto and Phoenix inclusion
Include needed parts at place where they are needed instead of including the
whole Proto library and significant parts of Phoenix in a few places.

Parsing time reported by Clang 9 with default (C++14) std:

was |now |gain|include
----|----|----|----------
4.45|4.22|5.2%|qi
4.52|4.23|7.5%|karma
4.37|3.99|9.7%|lex
3.75|3.47|7.5%|qi_numeric

There were phoenix/limits.hpp inclusion before every Proto inclusion to override
Proto limits with Phoenix limits values. It has no value in C++11+ world, and
poisons code too much as the number of places where Proto headers now included
increased, so I did not replicate it.
2019-11-29 03:20:30 +03:00

98 lines
2.8 KiB
C++

// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2009 Jean-Francois Ostiguy
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/detail/lightweight_test.hpp>
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/lex_lexertl.hpp>
#include <boost/spirit/include/qi_parse.hpp>
#include <boost/spirit/include/qi_operator.hpp>
#include <boost/spirit/include/qi_char.hpp>
#include <boost/spirit/include/qi_grammar.hpp>
#include <boost/spirit/include/qi_eoi.hpp>
#include <boost/phoenix/operator/self.hpp>
#include <string>
#include <iostream>
#include <sstream>
namespace lex = boost::spirit::lex;
namespace qi = boost::spirit::qi;
namespace mpl = boost::mpl;
template <typename Lexer>
struct my_lexer : lex::lexer<Lexer>
{
my_lexer()
{
delimiter = "BEGIN|END";
identifier = "[a-zA-Z][_\\.a-zA-Z0-9]*";
ws = "[ \\t\\n]+";
real = "([0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?)|([-+]?[1-9]+\\.?([eE][-+]?[0-9]+))";
integer = "[0-9]+";
this->self += ws[lex::_pass = lex::pass_flags::pass_ignore];
this->self += delimiter;
this->self += identifier;
this->self += real;
this->self += integer;
this->self += '=';
this->self += ';';
}
lex::token_def<> ws;
lex::token_def<std::string> identifier;
lex::token_def<int> integer;
lex::token_def<double> real;
lex::token_def<> delimiter;
};
template <typename Iterator>
struct my_grammar : qi::grammar<Iterator>
{
template <typename TokenDef>
my_grammar( TokenDef const& tok )
: my_grammar::base_type(statement)
{
statement
= qi::eoi
| *(delimiter | declaration)
;
delimiter = tok.delimiter >> tok.identifier;
declaration = tok.identifier >> option >> ';';
option = *(tok.identifier >> '=' >> (tok.real | tok.integer));
}
qi::rule<Iterator> statement, delimiter, declaration, option;
};
typedef lex::lexertl::token<char const*
, mpl::vector<std::string, double, int> > token_type;
typedef lex::lexertl::actor_lexer<token_type> lexer_type;
typedef my_lexer<lexer_type>::iterator_type iterator_type;
int main()
{
std::string test_string ("BEGIN section\n");
// we introduce a syntax error: ";;" instead of ";" as a terminator.
test_string += "Identity;;\n"; // this will make the parser fail
test_string += "END section\n" ;
char const* first = &test_string[0];
char const* last = &first[test_string.size()];
my_lexer<lexer_type> lexer;
my_grammar<iterator_type> grammar(lexer);
BOOST_TEST(lex::tokenize_and_parse(first, last, lexer, grammar));
BOOST_TEST(first != last);
return boost::report_errors();
}