%skeleton "lalr1.cc" %define "parser_class_name" "script_parser" %defines %{ #ifdef _MSC_VER #pragma warning(disable: 4800) #pragma warning(disable: 4267) #endif #include #include "node.h" class compiler; %} // The parsing context. %parse-param { compiler& driver } %lex-param { compiler& driver } %locations //%expect 7 %initial-action { // ロケーション初期化 @$.begin.filename = @$.end.filename = &driver.get_filename(); }; // %debug %error-verbose // Symbols. %union { int ival; std::string *sval; CArgs *args; CNode *expr; CAssign *assign; } %{ #include "compiler.h" %} %token END_OF_FILE 0 "end of file" %token TK_IVAL "ival" %token TK_IDENTIFIER "identifier" %token TK_EQ "==" %token TK_NE "!=" %token TK_GE ">=" %token TK_LE "<=" %token TK_NEWLINE "\n" %token TK_IF "if" %token TK_THEN "then" %token TK_ELSE "else" %token TK_ENDIF "endif" %token TK_FOR "for" %token TK_TO "to" %token TK_NEXT "next" %token TK_WHILE "while" %token TK_WEND "wend" %token TK_END "end" %token TK_RAND "rand" %token TK_PRINT "print" %type expr %type comp_expr %type value %type assign %type args %destructor { delete $$; } "identifier" %destructor { delete $$; } args %destructor { delete $$; } assign %destructor { delete $$; } value %destructor { delete $$; } expr %destructor { delete $$; } comp_expr %left '+' '-'; %left '*' '/' '%'; %left NEG; %% %start unit; unit : states | unit states ; states : statement "\n" | "\n" ; statement : "end" { driver.EndStatement(@1); } | assign { driver.AssignStatement(@1, $1); } | "if" comp_expr "then" { driver.IfStatement(@1, $2); } | "else" { driver.ElseStatement(@1); } | "endif" { driver.EndifStatement(@1); } | "for" assign "to" expr "step" expr { driver.ForStatement(@1, $2, $4, $6); } | "for" assign "to" expr { driver.ForStatement(@1, $2, $4, NULL); } | "next" { driver.NextStatement(@1); } | "while" comp_expr { driver.WhileStatement(@1, $2); } | "wend" { driver.WendStatement(@1); } | "print" args { driver.PrintStatement(@1, $2); } | error /* エラーの場合 */ ; assign : value '=' expr { $$ = new CAssign(@1, '=', $1, $3); } ; comp_expr : expr "==" expr { $$ = CNode::MakeNode(driver, @1, OP_EQ, $1, $3); } | expr "!=" expr { $$ = CNode::MakeNode(driver, @1, OP_NE, $1, $3); } | expr '>' expr { $$ = CNode::MakeNode(driver, @1, OP_GT, $1, $3); } | expr ">=" expr { $$ = CNode::MakeNode(driver, @1, OP_GE, $1, $3); } | expr '<' expr { $$ = CNode::MakeNode(driver, @1, OP_LT, $1, $3); } | expr "<=" expr { $$ = CNode::MakeNode(driver, @1, OP_LE, $1, $3); } ; expr : expr '-' expr { $$ = CNode::MakeNode(driver, @1, OP_MINUS, $1, $3); } | expr '+' expr { $$ = CNode::MakeNode(driver, @1, OP_PLUS, $1, $3); } | expr '*' expr { $$ = CNode::MakeNode(driver, @1, OP_TIMES, $1, $3); } | expr '/' expr { $$ = CNode::MakeNode(driver, @1, OP_DIVIDE, $1, $3); } | expr '%' expr { $$ = CNode::MakeNode(driver, @1, OP_MOD, $1, $3); } | '-' expr %prec NEG { $$ = CNode::MakeNode(driver, @1, OP_NEG, $2); } | '(' expr ')' { $$ = $2; } | value { $$ = $1; } | "ival" { $$ = new CNode(@1, OP_CONST, $1); } | "rand" '(' expr ')' { $$ = new CNode(@1, OP_RANDFUNC, $3); } ; value : "identifier" { $$ = new CValueNode(@1, $1); } ; args : expr { $$ = new CArgs(@1, $1); } | args ',' expr { $$ = $1->Add(@3, $3); } ; %% void yy::script_parser::error(const yy::script_parser::location_type& l, const std::string& m) { driver.error(l, m); }