Mercurial > hg > Members > nobuyasu > SampleSource
diff Bison-Flex/Compiler-StackBase/EUC/script-parser.yy @ 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/Bison-Flex/Compiler-StackBase/EUC/script-parser.yy Mon May 09 03:11:59 2011 +0900 @@ -0,0 +1,243 @@ +%skeleton "lalr1.cc" +%define "parser_class_name" "script_parser" +%defines +%{ +#ifdef _MSC_VER +#pragma warning(disable: 4800) +#pragma warning(disable: 4267) +#endif + +#include <string> +#include "node.h" +class compiler; +%} +%parse-param { compiler& driver } +%lex-param { compiler& driver } +%locations +%expect 1 /* if文で衝突が発生するので、1つの衝突は無視 */ +%initial-action +{ + // ロケーション初期化 + @$.begin.filename = @$.end.filename = &driver.get_filename(); +} ; +// %debug +%error-verbose +// Symbols. +%union +{ + int ival; + std::string *sval; + + int type; + CValueList *value_list; + CArgList *arglist; + CDeclList *decls; + CStateList *states; + CStatement *statement; + CArgDef *argdef; + CArgs *args; + CValueNode *value; + CNode *expr; + CAssign *assign; + CStateBlock *block; +} +%{ +#include "compiler.h" +%} + +%token END_OF_FILE 0 "end of file" +%token <ival> TK_IVAL "ival" +%token <sval> TK_IDENTIFIER "identifier" +%token <sval> TK_SVAL "sval" +%token TK_LOGOR "||" +%token TK_LOGAND "&&" +%token TK_EQ "==" +%token TK_NE "!=" +%token TK_GE ">=" +%token TK_LE "<=" +%token TK_LSHIFT "<<" +%token TK_RSHIFT ">>" +%token TK_ADD_ASSIGN "+=" +%token TK_SUB_ASSIGN "-=" +%token TK_MUL_ASSIGN "*=" +%token TK_DIV_ASSIGN "/=" +%token TK_MOD_ASSIGN "%=" + +%token TK_IF "if" +%token TK_ELSE "else" +%token TK_WHILE "while" +%token TK_FOR "for" +%token TK_SWITCH "switch" +%token TK_CASE "case" +%token TK_DEFAULT "default" +%token TK_BREAK "break" +%token TK_RETURN "return" +%token TK_INTEGER "int" +%token TK_STRING "string" +%token TK_VOID "void" + +%type <expr> expr +%type <value> value +%type <assign> assign +%type <value_list> value_list +%type <arglist> arglist +%type <argdef> arg +%type <decls> decls decl_list +%type <states> states state_list +%type <block> block +%type <args> args +%type <statement> statement +%type <type> type + +%destructor { delete $$; } "identifier" +%destructor { delete $$; } "sval" + +%destructor { delete $$; } value_list +%destructor { delete $$; } arglist +%destructor { delete $$; } arg +%destructor { delete $$; } decls decl_list +%destructor { delete $$; } states state_list +%destructor { delete $$; } args +%destructor { delete $$; } block +%destructor { delete $$; } assign +%destructor { delete $$; } statement +%destructor { delete $$; } value +%destructor { delete $$; } expr + +%left "||"; +%left "&&"; +%nonassoc "==" "!=" '>' '<' ">=" "<="; +%left '&' '|'; +%left "<<" ">>"; +%left '+' '-'; +%left '*' '/' '%'; +%left NEG; +%% +%start unit; + +unit : define_or_state + | unit define_or_state + ; + +define_or_state : error ';' + | function + | declaration + ; + +declaration : type value_list ';' { driver.DefineValue(@2, $1, $2); } + | type "identifier" '(' ')' ';' { driver.DefineFunction(@2, $1, $2, NULL); } + | type "identifier" '(' arglist ')' ';' { driver.DefineFunction(@2, $1, $2, $4); } + | "void" "identifier" '(' ')' ';' { driver.DefineFunction(@2, TYPE_VOID, $2, NULL); } + | "void" "identifier" '(' arglist ')' ';' { driver.DefineFunction(@2, TYPE_VOID, $2, $4); } + ; + +value_list : value { $$ = new CValueList($1); } + | value_list ',' value { $$ = $1->Add($3); } + ; + +arglist : arg { $$ = new CArgList($1); } + | arglist ',' arg { $$ = $1->Add($3); } + ; + +arg : type { $$ = new CArgDef(@1, $1, NULL); } + | type '&' { $$ = new CArgDef(@1, TypeToRef($1), NULL); } + | type "identifier" { $$ = new CArgDef(@1, $1, $2); } + | type '&' "identifier" { $$ = new CArgDef(@1, TypeToRef($1), $3); } + | type "identifier" '[' ']' { $$ = new CArgDef(@1, TypeToRef($1), $2); } + | type '&' "identifier" '[' ']' { $$ = new CArgDef(@1, TypeToRef($1), $3); } + ; + +function : type "identifier" '(' ')' block { driver.AddFunction(@1, $1, $2, NULL, $5); } + | type "identifier" '(' arglist ')' block { driver.AddFunction(@1, $1, $2, $4, $6); } + | "void" "identifier" '(' ')' block { driver.AddFunction(@1, TYPE_VOID, $2, NULL, $5); } + | "void" "identifier" '(' arglist ')' block { driver.AddFunction(@1, TYPE_VOID, $2, $4, $6); } + ; + +type : "int" { $$ = TYPE_INTEGER; } + | "string" { $$ = TYPE_STRING; } + ; + +block : '{' decl_list state_list '}' { $$ = new CStateBlock($2, $3); } + ; + +decl_list : { $$ = NULL } + | decls { $$ = $1 } + ; + +state_list : { $$ = NULL } + | states { $$ = $1 } + ; + +decls : type value_list ';' { $$ = new CDeclList(new CDecl($1, $2)); } + | decls type value_list ';' { $$ = $1->Add(new CDecl($2, $3)); } + ; + +states : statement { $$ = new CStateList($1); } + | states statement { $$ = $1->Add($2); } + ; + +statement : ';' { $$ = new CNopStatement(@1); } + | assign ';' { $$ = new CAssignStatement(@1, $1); } + | "identifier" '(' args ')' ';' { $$ = new CFunctionStatement(@1, $1, $3); } + | "identifier" '(' ')' ';' { $$ = new CFunctionStatement(@1, $1, NULL); } + | "case" expr ':' { $$ = new CCaseStatement(@1, $2); } + | "default" ':' { $$ = new CDefaultStatement(@1); } + | "break" ';' { $$ = new CBreakStatement(@1); } + | "return" ';' { $$ = new CReturnStatement(@1, NULL); } + | "return" expr ';' { $$ = new CReturnStatement(@1, $2); } + | "if" '(' expr ')' statement { $$ = new CIfStatement(@1, $3, $5); } + | "if" '(' expr ')' statement "else" statement { $$ = new CIfStatement(@1, $3, $5, $7); } + | "for" '(' assign ';' expr ';' assign ')' statement + { $$ = new CForStatement(@1, $3, $5, $7, $9); } + | "while" '(' expr ')' statement { $$ = new CWhileStatement(@1, $3, $5); } + | "switch" '(' expr ')' '{' state_list '}' { $$ = new CSwitchStatement(@1, $3, $6); } + | block { $$ = new CBlockStatement(@1, $1); } + ; + +assign : value '=' expr { $$ = new CAssign(@1, '=', $1, $3); } + | value "+=" expr { $$ = new CAssign(@1, '+', $1, $3); } + | value "-=" expr { $$ = new CAssign(@1, '-', $1, $3); } + | value "*=" expr { $$ = new CAssign(@1, '*', $1, $3); } + | value "/=" expr { $$ = new CAssign(@1, '/', $1, $3); } + | value "%=" expr { $$ = new CAssign(@1, '%', $1, $3); } + ; + +expr : expr "&&" expr { $$ = CNode::MakeNode(driver, @2, OP_LOGAND, $1, $3); } + | expr "||" expr { $$ = CNode::MakeNode(driver, @2, OP_LOGOR, $1, $3); } + | expr "==" expr { $$ = CNode::MakeNode(driver, @2, OP_EQ, $1, $3); } + | expr "!=" expr { $$ = CNode::MakeNode(driver, @2, OP_NE, $1, $3); } + | expr '>' expr { $$ = CNode::MakeNode(driver, @2, OP_GT, $1, $3); } + | expr ">=" expr { $$ = CNode::MakeNode(driver, @2, OP_GE, $1, $3); } + | expr '<' expr { $$ = CNode::MakeNode(driver, @2, OP_LT, $1, $3); } + | expr "<=" expr { $$ = CNode::MakeNode(driver, @2, OP_LE, $1, $3); } + | expr '&' expr { $$ = CNode::MakeNode(driver, @2, OP_AND, $1, $3); } + | expr '|' expr { $$ = CNode::MakeNode(driver, @2, OP_OR, $1, $3); } + | expr "<<" expr { $$ = CNode::MakeNode(driver, @2, OP_LSHIFT, $1, $3); } + | expr ">>" expr { $$ = CNode::MakeNode(driver, @2, OP_RSHIFT, $1, $3); } + | expr '-' expr { $$ = CNode::MakeNode(driver, @2, OP_MINUS, $1, $3); } + | expr '+' expr { $$ = CNode::MakeNode(driver, @2, OP_PLUS, $1, $3); } + | expr '*' expr { $$ = CNode::MakeNode(driver, @2, OP_TIMES, $1, $3); } + | expr '/' expr { $$ = CNode::MakeNode(driver, @2, OP_DIVIDE, $1, $3); } + | expr '%' expr { $$ = CNode::MakeNode(driver, @2, OP_MOD, $1, $3); } + | '-' expr %prec NEG { $$ = CNode::MakeNode(driver, @2, OP_NEG, $2); } + | '(' expr ')' { $$ = $2; } + | value { $$ = $1; } + | "ival" { $$ = new CNode(@1, OP_CONST, $1); } + | "sval" { $$ = new CNode(@1, OP_STRING, $1); } + | "identifier" '(' args ')' { $$ = new CFunctionNode(@1, $1, $3); } + | "identifier" '(' ')' { $$ = new CFunctionNode(@1, $1, NULL); } + ; + +value : "identifier" { $$ = new CValueNode(@1, $1); } + | "identifier" '[' expr ']' { $$ = new CValueNode(@1, $1, $3); } + ; + +args : expr { $$ = new CArgs($1); } + | args ',' expr { $$ = $1->Add($3); } + ; + +%% +void yy::script_parser::error(const yy::script_parser::location_type& l, const std::string& m) +{ + driver.error(l, m); +}