Mercurial > hg > Members > nobuyasu > SampleSource
view boost-spirit/CALC/rule/calc.cpp @ 0:db40c85cad7a default tip
upload sample source
author | nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 09 May 2011 03:11:59 +0900 |
parents | |
children |
line wrap: on
line source
#include <boost/spirit.hpp> #include <iostream> #include <string> #include <cassert> using namespace std; using namespace boost::spirit; // 入力データ用のイテレータ // 変更可能なようにtypedefしておく typedef file_iterator<> iterator_t; // エラー処理用のパーサー(関数オブジェクト) struct error_parser { typedef nil_t result_t; // パーサーの結果型(nil_t) error_parser(char const *msg) : msg_(msg) { } template <typename ScannerT> int operator()(ScannerT const &scan, result_t &result) const { // 終わりまで来たら-1を返す if (scan.at_end()) { return -1; } cout << msg_ << endl; // 解釈した「長さ」を返すと、その分スキップするので // 改行までをスキャンし、その分をスキップ return (int)(*(anychar_p - '\n') >> ch_p('\n')).parse(scan).length(); } private: const char *msg_; } ; // エラー処理用のパーサーを定義する typedef functor_parser<error_parser> error_p; // 文法エラー処理パーサー定義 error_p syntax_error_p = error_parser("文法エラー"); // 文法定義 struct calc_grammer: public grammar<calc_grammer> { template <typename ScannerT> struct definition { rule<ScannerT> identifier; rule<ScannerT> number; rule<ScannerT> prime; rule<ScannerT> unary; rule<ScannerT> mul_expr; rule<ScannerT> add_expr; rule<ScannerT> assign; rule<ScannerT> print; rule<ScannerT> list; rule<ScannerT> statement; rule<ScannerT> input; // 文法ルールの定義 definition(calc_grammer const& self) { // 識別子(変数名) identifier = lexeme_d[(alpha_p | '_') >> *(alnum_p | '_')]; // 数値 number = uint_p; // 最初の(素の)要素 prime = identifier | number | '(' >> add_expr >> ')' ; // 単項演算子 unary = prime | '-' >> prime ; // 乗除算 mul_expr = unary >> *('*' >> unary | '/' >> unary); // 加減算 add_expr = mul_expr >> *('+' >> mul_expr | '-' >> mul_expr); // 代入文 assign = identifier >> '=' >> add_expr >> ch_p('\n'); // printコマンド print = str_p("print") >> add_expr >> ch_p('\n'); // listコマンド list = str_p("list") >> ch_p('\n'); // 文 statement = assign | print | list ; // 入力とマッチするすべてのルール // 式 | 改行のみ(空文) | 文法エラー input = *(statement | ch_p('\n') | syntax_error_p); } // スタートルールの定義 rule<ScannerT> const& start() const { return input; } }; } ; // main int main(int argc, char *argv[]) { // ファイルの読み込みに、file_iteratorを使用する file_iterator<> first("input.txt"); if (!first) { cout << "ファイルがオープンできません。" << endl; return 1; } file_iterator<> last = first.make_end(); // 解析処理を行う // スキップパーサーは、' ', '\t', '\r'をスキップし // \nは(文末に利用するため)スキップしない calc_grammer gr; if (parse(first, last, gr, ch_p(' ') | ch_p('\t') | ch_p('\r')).full) { // 解析成功 cout << "構文解析終了" << endl; } else { // エラー処理が入っているので、エラー処理されるとここには来ない // エラー処理パーサーで、エラー処理を行ったら失敗としたほうが // 良い。 cout << "構文解析失敗" << endl; } return 0; }