%{ #include #include #include #include "gamebuilder.h" #include "astnode.h" typedef void *yyscan_t; %} %locations %pure-parser /* %define api.pure */ %debug %error-verbose %parse-param { yyscan_t yyscanner } %lex-param { yysacn_t yyscanner } %parse-param { GameBuilder &bld } %union { int64_t iValue; double dValue; Bu::String *sValue; bool bValue; } %{ int yylex( YYSTYPE *yylval, struct YYLTYPE *llocp, yyscan_t yyscanner ); void yyerror( YYLTYPE *llocp, yyscan_t yyscanner, GameBuilder &, const char *error ) { printf("%d:%d-%d:%d: %s\n", llocp->first_line, llocp->first_column, llocp->last_line, llocp->last_column, error ); } %} %token tokGame %token tokGlobal %token tokFunction %token tokSituation %token tokSetup %token tokEnter %token tokAnd %token tokOr %token tokWhile %token tokFor %token tokEach %token tokDo %token tokIn %token tokIf %token tokThen %token tokElse %token tokNot %token tokCommand %token tokPlayer %token tokLtEq %token tokGtEq %token tokCmp %token tokPlusAssign %token tokMinusAssign %token tokTimesAssign %token tokDivideAssign %token tokSituationName %token tokIdent %token tokGoto %token tokString %token tokInt %token tokFloat %token tokBool %token tokNull %destructor { delete $$; printf("string deleted.\n"); } tokString tokSituationName %token eos 0 "end of stream" %left NOT %right '=' tokPlusAssign tokMinusAssign tokTimesAssign tokDivideAssign %left '-' '+' %left '*' '/' %left tokIn tokAnd tokOr %right '<' '>' tokLtEq tokGtEq tokCmp %left '(' ')' '[' ']' %left NEG %% input: gameDecls globalDecl bodyDecl ; gameDecls: | gameDecls tokGame '.' tokIdent '=' literal ';' { bld.setGameParam( *($4) ); } ; globalDecl: | tokGlobal '{' { bld.beginGlobal(); } globalExprList '}' { bld.closeGlobal(); } ; globalExprList: | globalExprList cmpltGlobalExpr ; cmpltGlobalExpr: globalExpr ';' | commandDecl ; globalExpr: tokIdent '=' expr ; bodyDecl: | bodyDecl situation | bodyDecl function ; situation: tokSituation tokSituationName { bld.beginSituation( *($2) ); } '{' situationMembers '}' { bld.endSituation(); } ; situationMembers: | situationMembers situationModeFunc | situationMembers commandDecl ; situationModeFunc: situationMode '{' cmpltExprList '}' { bld.closeSituationMode(); } ; situationMode: tokSetup { bld.beginSituationMode( Situation::modeSetup ); } | tokEnter { bld.beginSituationMode( Situation::modeEnter ); } ; function: tokFunction tokIdent { bld.beginFunction( *($2) ); } '(' funcParamList ')' { bld.endFunctionParams(); } '{' cmpltExprList '}' { bld.endFunction(); } ; funcParamList: | tokIdent { bld.addFunctionParam( *($1) ); } funcParamListEx ; funcParamListEx: | funcParamListEx ',' tokIdent { bld.addFunctionParam( *($3) ); } ; cmpltExprList: | cmpltExprList cmpltExpr ; cmpltExpr: expr ';' | tokGoto '(' expr ')' ';' { bld.addNode( AstNode::tGoto ); } | ifbase | tokFor tokEach forIterator tokIn expr tokDo '{' cmpltExprList '}' | tokWhile { bld.addNode( AstNode::tWhile ); bld.addNode( AstNode::tScope ); } expr { bld.closeNode(); bld.addNode( AstNode::tScope ); } tokDo '{' cmpltExprList '}' { bld.closeNode(); bld.closeNode(); } ; forIterator: tokIdent | tokIdent ':' tokIdent ifbase: tokIf { bld.addNode( AstNode::tIf ); bld.addNode( AstNode::tScope ); } expr { bld.closeNode(); bld.addNode( AstNode::tScope ); } tokThen '{' cmpltExprList '}' { bld.closeNode(); } ifnext { bld.closeNode(); } ; ifnext: | tokElse { bld.addNode( AstNode::tScope ); } '{' cmpltExprList '}' { bld.closeNode(); } | tokElse { bld.addNode( AstNode::tScope ); } ifbase ; varRef: tokIdent { bld.addVarRef( *($1), sidLocal ); } | tokPlayer '.' tokIdent { bld.addVarRef( *($3), sidPlayer ); } | tokGlobal '.' tokIdent { bld.addVarRef( *($3), sidGlobal ); } | tokSituation '.' tokIdent { bld.addVarRef( *($3), sidSituation ); } ; literal: tokInt { bld.addLiteral( Variable( $1 ) ); } | tokFloat { bld.addLiteral( Variable( $1 ) ); } | tokString { bld.addLiteral( Variable( *($1) ) ); } | tokBool { bld.addLiteral( Variable( $1 ) ); } | tokNull { bld.addLiteral( Variable( Variable::tNull ) ); } | tokSituationName { bld.addLiteral( Variable::newSituationName( *($1) ) ); } ; expr: literal | tokIdent '(' funcCallParams ')' { bld.addFuncCall( *($1) ); } | varRef | varRef '=' expr { bld.addNode( AstNode::tStore ); } | varRef tokPlusAssign expr { bld.addNode( AstNode::tPlusStore ); } | varRef tokMinusAssign expr { bld.addNode( AstNode::tMinusStore ); } | varRef tokTimesAssign expr { bld.addNode( AstNode::tMultiplyStore ); } | varRef tokDivideAssign expr { bld.addNode( AstNode::tDivideStore ); } | expr '+' expr { bld.addNode( AstNode::tPlus ); } | expr '-' expr { bld.addNode( AstNode::tMinus ); } | expr '/' expr { bld.addNode( AstNode::tDivide ); } | expr '*' expr { bld.addNode( AstNode::tMultiply ); } | expr tokAnd expr { bld.addNode( AstNode::tAnd ); } | expr tokOr expr { bld.addNode( AstNode::tOr ); } | expr tokIn expr { bld.addNode( AstNode::tIn ); } | expr tokCmp expr { bld.addNode( AstNode::tComp ); } | expr '<' expr { bld.addNode( AstNode::tCompLt ); } | expr '>' expr { bld.addNode( AstNode::tCompGt ); } | expr tokLtEq expr { bld.addNode( AstNode::tCompLtEq ); } | expr tokGtEq expr { bld.addNode( AstNode::tCompGtEq ); } | '(' expr ')' | expr '[' expr ']' | '[' ']' | '[' listValues ']' | '{' '}' | '{' dictValues '}' | tokNot expr %prec NOT { bld.addNode( AstNode::tNot ); } | '-' expr %prec NEG { bld.addNode( AstNode::tNegate ); } ; funcCallParams: | expr funcCallParamsEx ; funcCallParamsEx: | funcCallParamsEx ',' expr ; listValues: expr | listValues ',' expr ; dictValues: expr ':' expr | dictValues ',' expr ':' expr ; commandDecl: tokCommand ':' tokString { bld.beginCommand( *$3 ); } commandParamList '{' { bld.endCommandParams(); } cmpltExprList '}' { bld.closeCommand(); } ; commandParamList: | commandParamList tokString { bld.addCommandLiteral( *$2 ); } | commandParamList tokIdent { bld.addCommandParam( *$2 ); } ; %% /* void yylex_init( yyscan_t * ); void yylex_destroy( yyscan_t ); int main() { yyscan_t scanner; yylex_init ( &scanner ); yyparse( scanner ); yylex_destroy ( scanner ); return 0; } */