]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/example/x3/roman.cpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / spirit / example / x3 / roman.cpp
1 /*=============================================================================
2 Copyright (c) 2001-2015 Joel de Guzman
3 Copyright (c) 2015 Ahmed Charles
4
5 Distributed under the Boost Software License, Version 1.0. (See accompanying
6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 =============================================================================*/
8 ///////////////////////////////////////////////////////////////////////////////
9 //
10 // A Roman Numerals Parser (demonstrating the symbol table). This is
11 // discussed in the "Symbols" chapter in the Spirit User's Guide.
12 //
13 // [ JDG August 22, 2002 ] spirit1
14 // [ JDG March 13, 2007 ] spirit2
15 // [ JDG May 13, 2015 ] spirit X3
16 //
17 ///////////////////////////////////////////////////////////////////////////////
18
19 #include <boost/spirit/home/x3.hpp>
20
21 #include <iostream>
22 #include <string>
23
24 namespace client
25 {
26 namespace x3 = boost::spirit::x3;
27 namespace ascii = boost::spirit::x3::ascii;
28
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 struct hundreds_ : x3::symbols<unsigned>
35 {
36 hundreds_()
37 {
38 add
39 ("C" , 100)
40 ("CC" , 200)
41 ("CCC" , 300)
42 ("CD" , 400)
43 ("D" , 500)
44 ("DC" , 600)
45 ("DCC" , 700)
46 ("DCCC" , 800)
47 ("CM" , 900)
48 ;
49 }
50
51 } hundreds;
52
53 ///////////////////////////////////////////////////////////////////////////////
54 // Parse roman tens (10..90) numerals using the symbol table.
55 ///////////////////////////////////////////////////////////////////////////////
56 struct tens_ : x3::symbols<unsigned>
57 {
58 tens_()
59 {
60 add
61 ("X" , 10)
62 ("XX" , 20)
63 ("XXX" , 30)
64 ("XL" , 40)
65 ("L" , 50)
66 ("LX" , 60)
67 ("LXX" , 70)
68 ("LXXX" , 80)
69 ("XC" , 90)
70 ;
71 }
72
73 } tens;
74
75 ///////////////////////////////////////////////////////////////////////////////
76 // Parse roman ones (1..9) numerals using the symbol table.
77 ///////////////////////////////////////////////////////////////////////////////
78 struct ones_ : x3::symbols<unsigned>
79 {
80 ones_()
81 {
82 add
83 ("I" , 1)
84 ("II" , 2)
85 ("III" , 3)
86 ("IV" , 4)
87 ("V" , 5)
88 ("VI" , 6)
89 ("VII" , 7)
90 ("VIII" , 8)
91 ("IX" , 9)
92 ;
93 }
94
95 } ones;
96
97 ///////////////////////////////////////////////////////////////////////////////
98 // roman (numerals) grammar
99 //
100 // Note the use of the || operator. The expression
101 // a || b reads match a or b and in sequence. Try
102 // defining the roman numerals grammar in YACC or
103 // PCCTS. Spirit rules! :-)
104 ///////////////////////////////////////////////////////////////////////////////
105 namespace parser
106 {
107 using x3::eps;
108 using x3::lit;
109 using x3::_val;
110 using x3::_attr;
111 using ascii::char_;
112
113 auto set_zero = [](auto& ctx){ _val(ctx) = 0; };
114 auto add1000 = [](auto& ctx){ _val(ctx) += 1000; };
115 auto add = [](auto& ctx){ _val(ctx) += _attr(ctx); };
116
117 x3::rule<class roman, unsigned> const roman = "roman";
118
119 auto const roman_def =
120 eps [set_zero]
121 >>
122 (
123 -(+lit('M') [add1000])
124 >> -hundreds [add]
125 >> -tens [add]
126 >> -ones [add]
127 )
128 ;
129
130 BOOST_SPIRIT_DEFINE(roman);
131 }
132 }
133
134 ///////////////////////////////////////////////////////////////////////////////
135 // Main program
136 ///////////////////////////////////////////////////////////////////////////////
137 int
138 main()
139 {
140 std::cout << "/////////////////////////////////////////////////////////\n\n";
141 std::cout << "\t\tRoman Numerals Parser\n\n";
142 std::cout << "/////////////////////////////////////////////////////////\n\n";
143 std::cout << "Type a Roman Numeral ...or [q or Q] to quit\n\n";
144
145 typedef std::string::const_iterator iterator_type;
146 using client::parser::roman; // Our parser
147
148 std::string str;
149 unsigned result;
150 while (std::getline(std::cin, str))
151 {
152 if (str.empty() || str[0] == 'q' || str[0] == 'Q')
153 break;
154
155 iterator_type iter = str.begin();
156 iterator_type const end = str.end();
157 bool r = parse(iter, end, roman, result);
158
159 if (r && iter == end)
160 {
161 std::cout << "-------------------------\n";
162 std::cout << "Parsing succeeded\n";
163 std::cout << "result = " << result << std::endl;
164 std::cout << "-------------------------\n";
165 }
166 else
167 {
168 std::string rest(iter, end);
169 std::cout << "-------------------------\n";
170 std::cout << "Parsing failed\n";
171 std::cout << "stopped at: \": " << rest << "\"\n";
172 std::cout << "-------------------------\n";
173 }
174 }
175
176 std::cout << "Bye... :-) \n\n";
177 return 0;
178 }