Mercurial > hg > Members > nobuyasu > SampleSource
diff boost-spirit/Compiler-boost-spirit/parser.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 diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/boost-spirit/Compiler-boost-spirit/parser.cpp Mon May 09 03:11:59 2011 +0900 @@ -0,0 +1,573 @@ +// +// boost::spiritによる、C言語風構文パーサー +// +// 2008/06/05 Chihiro.SAKAMOTO +// Copyright Chihiro.SAKAMOTO +// +#include "stdafx.h" +#include "compiler.h" +#include "node.h" + +using namespace std; +using namespace boost::spirit; + +// 入力用のイテレータを定義 +typedef position_iterator<string::const_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; + } + + // 改行までをスキャンし、そこまでを表示する。 + + iterator_t b = scan.first; + size_t length = (*(anychar_p - '\n')).parse(scan).length(); + file_position fpos = scan.first.get_position(); + cout << fpos.file << ": " << fpos.line << "." << fpos.column << ": " + << msg_ << " : " << string(b, scan.first) << endl; + + // spiritのバックトラックの影響を受けるので、エラー処理は + // 細かく入れる必要が生じる + // そうしないと、大量のエラーに埋没する + // ここでは、エラー1つで中断している。 +// return (int)length + 1; + return -1; + } + + private: + const char *msg_; +} ; + +// エラー処理パーサー +typedef functor_parser<error_parser> error_p; + +// 文法エラー処理パーサー +error_p syntax_error_p = error_parser("文法エラー"); + +// 単項演算子ノードを生成する +struct unary_node_impl { + template <typename Ty1, typename Ty2> + struct result { typedef cnode_t type; } ; + + template <typename Ty1, typename Ty2> + cnode_t operator()(Ty1 op, const Ty2 &left) const + { + return cnode::make_node(op, left); + } +} ; + +// 二項演算子ノードを生成する +struct binary_node_impl { + template <typename Ty1, typename Ty2, typename Ty3> + struct result { typedef cnode_t type; } ; + + template <typename Ty1, typename Ty2, typename Ty3> + cnode_t operator()(Ty1 op, const Ty2 &left, const Ty3 &right) const + { + return cnode::make_node(op, left, right); + } +} ; + +// 値を追加 +struct push_back_impl { + template <typename Ty1, typename Ty2> + struct result { typedef Ty1 type; } ; + + template <typename Ty1, typename Ty2> + Ty1 operator()(Ty1 &list, const Ty2 &node) const + { + list->add(node); + return list; + } +} ; + +// ノードリストを生成する +struct make_argument_impl { + template <typename Ty> + struct result { typedef cnode_list_t type; } ; + + template <typename Ty> + cnode_list_t operator()(const Ty &node) const + { + return cnode_list_t(new cnode_list(node)); + } +} ; + +// ステートメントの生成 +struct make_statement_impl { + template <typename Ty> + struct result { typedef cstatement_t type; } ; + + template <typename Ty> + cstatement_t operator()(Ty state) const + { + return cstatement::make_statement(state); + } +} ; + +// ステートメントの生成 +struct make_statement1_impl { + template <typename Ty1, typename Ty2> + struct result { typedef cstatement_t type; } ; + + template <typename Ty1, typename Ty2> + cstatement_t operator()(Ty1 state, const Ty2 &node) const + { + return cstatement::make_statement(state, node); + } +} ; + +// ステートメントにインデックス付きで値を追加 +struct add_statement_impl { + template <typename Ty1, typename Ty2, typename Ty3> + struct result { typedef cstatement_t type; } ; + + template <typename Ty1, typename Ty2, typename Ty3> + cstatement_t operator()(Ty1 &statement, Ty2 index, const Ty3 &node) const + { + statement->add(index, node); + return statement; + } +} ; + +// 宣言の生成 +struct make_decl_impl { + template <typename Ty> + struct result { typedef cdeclaration_t type; } ; + + template <typename Ty> + cdeclaration_t operator()(Ty type) const + { + return cdeclaration_t(new cdeclaration(type)); + } +} ; + +// 宣言の生成 +struct make_decl1_impl { + template <typename Ty1, typename Ty2> + struct result { typedef cdeclaration_t type; } ; + + template <typename Ty1, typename Ty2> + cdeclaration_t operator()(Ty1 type, const Ty2 &node) const + { + return cdeclaration_t(new cdeclaration(type, node)); + } +} ; + +// 引数宣言の型を参照にする +struct arg_ref_impl { + template <typename Ty1> + struct result { typedef cargdef type; } ; + + template <typename Ty1> + cargdef operator()(Ty1 &decl) const + { + decl.set_ref(); + return decl; + } +} ; + +// 引数の名前を設定 +struct arg_name_impl { + template <typename Ty1, typename Ty2> + struct result { typedef cargdef type; } ; + + template <typename Ty1, typename Ty2> + cargdef operator()(Ty1 &decl, const Ty2 &name) const + { + decl.set_name(name); + return decl; + } +} ; + +// 関数の生成 +struct make_function_impl { + template <typename Ty1, typename Ty2> + struct result { typedef cfunction_t type; } ; + + template <typename Ty1, typename Ty2> + cfunction_t operator()(Ty1 type, const Ty2 &name) const + { + return cfunction_t(new cfunction(type, name)); + } +} ; + +// 最終登録 +struct analyze_impl { + template <typename Ty1, typename Ty2> + struct result { typedef void type; } ; + + template <typename Ty1, typename Ty2> + void operator()(const Ty1 &decl, Ty2 driver) const + { + decl->analyze(driver); + } +} ; + +// phoenixが使用する「無名関数」用の関数 +phoenix::function<binary_node_impl> const binary_node = binary_node_impl(); +phoenix::function<unary_node_impl> const unary_node = unary_node_impl(); +phoenix::function<push_back_impl> const push_back = push_back_impl(); +phoenix::function<make_argument_impl> const make_argument = make_argument_impl(); +phoenix::function<make_statement_impl> const make_statement = make_statement_impl(); +phoenix::function<make_statement1_impl> const make_statement1 = make_statement1_impl(); +phoenix::function<add_statement_impl> const add_statement = add_statement_impl(); +phoenix::function<make_decl_impl> const make_decl = make_decl_impl(); +phoenix::function<make_decl1_impl> const make_decl1 = make_decl1_impl(); +phoenix::function<arg_ref_impl> const arg_ref = arg_ref_impl(); +phoenix::function<arg_name_impl> const arg_name = arg_name_impl(); +phoenix::function<make_function_impl> const make_function = make_function_impl(); +phoenix::function<analyze_impl> const analyze = analyze_impl(); + +// 文法定義 +struct script_grammer: public grammar<script_grammer> { + script_grammer(compiler *driver) + :driver_(driver) + { + } + + compiler *driver_; // コンパイラ + + // 文字列のクロージャ + struct string_val: closure<string_val, std::string> { + member1 str; + } ; + // 数字のクロージャ + struct number_val: closure<number_val, unsigned int> { + member1 number; + } ; + // ノードのクロージャ + struct node_val: closure<node_val, cnode_t, int> { + member1 node; + member2 op; + } ; + // ノードのクロージャ + struct nodelist_val: closure<nodelist_val, cnode_list_t, int> { + member1 node; + member2 op; + } ; + // 文のクロージャ + struct state_val: closure<state_val, cstatement_t> { + member1 statement; + } ; + // 型のクロージャ + struct type_val: closure<type_val, int> { + member1 type; + } ; + + // 変数定義のクロージャ + struct decl_val: closure<decl_val, cdeclaration_t, int> { + member1 node; + member2 type; + } ; + + // 関数定義のクロージャ + struct func_val: closure<func_val, cfunction_t, int> { + member1 node; + member2 type; + } ; + + // 引数定義のクロージャ + struct argdef_val: closure<argdef_val, cargdef> { + member1 node; + } ; + + // 文ブロックのクロージャ + struct block_val: closure<block_val, cblock_t> { + member1 node; + } ; + + template <typename ScannerT> + struct definition { + rule<ScannerT, string_val::context_t> identifier; + rule<ScannerT, string_val::context_t> string_node; + rule<ScannerT, number_val::context_t> number; + rule<ScannerT, type_val::context_t> type; + rule<ScannerT, node_val::context_t> func_node; + rule<ScannerT, node_val::context_t> value; + rule<ScannerT, node_val::context_t> prime; + rule<ScannerT, node_val::context_t> unary; + rule<ScannerT, node_val::context_t> mul_expr; + rule<ScannerT, node_val::context_t> add_expr; + rule<ScannerT, node_val::context_t> shift_expr; + rule<ScannerT, node_val::context_t> bit_expr; + rule<ScannerT, node_val::context_t> equ_expr; + rule<ScannerT, node_val::context_t> and_expr; + rule<ScannerT, node_val::context_t> expr; + rule<ScannerT, node_val::context_t> assign; + rule<ScannerT, nodelist_val::context_t> argument; + rule<ScannerT, state_val::context_t> statement; + rule<ScannerT, func_val::context_t> function; + rule<ScannerT, type_val::context_t> arg; + rule<ScannerT, decl_val::context_t> decl_value; + rule<ScannerT, decl_val::context_t> decl_func; + rule<ScannerT, argdef_val::context_t> argdef; + rule<ScannerT, block_val::context_t> block; + rule<ScannerT> input; + rule<ScannerT> ident; + + symbols<> keywords; + symbols<> mul_op, add_op, shift_op, bit_op, equ_op, assign_op; + dynamic_distinct_parser<ScannerT> keyword_p; + + definition(script_grammer const& self) + :keyword_p(alnum_p | '_') + { + using phoenix::arg1; + using phoenix::arg2; + using phoenix::var; + using phoenix::new_; + using phoenix::construct_; + + keywords = "if", "for", "while", "switch", "case", "default", "break", "return"; + // 識別子 + ident = lexeme_d[ + ((alpha_p | '_') >> *(alnum_p | '_')) - (keywords >> anychar_p - (alnum_p | '_')) + ]; + // 識別子(クロージャに登録) + identifier = ident[identifier.str = construct_<string>(arg1, arg2)]; + // 数値 + number = uint_p[number.number = arg1]; + // 文字列 + string_node = lexeme_d[ + confix_p(ch_p('"')[string_node.str = ""], *c_escape_ch_p[string_node.str += arg1], '"') + ]; + + // 変数 + value = identifier[value.node = unary_node(OP_IDENTIFIER, arg1)] + >> !('[' >> expr[value.node = binary_node(OP_ARRAY, value.node, arg1)] >> ']'); + + // 関数の引数 + argument = expr[argument.node = make_argument(arg1)] + >> *(',' >> expr[argument.node = push_back(argument.node, arg1)]); + + // 関数呼び出し + func_node = identifier[func_node.node = unary_node(OP_FUNCTION, arg1)] >> + '(' >> !argument[func_node.node = binary_node(OP_FUNCTION, func_node.node, arg1)] >> ')'; + + // 計算のprimeノード + prime = func_node[prime.node = arg1] + | value[prime.node = arg1] + | number[prime.node = unary_node(OP_NUMBER, arg1)] + | string_node[prime.node = unary_node(OP_STRING, arg1)] + | '(' >> expr[prime.node = arg1] >> ')' + ; + + // 単項演算子 + unary = prime[unary.node = arg1] + | '-' >> prime[unary.node = unary_node(OP_NEG, arg1)]; + + // 二項演算子(*, /, %) + mul_op.add("*", OP_MUL)("/", OP_DIV)("%", OP_MOD); + mul_expr = unary[mul_expr.node = arg1] + >> *(mul_op[mul_expr.op = arg1] + >> unary[mul_expr.node = binary_node(mul_expr.op, mul_expr.node, arg1)]); + + // 二項演算子(+, -) + add_op.add("+", OP_ADD)("-", OP_SUB); + add_expr = mul_expr[add_expr.node = arg1] + >> *(add_op[add_expr.op = arg1] + >> mul_expr[add_expr.node = binary_node(add_expr.op, add_expr.node, arg1)]); + + // 二項演算子(<<, >>) + shift_op.add("<<", OP_LSHIFT)(">>", OP_RSHIFT); + shift_expr = add_expr[shift_expr.node = arg1] + >> *(shift_op[shift_expr.op = arg1] + >> add_expr[shift_expr.node = binary_node(shift_expr.op, shift_expr.node, arg1)]); + + // 二項演算子(&, |) + bit_op.add("&", OP_AND)("|", OP_OR); + bit_expr = shift_expr[bit_expr.node = arg1] + >> *(bit_op[bit_expr.op = arg1] + >> shift_expr[bit_expr.node = binary_node(bit_expr.op, bit_expr.node, arg1)]); + + // 二項演算子(比較) + equ_op.add("==", OP_EQ)("!=", OP_NE)(">=", OP_GE)(">", OP_GT)("<=", OP_LE)("<", OP_LT); + equ_expr = bit_expr[equ_expr.node = arg1] + >> !(equ_op[equ_expr.op = arg1] + >> bit_expr[equ_expr.node = binary_node(equ_expr.op, equ_expr.node, arg1)]); + + // 二項演算子(&&) + and_expr = equ_expr[and_expr.node = arg1] + >> *("&&" >> equ_expr[and_expr.node = binary_node(OP_LOGAND, and_expr.node, arg1)]); + + // 二項演算子(||) + expr = and_expr[expr.node = arg1] + >> *("||" >> and_expr[expr.node = binary_node(OP_LOGOR, expr.node, arg1)]); + + // 代入 + assign_op.add + ("=", OP_ASSIGN) + ("+=", OP_ADD_ASSIGN) + ("-=", OP_SUB_ASSIGN) + ("*=", OP_MUL_ASSIGN) + ("/=", OP_DIV_ASSIGN) + ("%=", OP_MOD_ASSIGN) + ("&=", OP_AND_ASSIGN) + ("|=", OP_OR_ASSIGN) + ("<<=", OP_LSHIFT_ASSIGN) + (">>=", OP_RSHIFT_ASSIGN); + assign = value[assign.node = arg1] + >> assign_op[assign.op = arg1] + >> expr[assign.node = binary_node(assign.op, assign.node, arg1)]; + + // 型宣言 + type = keyword_p("int")[type.type = TYPE_INTEGER] >> !ch_p('&')[type.type |= TYPE_REF] + | keyword_p("string")[type.type = TYPE_STRING] >> !ch_p('&')[type.type |= TYPE_REF] + | keyword_p("void")[type.type = TYPE_VOID] + ; + + // 関数宣言の引数 + arg = type[arg.type = arg1] + >> !identifier + >> !str_p("[]")[arg.type |= TYPE_REF]; + + // 変数宣言 + decl_value = type[decl_value.node = make_decl(arg1)] + >> value[decl_value.node = push_back(decl_value.node, arg1)] % ',' >> ';'; + // 関数宣言 + decl_func = type[decl_func.type = arg1] + >> identifier[decl_func.node = make_decl1(decl_func.type, arg1)] + >> '(' >> !(arg[decl_func.node = push_back(decl_func.node, arg1)] % ',') >> ')' >> ';'; + + // 関数定義の引数 + argdef = type[argdef.node = construct_<cargdef>(arg1)] + >> !identifier[argdef.node = arg_name(argdef.node, arg1)] + >> !str_p("[]")[argdef.node = arg_ref(argdef.node)]; + + // 関数定義 + function = type[function.type = arg1] + >> identifier[function.node = make_function(function.type, arg1)] + >> '(' >> !(argdef[function.node = push_back(function.node, arg1)] % ',') >> ')' + >> block[function.node = push_back(function.node, arg1)]; + + // 文ブロック + block = ch_p('{')[block.node = construct_<cblock_t>(new_<cblock>())] + >> *decl_value[block.node = push_back(block.node, arg1)] + >> *statement[block.node = push_back(block.node, arg1)] + >> '}'; + + // 文 + statement = ch_p(';')[statement.statement = make_statement(NOP_STATE)] + | assign[statement.statement = make_statement1(ASSIGN_STATE, arg1)] >> ';' + | str_p("case") >> expr[statement.statement = make_statement1(CASE_STATE, arg1)] >> ':' + | str_p("default")[statement.statement = make_statement(DEFAULT_STATE)] >> ':' + | str_p("break")[statement.statement = make_statement(BREAK_STATE)] >> ';' + | str_p("return")[statement.statement = make_statement(RETURN_STATE)] + >> !expr[statement.statement = push_back(statement.statement, arg1)] >> ';' + | str_p("if")[statement.statement= make_statement(IF_STATE)] + >> '(' >> expr[statement.statement = push_back(statement.statement, arg1)] >> ')' + >> statement[statement.statement = add_statement(statement.statement, 0, arg1)] + >> !("else" + >> statement[statement.statement = add_statement(statement.statement, 1, arg1)]) + | str_p("for")[statement.statement = make_statement(FOR_STATE)] >> '(' + >> assign[statement.statement = add_statement(statement.statement, 0, arg1)] >> ';' + >> expr[statement.statement = add_statement(statement.statement, 1, arg1)] >> ';' + >> assign[statement.statement = add_statement(statement.statement, 2, arg1)] >> ')' + >> statement[statement.statement = push_back(statement.statement, arg1)] + | str_p("while")[statement.statement = make_statement(WHILE_STATE)] >> '(' + >> expr[statement.statement = push_back(statement.statement, arg1)] >> ')' + >> statement[statement.statement = push_back(statement.statement, arg1)] + | str_p("switch") >> '(' + >> expr[statement.statement = make_statement1(SWITCH_STATE, arg1)] >> ')' + >> '{' + >> *statement[statement.statement = push_back(statement.statement, arg1)] + >> '}' + | func_node[statement.statement = make_statement1(CALL_STATE, arg1)] >> ';' + | block[statement.statement = make_statement1(BLOCK_STATE, arg1)] + ; + + // 入力された構文 + input = *(decl_value[analyze(arg1, self.driver_)] + | decl_func[analyze(arg1, self.driver_)] + | function[analyze(arg1, self.driver_)] + | syntax_error_p + ); + } + + rule<ScannerT> const& start() const + { + return input; + } + } ; +} ; + +// スキップイテレーター +// コメントのスキップを加える +struct skip_parser: public grammar<skip_parser> { + template <typename ScannerT> + struct definition { + rule<ScannerT> skip_p; + + definition(skip_parser const& self) + { + skip_p = space_p + | comment_p("//") // C++コメント用 + | comment_p("/*", "*/") // Cコメント用 + ; + } + rule<ScannerT> const& start() const + { + return skip_p; + } + } ; +} ; + +// 全部スキップしてみて、エンドまで来たか? +template <typename IteratorT, typename DerivedT> +bool skip_all(IteratorT first, IteratorT last, parser<DerivedT> const &p) +{ + for (;;) { + parse_info<IteratorT> info = parse(first, last, p); + if (info.full) + return true; + if (!info.hit) + return false; + first = info.stop; + } +} + +// 構文解析 +bool script_parser(const string &path, compiler *driver) +{ + ifstream fin(path.c_str()); + + if (!fin) { + driver->error("ファイル" + path + "がオープンできません。"); + return false; + } + + // ファイルを一度メモリーに読み込む + istreambuf_iterator<char> fbegin(fin); + istreambuf_iterator<char> fend; + string input(fbegin, fend); + + // ポジションイテレータ + iterator_t begin(input.begin(), input.end(), path); + iterator_t end; + begin.set_tabchars(4); // tab=4に設定 + + script_grammer gr(driver); + skip_parser skip_p; + parse_info<iterator_t> info = parse(begin, end, gr, skip_p); + if (info.hit && (info.full || skip_all(info.stop, end, skip_p))) { + return true; + } + + driver->error("構文解析失敗"); + + return false; +}