|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r57312 - trunk/libs/spirit/example/lex
From: hartmut.kaiser_at_[hidden]
Date: 2009-11-03 10:28:31
Author: hkaiser
Date: 2009-11-03 10:28:30 EST (Tue, 03 Nov 2009)
New Revision: 57312
URL: http://svn.boost.org/trac/boost/changeset/57312
Log:
Spirit: added a new lexer example
Added:
trunk/libs/spirit/example/lex/custom_token_attribute.cpp (contents, props changed)
Text files modified:
trunk/libs/spirit/example/lex/Jamfile | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
Modified: trunk/libs/spirit/example/lex/Jamfile
==============================================================================
--- trunk/libs/spirit/example/lex/Jamfile (original)
+++ trunk/libs/spirit/example/lex/Jamfile 2009-11-03 10:28:30 EST (Tue, 03 Nov 2009)
@@ -21,4 +21,5 @@
exe word_count_functor_flex : word_count_functor_flex.cpp ;
exe strip_comments : strip_comments.cpp ;
exe strip_comments_lexer : strip_comments_lexer.cpp ;
+exe custom_token_attribute : custom_token_attribute.cpp ;
Added: trunk/libs/spirit/example/lex/custom_token_attribute.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/lex/custom_token_attribute.cpp 2009-11-03 10:28:30 EST (Tue, 03 Nov 2009)
@@ -0,0 +1,112 @@
+// Copyright (c) 2001-2009 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 <boost/spirit/include/lex_lexertl.hpp>
+#include <boost/spirit/include/qi.hpp>
+
+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 <typename Iterator>
+ struct assign_to_attribute_from_iterators<rational, Iterator>
+ {
+ 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 <typename Lexer>
+struct lex_rational : lex::lexer<Lexer>
+{
+ lex_rational()
+ {
+ this->self.add_pattern("INT", "[1-9][0-9]*");
+
+ rt = "\\{{INT},{INT}\\}";
+ this->self.add(rt);
+ }
+ lex::token_def<rational> 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<std::string::iterator,
+ mpl::vector<rational> > token_type;
+
+ // use actor_lexer<> here if your token definitions have semantic
+ // actions
+ typedef lex::lexertl::lexer<token_type> 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<lexer_type> 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;
+}
+
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk