%{ // Make sure we don't get gram.h twice. #define _CMDGRAM_H_ #include #include #include "console/console.h" #include "console/compiler.h" #include "console/consoleInternal.h" #ifndef YYDEBUG #define YYDEBUG 0 #endif #define YYSSIZE 350 int outtext(char *fmt, ...); extern int serrors; #define nil 0 #undef YY_ARGS #define YY_ARGS(x) x int CMDlex(); void CMDerror(char *, ...); #define alloca dMalloc %} %{ /* Reserved Word Definitions */ %} %token rwDEFINE rwENDDEF rwDECLARE %token rwBREAK rwELSE rwCONTINUE rwGLOBAL %token rwIF rwNIL rwRETURN rwWHILE rwDO %token rwENDIF rwENDWHILE rwENDFOR rwDEFAULT %token rwFOR rwDATABLOCK rwSWITCH rwCASE rwSWITCHSTR %token rwCASEOR rwPACKAGE rwNAMESPACE rwCLASS %token ILLEGAL_TOKEN %{ /* Constants and Identifier Definitions */ %} %token CHRCONST %token INTCONST %token TTAG %token VAR %token IDENT %token STRATOM %token TAGATOM %token FLTCONST %{ /* Operator Definitions */ %} %token '+' '-' '*' '/' '<' '>' '=' '.' '|' '&' '%' %token '(' ')' ',' ':' ';' '{' '}' '^' '~' '!' '@' %token opMINUSMINUS opPLUSPLUS %token STMT_SEP %token opSHL opSHR opPLASN opMIASN opMLASN opDVASN opMODASN opANDASN %token opXORASN opORASN opSLASN opSRASN opCAT %token opEQ opNE opGE opLE opAND opOR opSTREQ %token opCOLONCOLON %union { char c; int i; const char * s; char * str; double f; StmtNode * stmt; ExprNode * expr; SlotAssignNode * slist; VarNode * var; SlotDecl slot; ObjectBlockDecl odcl; ObjectDeclNode * od; AssignDecl asn; IfStmtNode * ifnode; } %type parent_block %type case_block %type switch_stmt %type decl %type decl_list %type package_decl %type fn_decl_stmt %type fn_decl_list %type statement_list %type stmt %type expr_list %type expr_list_decl %type aidx_expr %type funcall_expr %type object_name %type object_args %type stmt_expr %type case_expr %type class_name_expr %type if_stmt %type while_stmt %type for_stmt %type stmt_block %type datablock_decl %type object_decl %type object_decl_list %type object_declare_block %type expr %type slot_assign_list %type slot_assign %type slot_acc %type expression_stmt %type var_list %type var_list_decl %type assign_op_struct %left '[' %right opMODASN opANDASN opXORASN opPLASN opMIASN opMLASN opDVASN opMDASN opNDASN opNTASN opORASN opSLASN opSRASN '=' %left '?' ':' %left opOR %left opAND %left '|' %left '^' %left '&' %left opEQ opNE %left '<' opLE '>' opGE %left '@' opCAT opSTREQ opSTRNE %left opSHL opSHR %left '+' '-' %left '*' '/' '%' %right '!' '~' opPLUSPLUS opMINUSMINUS UNARY %left '.' %% start : decl_list { } ; decl_list : { $$ = nil; } | decl_list decl { if(!statementList) { statementList = $2; } else { statementList->append($2); } } ; decl : stmt { $$ = $1; } | fn_decl_stmt { $$ = $1; } | package_decl { $$ = $1; } ; package_decl : rwPACKAGE IDENT '{' fn_decl_list '}' ';' { $$ = $4; for(StmtNode *walk = ($4);walk;walk = walk->getNext() ) walk->setPackage($2); } ; fn_decl_list : fn_decl_stmt { $$ = $1; } | fn_decl_list fn_decl_stmt { $$ = $1; ($1)->append($2); } ; statement_list : { $$ = nil; } | statement_list stmt { if(!$1) { $$ = $2; } else { ($1)->append($2); $$ = $1; } } ; stmt : if_stmt | while_stmt | for_stmt | datablock_decl | switch_stmt | rwBREAK ';' { $$ = BreakStmtNode::alloc(); } | rwCONTINUE ';' { $$ = ContinueStmtNode::alloc(); } | rwRETURN ';' { $$ = ReturnStmtNode::alloc(NULL); } | rwRETURN expr ';' { $$ = ReturnStmtNode::alloc($2); } | expression_stmt ';' { $$ = $1; } | TTAG '=' expr ';' { $$ = TTagSetStmtNode::alloc($1, $3, NULL); } | TTAG '=' expr ',' expr ';' { $$ = TTagSetStmtNode::alloc($1, $3, $5); } ; fn_decl_stmt : rwDEFINE IDENT '(' var_list_decl ')' '{' statement_list '}' { $$ = FunctionDeclStmtNode::alloc($2, NULL, $4, $7); } | rwDEFINE IDENT opCOLONCOLON IDENT '(' var_list_decl ')' '{' statement_list '}' { $$ = FunctionDeclStmtNode::alloc($4, $2, $6, $9); } ; var_list_decl : { $$ = NULL; } | var_list { $$ = $1; } ; var_list : VAR { $$ = VarNode::alloc($1, NULL); } | var_list ',' VAR { $$ = $1; ((StmtNode*)($1))->append((StmtNode*)VarNode::alloc($3, NULL)); } ; datablock_decl : rwDATABLOCK IDENT '(' IDENT parent_block ')' '{' slot_assign_list '}' ';' { $$ = ObjectDeclNode::alloc(ConstantNode::alloc($2), ConstantNode::alloc($4), NULL, $5, $8, NULL, true); } ; object_decl : rwDECLARE class_name_expr '(' object_name parent_block object_args ')' '{' object_declare_block '}' { $$ = ObjectDeclNode::alloc($2, $4, $6, $5, $9.slots, $9.decls, false); } | rwDECLARE class_name_expr '(' object_name parent_block object_args ')' { $$ = ObjectDeclNode::alloc($2, $4, $6, $5, NULL, NULL, false); } ; parent_block : { $$ = NULL; } | ':' IDENT { $$ = $2; } ; object_name : { $$ = StrConstNode::alloc("", false); } | expr { $$ = $1; } ; object_args : { $$ = NULL; } | ',' expr_list { $$ = $2; } ; object_declare_block : { $$.slots = NULL; $$.decls = NULL; } | slot_assign_list { $$.slots = $1; $$.decls = NULL; } | object_decl_list { $$.slots = NULL; $$.decls = $1; } | slot_assign_list object_decl_list { $$.slots = $1; $$.decls = $2; } ; object_decl_list : object_decl ';' { $$ = $1; } | object_decl_list object_decl ';' { $1->append($2); $$ = $1; } ; stmt_block : '{' statement_list '}' { $$ = $2; } | stmt { $$ = $1; } ; switch_stmt : rwSWITCH '(' expr ')' '{' case_block '}' { $$ = $6; $6->propagateSwitchExpr($3, false); } | rwSWITCHSTR '(' expr ')' '{' case_block '}' { $$ = $6; $6->propagateSwitchExpr($3, true); } ; case_block : rwCASE case_expr ':' statement_list { $$ = IfStmtNode::alloc($1, $2, $4, NULL, false); } | rwCASE case_expr ':' statement_list rwDEFAULT ':' statement_list { $$ = IfStmtNode::alloc($1, $2, $4, $7, false); } | rwCASE case_expr ':' statement_list case_block { $$ = IfStmtNode::alloc($1, $2, $4, $5, true); } ; case_expr : expr { $$ = $1;} | case_expr rwCASEOR expr { ($1)->append($3); $$=$1; } ; if_stmt : rwIF '(' expr ')' stmt_block { $$ = IfStmtNode::alloc($1, $3, $5, NULL, false); } | rwIF '(' expr ')' stmt_block rwELSE stmt_block { $$ = IfStmtNode::alloc($1, $3, $5, $7, false); } ; while_stmt : rwWHILE '(' expr ')' stmt_block { $$ = LoopStmtNode::alloc($1, nil, $3, nil, $5, false); } | rwDO stmt_block rwWHILE '(' expr ')' { $$ = LoopStmtNode::alloc($3, nil, $5, nil, $2, true); } ; for_stmt : rwFOR '(' expr ';' expr ';' expr ')' stmt_block { $$ = LoopStmtNode::alloc($1, $3, $5, $7, $9, false); } | rwFOR '(' expr ';' expr ';' ')' stmt_block { $$ = LoopStmtNode::alloc($1, $3, $5, NULL, $8, false); } | rwFOR '(' expr ';' ';' expr ')' stmt_block { $$ = LoopStmtNode::alloc($1, $3, NULL, $6, $8, false); } | rwFOR '(' expr ';' ';' ')' stmt_block { $$ = LoopStmtNode::alloc($1, $3, NULL, NULL, $7, false); } | rwFOR '(' ';' expr ';' expr ')' stmt_block { $$ = LoopStmtNode::alloc($1, NULL, $4, $6, $8, false); } | rwFOR '(' ';' expr ';' ')' stmt_block { $$ = LoopStmtNode::alloc($1, NULL, $4, NULL, $7, false); } | rwFOR '(' ';' ';' expr ')' stmt_block { $$ = LoopStmtNode::alloc($1, NULL, NULL, $5, $7, false); } | rwFOR '(' ';' ';' ')' stmt_block { $$ = LoopStmtNode::alloc($1, NULL, NULL, NULL, $6, false); } ; expression_stmt : stmt_expr { $$ = $1; } ; expr : stmt_expr { $$ = $1; } | '(' expr ')' { $$ = $2; } | expr '^' expr { $$ = IntBinaryExprNode::alloc($2, $1, $3); } | expr '%' expr { $$ = IntBinaryExprNode::alloc($2, $1, $3); } | expr '&' expr { $$ = IntBinaryExprNode::alloc($2, $1, $3); } | expr '|' expr { $$ = IntBinaryExprNode::alloc($2, $1, $3); } | expr '+' expr { $$ = FloatBinaryExprNode::alloc($2, $1, $3); } | expr '-' expr { $$ = FloatBinaryExprNode::alloc($2, $1, $3); } | expr '*' expr { $$ = FloatBinaryExprNode::alloc($2, $1, $3); } | expr '/' expr { $$ = FloatBinaryExprNode::alloc($2, $1, $3); } | '-' expr %prec UNARY { $$ = FloatUnaryExprNode::alloc($1, $2); } | '*' expr %prec UNARY { $$ = TTagDerefNode::alloc($2); } | TTAG { $$ = TTagExprNode::alloc($1); } | expr '?' expr ':' expr { $$ = ConditionalExprNode::alloc($1, $3, $5); } | expr '<' expr { $$ = IntBinaryExprNode::alloc($2, $1, $3); } | expr '>' expr { $$ = IntBinaryExprNode::alloc($2, $1, $3); } | expr opGE expr { $$ = IntBinaryExprNode::alloc($2, $1, $3); } | expr opLE expr { $$ = IntBinaryExprNode::alloc($2, $1, $3); } | expr opEQ expr { $$ = IntBinaryExprNode::alloc($2, $1, $3); } | expr opNE expr { $$ = IntBinaryExprNode::alloc($2, $1, $3); } | expr opOR expr { $$ = IntBinaryExprNode::alloc($2, $1, $3); } | expr opSHL expr { $$ = IntBinaryExprNode::alloc($2, $1, $3); } | expr opSHR expr { $$ = IntBinaryExprNode::alloc($2, $1, $3); } | expr opAND expr { $$ = IntBinaryExprNode::alloc($2, $1, $3); } | expr opSTREQ expr { $$ = StreqExprNode::alloc($1, $3, true); } | expr opSTRNE expr { $$ = StreqExprNode::alloc($1, $3, false); } | expr '@' expr { $$ = StrcatExprNode::alloc($1, $3, $2); } | '!' expr { $$ = IntUnaryExprNode::alloc($1, $2); } | '~' expr { $$ = IntUnaryExprNode::alloc($1, $2); } | TAGATOM { $$ = StrConstNode::alloc($1, true); } | FLTCONST { $$ = FloatNode::alloc($1); } | INTCONST { $$ = IntNode::alloc($1); } | rwBREAK { $$ = ConstantNode::alloc(StringTable->insert("break")); } | slot_acc { $$ = SlotAccessNode::alloc($1.object, $1.array, $1.slotName); } | IDENT { $$ = ConstantNode::alloc($1); } | STRATOM { $$ = StrConstNode::alloc($1, false); } | VAR { $$ = (ExprNode*)VarNode::alloc($1, NULL); } | VAR '[' aidx_expr ']' { $$ = (ExprNode*)VarNode::alloc($1, $3); } ; slot_acc : expr '.' IDENT { $$.object = $1; $$.slotName = $3; $$.array = NULL; } | expr '.' IDENT '[' aidx_expr ']' { $$.object = $1; $$.slotName = $3; $$.array = $5; } ; class_name_expr : IDENT { $$ = ConstantNode::alloc($1); } | '(' expr ')' { $$ = $2; } ; assign_op_struct : opPLUSPLUS { $$.token = '+'; $$.expr = FloatNode::alloc(1); } | opMINUSMINUS { $$.token = '-'; $$.expr = FloatNode::alloc(1); } | opPLASN expr { $$.token = '+'; $$.expr = $2; } | opMIASN expr { $$.token = '-'; $$.expr = $2; } | opMLASN expr { $$.token = '*'; $$.expr = $2; } | opDVASN expr { $$.token = '/'; $$.expr = $2; } | opMODASN expr { $$.token = '%'; $$.expr = $2; } | opANDASN expr { $$.token = '&'; $$.expr = $2; } | opXORASN expr { $$.token = '^'; $$.expr = $2; } | opORASN expr { $$.token = '|'; $$.expr = $2; } | opSLASN expr { $$.token = opSHL; $$.expr = $2; } | opSRASN expr { $$.token = opSHR; $$.expr = $2; } ; stmt_expr : funcall_expr { $$ = $1; } | object_decl { $$ = $1; } | VAR '=' expr { $$ = AssignExprNode::alloc($1, NULL, $3); } | VAR '[' aidx_expr ']' '=' expr { $$ = AssignExprNode::alloc($1, $3, $6); } | VAR assign_op_struct { $$ = AssignOpExprNode::alloc($1, NULL, $2.expr, $2.token); } | VAR '[' aidx_expr ']' assign_op_struct { $$ = AssignOpExprNode::alloc($1, $3, $5.expr, $5.token); } | slot_acc assign_op_struct { $$ = SlotAssignOpNode::alloc($1.object, $1.slotName, $1.array, $2.token, $2.expr); } | slot_acc '=' expr { $$ = SlotAssignNode::alloc($1.object, $1.array, $1.slotName, $3); } | slot_acc '=' '{' expr_list '}' { $$ = SlotAssignNode::alloc($1.object, $1.array, $1.slotName, $4); } ; funcall_expr : IDENT '(' expr_list_decl ')' { $$ = FuncCallExprNode::alloc($1, NULL, $3, false); } | IDENT opCOLONCOLON IDENT '(' expr_list_decl ')' { $$ = FuncCallExprNode::alloc($3, $1, $5, false); } | expr '.' IDENT '(' expr_list_decl ')' { $1->append($5); $$ = FuncCallExprNode::alloc($3, NULL, $1, true); } ; expr_list_decl : { $$ = NULL; } | expr_list { $$ = $1; } ; expr_list : expr { $$ = $1; } | expr_list ',' expr { ($1)->append($3); $$ = $1; } ; slot_assign_list : slot_assign { $$ = $1; } | slot_assign_list slot_assign { $1->append($2); $$ = $1; } ; slot_assign : IDENT '=' expr ';' { $$ = SlotAssignNode::alloc(NULL, NULL, $1, $3); } | rwDATABLOCK '=' expr ';' { $$ = SlotAssignNode::alloc(NULL, NULL, StringTable->insert("datablock"), $3); } | IDENT '[' aidx_expr ']' '=' expr ';' { $$ = SlotAssignNode::alloc(NULL, $3, $1, $6); } ; aidx_expr : expr { $$ = $1; } | aidx_expr ',' expr { $$ = CommaCatExprNode::alloc($1, $3); } ; %%