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;
+}