bool Parser::parseFunDeclArgsRest( AstFunDeclNode* fun ) { std::string name; AstTypeNode* type; #ifdef DEBUG_PARSER fprintf( stderr, "parseFunDeclArgsRest\n" ); #endif /* DEBUG_PARSER */ switch( peek() ) { case LEXTOK_SCOL: if( !match( LEXTOK_SCOL ) ) return false; name = peekStr(); if( !match( LEXTOK_IDENT ) || !match( LEXTOK_COL ) || !parseTypeIdent( type ) ) return false; fun->addArg( name.c_str(), type ); return parseFunDeclArgsRest( fun ); case LEXTOK_RPAR: return true; default: return error(); } }
bool Parser::parseIdentListRest( std::vector< std::string >& idents ) { #ifdef DEBUG_PARSER fprintf( stderr, "parseIdentListRest\n" ); #endif /* DEBUG_PARSER */ switch( peek() ) { case LEXTOK_COMMA: if( !match( LEXTOK_COMMA ) ) return false; idents.push_back( peekStr() ); return match( LEXTOK_IDENT ) && parseIdentListRest( idents ); case LEXTOK_EQ: case LEXTOK_COL: return true; default: return error(); } }
bool Parser::parseExpr5( AstExprNode*& expr ) { std::string name; #ifdef DEBUG_PARSER fprintf( stderr, "parseExpr5\n" ); #endif /* DEBUG_PARSER */ switch( peek() ) { // Expr5: case LEXTOK_IDENT: name = peekStr(); return match( LEXTOK_IDENT ) && parseExpr5Ident( name, expr ); case LEXTOK_NUMBER: expr = new AstIntExprNode( peekInt() ); return match( LEXTOK_NUMBER ); case LEXTOK_LPAR: return match( LEXTOK_LPAR ) && parseExpr0( expr ) && match( LEXTOK_RPAR ); default: return error(); } }
/// Try and match a given string in the input /// The string is consumed if matched bool Input::matchStr(const std::string& str) { if (peekStr(str)) { for (size_t i = 0; i < str.length(); ++i) readCh(); return true; } return false; }
bool Parser::parseVarDeclRest( AstBlkStmtNode* blk ) { AstTypeNode* type; std::vector< std::string > idents; std::vector< std::string >::const_iterator cur, end; #ifdef DEBUG_PARSER fprintf( stderr, "parseVarDeclRest\n" ); #endif /* DEBUG_PARSER */ switch( peek() ) { case LEXTOK_IDENT: idents.push_back( peekStr() ); if( !match( LEXTOK_IDENT ) || !parseIdentListRest( idents ) || !match( LEXTOK_COL ) || !parseTypeIdent( type ) || !match( LEXTOK_SCOL ) ) return false; cur = idents.begin(); end = idents.end(); blk->addDecl( new AstVarDeclNode( (cur++)->c_str(), type ) ); for(; cur != end; ++cur ) blk->addDecl( new AstVarDeclNode( cur->c_str(), type->clone() ) ); return parseVarDeclRest( blk ); case LEXTOK_KW_CONST: case LEXTOK_KW_VAR: case LEXTOK_KW_BEGIN: return true; default: return error(); } }
bool Parser::parseProgram( AstProgDeclNode*& prog ) { AstFunDeclNode* fun; AstBlkStmtNode* blk; #ifdef DEBUG_PARSER fprintf( stderr, "parseProgram\n" ); #endif /* DEBUG_PARSER */ switch( peek() ) { case LEXTOK_KW_PROG: if( !match( LEXTOK_KW_PROG ) ) return false; prog = new AstProgDeclNode( peekStr().c_str() ); blk = new AstBlkStmtNode(); if( !match( LEXTOK_IDENT ) || !match( LEXTOK_SCOL ) || !parseDeclsGlob( prog ) || !parseBlock( blk ) || !match( LEXTOK_DOT ) || !match( LEXTOK_EOI ) ) return false; fun = new AstFunDeclNode( "main" ); fun->setResType( new AstIntTypeNode() ); fun->setBody( blk ); prog->addFun( fun ); return true; default: return error(); } }
bool Parser::parseStmt( AstBlkStmtNode* blk ) { bool inc; std::string str; AstExprNode *expr1, *expr2; AstBlkStmtNode *bodyBlk, *elseBlk; #ifdef DEBUG_PARSER fprintf( stderr, "parseStmt\n" ); #endif /* DEBUG_PARSER */ switch( peek() ) { case LEXTOK_IDENT: str = peekStr(); return match( LEXTOK_IDENT ) && parseStmtIdent( str, blk ); case LEXTOK_KW_IF: bodyBlk = new AstBlkStmtNode(); elseBlk = NULL; if( !match( LEXTOK_KW_IF ) || !parseExpr0( expr1 ) || !match( LEXTOK_KW_THEN ) || !parseStmt( bodyBlk ) || !parseElseBranch( elseBlk ) ) return false; blk->addStmt( new AstIfStmtNode( expr1, bodyBlk, elseBlk ) ); return true; case LEXTOK_KW_WHILE: if( !match( LEXTOK_KW_WHILE ) || !parseExpr0( expr1 ) || !match( LEXTOK_KW_DO ) ) return false; bodyBlk = new AstBlkStmtNode(); bodyBlk->addStmt( new AstBreakStmtNode( new AstUnopExprNode( LEXTOK_NOT, expr1 ) ) ); if( !parseStmt( bodyBlk ) ) return false; blk->addStmt( new AstLoopStmtNode( bodyBlk ) ); return true; case LEXTOK_KW_FOR: if( !match( LEXTOK_KW_FOR ) ) return false; str = peekStr(); if( !match( LEXTOK_IDENT ) || !match( LEXTOK_ASSGN ) || !parseExpr0( expr1 ) || !parseForDirection( inc ) || !parseExpr0( expr2 ) || !match( LEXTOK_KW_DO ) ) return false; bodyBlk = new AstBlkStmtNode(); bodyBlk->addStmt( new AstBreakStmtNode( new AstBinopExprNode( (inc ? LEXTOK_GT : LEXTOK_LT), new AstVarExprNode( str.c_str() ), expr2 ) ) ); if( !parseStmt( bodyBlk ) ) return false; bodyBlk->addStmt( new AstBinopStmtNode( (inc ? LEXTOK_KW_INC : LEXTOK_KW_DEC), new AstVarExprNode( str.c_str() ), new AstIntExprNode( 1 ) ) ); blk->addStmt( new AstBinopStmtNode( LEXTOK_ASSGN, new AstVarExprNode( str.c_str() ), expr1 ) ); blk->addStmt( new AstLoopStmtNode( bodyBlk ) ); return true; case LEXTOK_KW_EXIT: blk->addStmt( new AstExitStmtNode() ); return match( LEXTOK_KW_EXIT ); case LEXTOK_KW_CONST: case LEXTOK_KW_VAR: case LEXTOK_KW_BEGIN: return parseBlock( blk ); case LEXTOK_KW_INC: if( !match( LEXTOK_KW_INC ) || !match( LEXTOK_LPAR ) ) return false; str = peekStr(); if( !match( LEXTOK_IDENT ) || !parseStmtLvalIdent( str, expr1 ) || !match( LEXTOK_RPAR ) ) return false; blk->addStmt( new AstBinopStmtNode( LEXTOK_KW_INC, expr1, new AstIntExprNode( 1 ) ) ); return true; case LEXTOK_KW_DEC: if( !match( LEXTOK_KW_DEC ) || !match( LEXTOK_LPAR ) ) return false; str = peekStr(); if( !match( LEXTOK_IDENT ) || !parseStmtLvalIdent( str, expr1 ) || !match( LEXTOK_RPAR ) ) return false; blk->addStmt( new AstBinopStmtNode( LEXTOK_KW_DEC, expr1, new AstIntExprNode( 1 ) ) ); return true; case LEXTOK_KW_READLN: if( !match( LEXTOK_KW_READLN ) || !match( LEXTOK_LPAR ) ) return false; str = peekStr(); if( !match( LEXTOK_IDENT ) || !parseStmtLvalIdent( str, expr1 ) || !match( LEXTOK_RPAR ) ) return false; blk->addStmt( new AstReadStmtNode( "%d", expr1 ) ); return true; case LEXTOK_KW_WRITE: if( !match( LEXTOK_KW_WRITE ) || !match( LEXTOK_LPAR ) ) return false; str = peekStr(); if( !match( LEXTOK_STRING ) || !match( LEXTOK_RPAR ) ) return false; blk->addStmt( new AstWriteStmtNode( "%s", new AstStrExprNode( str.c_str() ) ) ); return true; case LEXTOK_KW_WRITELN: if( !match( LEXTOK_KW_WRITELN ) || !match( LEXTOK_LPAR ) || !parseExpr0( expr1 ) || !match( LEXTOK_RPAR ) ) return false; blk->addStmt( new AstWriteStmtNode( "%d\n", expr1 ) ); return true; case LEXTOK_SCOL: case LEXTOK_KW_END: return true; default: return error(); } }
bool Parser::parseDeclsGlob( AstProgDeclNode* prog ) { AstFunDeclNode* fun; AstTypeNode* resType; #ifdef DEBUG_PARSER fprintf( stderr, "parseDeclsGlob\n" ); #endif /* DEBUG_PARSER */ switch( peek() ) { case LEXTOK_KW_FUNC: if( !match( LEXTOK_KW_FUNC ) ) return false; fun = new AstFunDeclNode( peekStr().c_str() ); if( !match( LEXTOK_IDENT ) || !match( LEXTOK_LPAR ) || !parseFunDeclArgs( fun ) || !match( LEXTOK_RPAR ) || !match( LEXTOK_COL ) || !parseTypeIdent( resType ) || !match( LEXTOK_SCOL ) || !parseFunDeclBody( fun ) || !match( LEXTOK_SCOL ) ) return false; fun->setResType( resType ); prog->addFun( fun ); return parseDeclsGlob( prog ); case LEXTOK_KW_PROC: if( !match( LEXTOK_KW_PROC ) ) return false; fun = new AstFunDeclNode( peekStr().c_str() ); if( !match( LEXTOK_IDENT ) || !match( LEXTOK_LPAR ) || !parseFunDeclArgs( fun ) || !match( LEXTOK_RPAR ) || !match( LEXTOK_SCOL ) || !parseFunDeclBody( fun ) || !match( LEXTOK_SCOL ) ) return false; fun->setResType( NULL ); prog->addFun( fun ); return parseDeclsGlob( prog ); case LEXTOK_KW_CONST: case LEXTOK_KW_VAR: case LEXTOK_KW_BEGIN: return true; default: return error(); } }