1 /*=============================================================================
2 Copyright (c) 2001-2010 Joel de Guzman
4 Distributed under the Boost Software License, Version 1.0. (See accompanying
5 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 =============================================================================*/
7 ///////////////////////////////////////////////////////////////////////////////
9 // A Roman Numerals Parser (demonstrating the symbol table). This is
10 // discussed in the "Symbols" chapter in the Spirit User's Guide.
12 // [ JDG August 22, 2002 ] spirit1
13 // [ JDG March 13, 2007 ] spirit2
15 ///////////////////////////////////////////////////////////////////////////////
17 #include <boost/config/warning_disable.hpp>
18 #include <boost/spirit/include/qi.hpp>
19 #include <boost/spirit/include/phoenix_operator.hpp>
26 namespace qi
= boost::spirit::qi
;
27 namespace ascii
= boost::spirit::ascii
;
29 ///////////////////////////////////////////////////////////////////////////////
30 // Parse roman hundreds (100..900) numerals using the symbol table.
31 // Notice that the data associated with each slot is the parser's attribute
32 // (which is passed to attached semantic actions).
33 ///////////////////////////////////////////////////////////////////////////////
34 //[tutorial_roman_hundreds
35 struct hundreds_
: qi::symbols
<char, unsigned>
55 ///////////////////////////////////////////////////////////////////////////////
56 // Parse roman tens (10..90) numerals using the symbol table.
57 ///////////////////////////////////////////////////////////////////////////////
58 //[tutorial_roman_tens
59 struct tens_
: qi::symbols
<char, unsigned>
79 ///////////////////////////////////////////////////////////////////////////////
80 // Parse roman ones (1..9) numerals using the symbol table.
81 ///////////////////////////////////////////////////////////////////////////////
82 //[tutorial_roman_ones
83 struct ones_
: qi::symbols
<char, unsigned>
103 ///////////////////////////////////////////////////////////////////////////////
104 // roman (numerals) grammar
106 // Note the use of the || operator. The expression
107 // a || b reads match a or b and in sequence. Try
108 // defining the roman numerals grammar in YACC or
109 // PCCTS. Spirit rules! :-)
110 ///////////////////////////////////////////////////////////////////////////////
111 //[tutorial_roman_grammar
112 template <typename Iterator
>
113 struct roman
: qi::grammar
<Iterator
, unsigned()>
115 roman() : roman::base_type(start
)
123 start
= eps
[_val
= 0] >>
125 +lit('M') [_val
+= 1000]
126 || hundreds
[_val
+= _1
]
133 qi::rule
<Iterator
, unsigned()> start
;
138 ///////////////////////////////////////////////////////////////////////////////
140 ///////////////////////////////////////////////////////////////////////////////
144 std::cout
<< "/////////////////////////////////////////////////////////\n\n";
145 std::cout
<< "\t\tRoman Numerals Parser\n\n";
146 std::cout
<< "/////////////////////////////////////////////////////////\n\n";
147 std::cout
<< "Type a Roman Numeral ...or [q or Q] to quit\n\n";
149 typedef std::string::const_iterator iterator_type
;
150 typedef client::roman
<iterator_type
> roman
;
152 roman roman_parser
; // Our grammar
156 while (std::getline(std::cin
, str
))
158 if (str
.empty() || str
[0] == 'q' || str
[0] == 'Q')
161 std::string::const_iterator iter
= str
.begin();
162 std::string::const_iterator end
= str
.end();
163 //[tutorial_roman_grammar_parse
164 bool r
= parse(iter
, end
, roman_parser
, result
);
166 if (r
&& iter
== end
)
168 std::cout
<< "-------------------------\n";
169 std::cout
<< "Parsing succeeded\n";
170 std::cout
<< "result = " << result
<< std::endl
;
171 std::cout
<< "-------------------------\n";
175 std::string
rest(iter
, end
);
176 std::cout
<< "-------------------------\n";
177 std::cout
<< "Parsing failed\n";
178 std::cout
<< "stopped at: \": " << rest
<< "\"\n";
179 std::cout
<< "-------------------------\n";
184 std::cout
<< "Bye... :-) \n\n";