0
|
1 #include <boost/spirit/core.hpp>
|
|
2 #include <boost/spirit/utility/confix.hpp>
|
|
3 #include <boost/spirit/tree/ast.hpp>
|
|
4 #include <boost/spirit/utility/escape_char.hpp>
|
|
5 #include <boost/spirit/iterator/position_iterator.hpp>
|
|
6 #include <boost/spirit/iterator/file_iterator.hpp>
|
|
7 #include <boost/spirit/utility/functor_parser.hpp>
|
|
8 #include <iostream>
|
|
9 #include <map>
|
|
10 #include <string>
|
|
11 #include <cassert>
|
|
12 #include <algorithm>
|
|
13
|
|
14 using namespace std;
|
|
15 using namespace boost::spirit;
|
|
16
|
|
17 typedef file_iterator<> iterator_t;
|
|
18 typedef node_val_data_factory<int> factory_t;
|
|
19 typedef tree_match<iterator_t, factory_t> tree_match_t;
|
|
20 typedef tree_match_t::tree_iterator tree_iter_t;
|
|
21
|
|
22 map<string, int> values; // 変数テーブル
|
|
23
|
|
24 struct error_parser {
|
|
25 typedef nil_t result_t; // パーサーの結果型(nil_t)
|
|
26
|
|
27 error_parser(char const *msg)
|
|
28 : msg_(msg)
|
|
29 {
|
|
30 }
|
|
31
|
|
32 template <typename ScannerT>
|
|
33 int operator()(ScannerT const &scan, result_t &result) const
|
|
34 {
|
|
35 // 終わりまで来たら-1を返す
|
|
36 if (scan.at_end()) {
|
|
37 return -1;
|
|
38 }
|
|
39
|
|
40 cout << msg_ << endl;
|
|
41 // 解釈した「長さ」を返すと、その分スキップするので
|
|
42 // 改行までをスキャンし、その分をスキップ
|
|
43 return (int)(*(anychar_p - '\n') >> ch_p('\n')).parse(scan).length();
|
|
44 }
|
|
45
|
|
46 private:
|
|
47 const char *msg_;
|
|
48 } ;
|
|
49
|
|
50 typedef functor_parser<error_parser> error_p;
|
|
51
|
|
52 // エラー処理パーサー定義
|
|
53 error_p syntax_error_p = error_parser("文法エラー");
|
|
54
|
|
55 // ノードに値を設定する
|
|
56 struct set_value {
|
|
57 set_value(int id): id_(id){}
|
|
58 void operator()(tree_node< node_val_data<iterator_t, int> >& node,
|
|
59 iterator_t b, iterator_t e) const
|
|
60 {
|
|
61 node.value.value(id_);
|
|
62 }
|
|
63 int id_;
|
|
64 } ;
|
|
65
|
|
66 // 文法定義
|
|
67 struct calc_grammer: public grammar<calc_grammer> {
|
|
68 enum {
|
|
69 OP_NOP,
|
|
70 OP_IDENTIFIER,
|
|
71 OP_NUMBER,
|
|
72 OP_NEG,
|
|
73 OP_MUL,
|
|
74 OP_DIV,
|
|
75 OP_ADD,
|
|
76 OP_SUB,
|
|
77 OP_ASSIGN,
|
|
78 OP_PRINT,
|
|
79 OP_LIST,
|
|
80 } ;
|
|
81
|
|
82 template <typename ScannerT>
|
|
83 struct definition {
|
|
84 rule<ScannerT> identifier;
|
|
85 rule<ScannerT> number;
|
|
86 rule<ScannerT> prime;
|
|
87 rule<ScannerT> unary;
|
|
88 rule<ScannerT> mul_expr;
|
|
89 rule<ScannerT> add_expr;
|
|
90 rule<ScannerT> assign;
|
|
91 rule<ScannerT> print;
|
|
92 rule<ScannerT> list;
|
|
93 rule<ScannerT> statement;
|
|
94 rule<ScannerT> input;
|
|
95
|
|
96 definition(calc_grammer const& self)
|
|
97 {
|
|
98 identifier = access_node_d[leaf_node_d[lexeme_d[alpha_p >> *alnum_p]]][set_value(OP_IDENTIFIER)];
|
|
99 number = access_node_d[uint_p][set_value(OP_NUMBER)];
|
|
100
|
|
101 prime = identifier
|
|
102 | number
|
|
103 | inner_node_d['(' >> add_expr >> ')']
|
|
104 ;
|
|
105
|
|
106 unary = prime
|
|
107 | access_node_d[root_node_d[ch_p('-')]][set_value(OP_NEG)] >> prime
|
|
108 ;
|
|
109
|
|
110 mul_expr = unary % root_node_d[access_node_d[ch_p('*')][set_value(OP_MUL)] | access_node_d[ch_p('/')][set_value(OP_DIV)]];
|
|
111
|
|
112 add_expr = mul_expr % root_node_d[access_node_d[ch_p('+')][set_value(OP_ADD)] | access_node_d[ch_p('-')][set_value(OP_SUB)]];
|
|
113
|
|
114 assign = identifier >> access_node_d[root_node_d[ch_p('=')]][set_value(OP_ASSIGN)] >> add_expr;
|
|
115 print = access_node_d[root_node_d[str_p("print")]][set_value(OP_PRINT)] >> add_expr;
|
|
116 list = access_node_d[root_node_d[str_p("list")]][set_value(OP_LIST)];
|
|
117
|
|
118 statement = root_node_d[assign | print | list] >> discard_node_d[ch_p('\n')];
|
|
119
|
|
120 // 入力は、「文」、「空行」もしくは「エラー」
|
|
121 input = *(statement | discard_node_d[ch_p('\n')] | syntax_error_p);
|
|
122 }
|
|
123
|
|
124 rule<ScannerT> const& start() const
|
|
125 {
|
|
126 return input;
|
|
127 }
|
|
128 } ;
|
|
129 } ;
|
|
130
|
|
131 // ツリーのイテレータから、変数を取り出す
|
|
132
|
|
133 int &value_ref(const tree_iter_t &it)
|
|
134 {
|
|
135 return values[string(it->value.begin(), it->value.end())];
|
|
136 }
|
|
137
|
|
138 // リストコマンドの関数オブジェクト
|
|
139
|
|
140 struct list_action {
|
|
141 void operator()(const std::pair<std::string, int> &it)
|
|
142 {
|
|
143 cout << it.first << " = " << it.second << endl;
|
|
144 }
|
|
145 } ;
|
|
146
|
|
147 int eval(const tree_iter_t &it)
|
|
148 {
|
|
149 switch (it->value.value()) {
|
|
150 case calc_grammer::OP_NEG:
|
|
151 assert(it->children.size() == 1);
|
|
152 return -eval(it->children.begin());
|
|
153
|
|
154 case calc_grammer::OP_ADD:
|
|
155 assert(it->children.size() == 2);
|
|
156 return eval(it->children.begin()) + eval(it->children.begin() + 1);
|
|
157
|
|
158 case calc_grammer::OP_SUB:
|
|
159 assert(it->children.size() == 2);
|
|
160 return eval(it->children.begin()) - eval(it->children.begin() + 1);
|
|
161
|
|
162 case calc_grammer::OP_MUL:
|
|
163 assert(it->children.size() == 2);
|
|
164 return eval(it->children.begin()) * eval(it->children.begin() + 1);
|
|
165
|
|
166 case calc_grammer::OP_DIV:
|
|
167 assert(it->children.size() == 2);
|
|
168 return eval(it->children.begin()) / eval(it->children.begin() + 1);
|
|
169
|
|
170 case calc_grammer::OP_ASSIGN:
|
|
171 assert(it->children.size() == 2);
|
|
172 return value_ref(it->children.begin()) = eval(it->children.begin() + 1);
|
|
173
|
|
174 case calc_grammer::OP_IDENTIFIER:
|
|
175 return values[string(it->value.begin(), it->value.end())];
|
|
176
|
|
177 case calc_grammer::OP_NUMBER:
|
|
178 return atoi(string(it->value.begin(), it->value.end()).c_str());
|
|
179
|
|
180 case calc_grammer::OP_PRINT:
|
|
181 cout << eval(it->children.begin()) << endl;
|
|
182 break;
|
|
183
|
|
184 case calc_grammer::OP_LIST:
|
|
185 for_each(values.begin(), values.end(), list_action());
|
|
186 break;
|
|
187 }
|
|
188 return 0;
|
|
189 }
|
|
190
|
|
191 // main
|
|
192
|
|
193 int main(int argc, char *argv[])
|
|
194 {
|
|
195 // ファイルの読み込みに、file_iteratorを使用する
|
|
196 file_iterator<> first("input.txt");
|
|
197 if (!first) {
|
|
198 cout << "ファイルがオープンできません。" << endl;
|
|
199 return 1;
|
|
200 }
|
|
201 file_iterator<> last = first.make_end();
|
|
202
|
|
203 // 抽象構文木作成
|
|
204 calc_grammer gr;
|
|
205 tree_parse_info<iterator_t, factory_t> info; // 解析情報を保持する変数
|
|
206 info = ast_parse(first, last, gr, ch_p(' ') | ch_p('\t') | ch_p('\r'), factory_t());
|
|
207
|
|
208 if (info.full) {
|
|
209 const tree_iter_t &root = info.trees.begin();
|
|
210 size_t size = root->children.size();
|
|
211 for(size_t i=0; i<size; i++) {
|
|
212 eval(root->children.begin() + i);
|
|
213 }
|
|
214 }
|
|
215 else {
|
|
216 // エラー処理が入っているので、エラー処理されるとここには来ない
|
|
217 // エラー処理パーサーで、エラー処理を行ったら失敗としたほうが
|
|
218 // 良い。
|
|
219 cout << "構文解析失敗" << endl;
|
|
220 }
|
|
221
|
|
222 return 0;
|
|
223 }
|