// Copyright (c) 2001-2010 Hartmut Kaiser // // 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) // The purpose of this example is to demonstrate how custom, user defined types // can be easily integrated with the lexer as token value types. Moreover, the // custom token values are properly exposed to the parser as well, allowing to // retrieve the custom values using the built in parser attribute propagation // rules. #include #include namespace lex = boost::spirit::lex; namespace qi = boost::spirit::qi; namespace mpl = boost::mpl; /////////////////////////////////////////////////////////////////////////////// // This is just a simple custom rational data structure holding two ints to be // interpreted as a rational number struct rational { rational(int n = 0, int d = 0) : nominator_(n), denominator_(d) {} int nominator_; int denominator_; }; /////////////////////////////////////////////////////////////////////////////// // A rational is represented as "{n,d}", where 'n' and 'd' are the nominator // and denominator of the number. We use Spirit.Qi to do the low level parsing // of the input sequence as matched by the lexer. Certainly, any other // conversion could be used instead. // // The lexer uses the template assign_to_attribute_from_iterators<> to convert // the matched input sequence (pair of iterators) to the token value type as // specified while defining the lex::token_def<>. // // Our specialization of assign_to_attribute_from_iterators<> for the rational // data type defined above has to be placed into the // namespace boost::spirit::traits, otherwise it won't be found by the library. namespace boost { namespace spirit { namespace traits { template struct assign_to_attribute_from_iterators { static void call(Iterator const& first, Iterator const& last, rational& attr) { int x, y; Iterator b = first; qi::parse(b, last, '{' >> qi::int_ >> ',' >> qi::int_ >> '}', x, y); attr = rational(x, y); } }; }}} /////////////////////////////////////////////////////////////////////////////// // a lexer recognizing a single token type: rational template struct lex_rational : lex::lexer { lex_rational() { this->self.add_pattern("INT", "[1-9][0-9]*"); rt = "\\{{INT},{INT}\\}"; this->self.add(rt); } lex::token_def rt; }; int main() { // the token type needs to know the iterator type of the underlying // input and the set of used token value types typedef lex::lexertl::token > token_type; // use actor_lexer<> here if your token definitions have semantic // actions typedef lex::lexertl::lexer lexer_type; // this is the iterator exposed by the lexer, we use this for parsing typedef lexer_type::iterator_type iterator_type; // create a lexer instance std::string input("{3,4}"); std::string::iterator s = input.begin(); lex_rational lex; iterator_type b = lex.begin(s, input.end()); // use the embedded token_def as a parser, it exposes its token value type // as its parser attribute type rational r; if (!qi::parse(b, lex.end(), lex.rt, r)) { std::cerr << "Parsing failed!" << std::endl; return -1; } std::cout << "Parsing succeeded: {" << r.nominator_ << ", " << r.denominator_ << "}" << std::endl; return 0; }