bool ParseFunctionCall(FunctionEvent *FnEvent, CallExpr *Call, vector<ValueDecl*>& References, ASTContext& Ctx) { #ifndef NDEBUG auto Predicate = Call->getDirectCallee(); assert(Predicate != NULL); assert(Predicate->getName() == "__tesla_call"); #endif if (Call->getNumArgs() != 1) { Report("TESLA predicate should have one (boolean) argument", Call->getLocStart(), Ctx) << Call->getSourceRange(); return false; } auto Bop = dyn_cast<BinaryOperator>(Call->getArg(0)->IgnoreImplicit()); if (!Bop || (Bop->getOpcode() != BO_EQ)) { Report("A TESLA predicate should be of the form foo(x) == y", Call->getLocStart(), Ctx) << Call->getSourceRange(); return false; } return ParseFunctionCall(FnEvent, Bop, References, Ctx); }
bool PassParser::Parse(Lexer* lexer, const boost::filesystem::path& dir) { m_rootDir = dir; Token token = lexer->CurToken(); if(token.type != Token::token_id) { Error(token.line, "unexpected token: '" + token.str + "'"); return false; } m_name = token.str; if(FindSymbol(m_name, true) != nullptr) { Error(token.line, "object '" + m_name + "' already defined."); return false; } token = lexer->NextToken(); if(token.str != "{") { Error(token.line, "unexpected token: '" + token.str + "'"); return false; } token = lexer->NextToken(); while(true) { if(ParseFunctionCall(lexer) == false) { return false; } if(lexer->CurToken().str == "}") { break; } } token = lexer->NextToken(); if(token.str == ";") { lexer->SkipToken(token); } return true; }
Expresion* Sintactico::ParseFactor() { if ( proximo_token.GetTipo() == punt_parentizq ) { proximo_token = analizador_lexico->ObtenerSiguienteToken(); Expresion* expr = ParseExpression(); if ( proximo_token.GetTipo() == punt_parentder ) { proximo_token = analizador_lexico->ObtenerSiguienteToken(); } else throw SyntaxException("Falta un parentesis derecho: produccion Factor",analizador_lexico->GetLineaActual()); return expr; } else if ( proximo_token.GetTipo() == lit_int || proximo_token.GetTipo() == lit_float || proximo_token.GetTipo() == lit_string || proximo_token.GetTipo() == lit_boolean || proximo_token.GetTipo() == lit_caracter ) { return ParseLiteralConstant(); } else if ( proximo_token.GetTipo() == op_suma || proximo_token.GetTipo() == op_resta || proximo_token.GetTipo() == kw_not ) { //Utilizamos Primeros ( unary-expression ) return ParseUnaryExpression(); } else if ( proximo_token.GetTipo() == id ) { string identificador = proximo_token.GetLexema(); proximo_token = analizador_lexico->ObtenerSiguienteToken(); if ( proximo_token.GetTipo() == punt_parentizq ) { list<Expresion*>args = ParseFunctionCall(); FunctionCall* func = new FunctionCall(identificador,args); return func; } else { list<Qualifier*> qualifier_list = ParseQualifiers(); Identificador* id = new Identificador(identificador,qualifier_list); return id; } } else throw SyntaxException("No se encontro un token correcto...factor",analizador_lexico->GetLineaActual() ); }
AST* ParseObject(ParserState* parser) { if(parser->currentToken.type == TOKEN_OBJECT) { Match(parser, TOKEN_OBJECT); return CreateASTNode(SEM_OBJECT, VALUE_EMPTY); } else { Match(parser, TOKEN_NEW); AST* constructor_call = ParseFunctionCall(parser); AST* ast = CreateASTNode(SEM_NEW, VALUE_EMPTY); AddASTChild(ast, constructor_call); return ast; } }
AST* ParseValue(ParserState* parser) { AST* node; if(parser->currentToken.type == TOKEN_NUMBER || parser->currentToken.type == TOKEN_STRING) { node = CreateASTNode(SEM_CONSTANT, parser->currentToken.value); Match(parser, parser->currentToken.type); } else { if(parser->nextToken.type == TOKEN_LEFTBRACKET) return ParseFunctionCall(parser); Value *id = Match(parser, TOKEN_ID); /* XXX: Factor this out */ if(parser->currentToken.type == TOKEN_LEFT_SQUARE_BRACKET) { Match(parser, TOKEN_LEFT_SQUARE_BRACKET); AST* size = ParseExpression(parser); Match(parser, TOKEN_RIGHT_SQUARE_BRACKET); node = CreateASTNode(SEM_INDEX, id); AddASTChild(node, size); } else if(parser->currentToken.type == TOKEN_DOT) { Match(parser, TOKEN_DOT); Value* field_name = Match(parser, TOKEN_FIELD); if(parser->currentToken.type == TOKEN_LEFTBRACKET) { node = CreateASTNode(SEM_METHOD_CALL, VALUE_EMPTY); AST* field_node = CreateASTNode(SEM_FIELD, id); AddASTChild(field_node, CreateASTNode(SEM_CONSTANT, field_name)); AddASTChild(node, field_node); Match(parser, TOKEN_LEFTBRACKET); AddASTChild(node, ParseArgumentList(parser)); Match(parser, TOKEN_RIGHTBRACKET); } else { node = CreateASTNode(SEM_FIELD, id); AddASTChild(node, CreateASTNode(SEM_CONSTANT, field_name)); } } else { node = CreateASTNode(SEM_ID, id); } } return node; }
asCScriptNode *asCParser::ParseExprPostOp() { asCScriptNode *node = new asCScriptNode(snExprPostOp); sToken t; GetToken(&t); if( !IsPostOperator(t.type) ) { Error(TXT_EXPECTED_POST_OPERATOR, &t); return node; } node->SetToken(&t); node->UpdateSourcePos(t.pos, t.length); if( t.type == ttDot ) { sToken t1, t2; GetToken(&t1); GetToken(&t2); RewindTo(&t1); if( t2.type == ttOpenParanthesis ) node->AddChildLast(ParseFunctionCall()); else node->AddChildLast(ParseIdentifier()); } else if( t.type == ttOpenBracket ) { node->AddChildLast(ParseAssignment()); GetToken(&t); if( t.type != ttCloseBracket ) { ExpectedToken("]"); return node; } node->UpdateSourcePos(t.pos, t.length); } return node; }
AST* ParseOperator(ParserState* parser) { AST* ast; switch(parser->currentToken.type) { case TOKEN_BEGIN: return ParseBlock(parser); case TOKEN_ID: ast = parser->nextToken.type == TOKEN_LEFTBRACKET ? ParseFunctionCall(parser) : ParseAssignment(parser); Match(parser, TOKEN_SEMICOLON); return ast; case TOKEN_LOCAL: ast = ParseAssignment(parser); Match(parser, TOKEN_SEMICOLON); return ast; case TOKEN_WHILE: return ParseWhileCycle(parser); case TOKEN_IF: return ParseIfStatement(parser); case TOKEN_FUNCTION: return ParseFunctionDefinition(parser); case TOKEN_RETURN: ast = ParseReturn(parser); Match(parser, TOKEN_SEMICOLON); return ast; case TOKEN_PRINT: ast = ParsePrint(parser); Match(parser, TOKEN_SEMICOLON); return ast; case TOKEN_INCLUDE: return ParseInclude(parser); case TOKEN_LOAD: ast = ParseLoad(parser); Match(parser, TOKEN_SEMICOLON); return ast; /** TODO: Factor common parts out of switch */ } FailWithUnexpectedToken(parser, parser->currentToken.type, TOKEN_ID); return NULL; }
asCScriptNode *asCParser::ParseExprValue() { asCScriptNode *node = new asCScriptNode(snExprValue); sToken t1; GetToken(&t1); RewindTo(&t1); if( t1.type == ttIdentifier || IsRealType(t1.type) ) { if( IsFunctionCall() ) node->AddChildLast(ParseFunctionCall()); else node->AddChildLast(ParseIdentifier()); } else if( t1.type == ttCast ) node->AddChildLast(ParseCast()); else if( IsConstant(t1.type) ) node->AddChildLast(ParseConstant()); else if( t1.type == ttOpenParanthesis ) { GetToken(&t1); node->UpdateSourcePos(t1.pos, t1.length); node->AddChildLast(ParseAssignment()); if( isSyntaxError ) return node; GetToken(&t1); if( t1.type != ttCloseParanthesis ) Error(ExpectedToken(")").AddressOf(), &t1); node->UpdateSourcePos(t1.pos, t1.length); } else Error(TXT_EXPECTED_EXPRESSION_VALUE, &t1); return node; }
/* ============== Expression ============== */ def_t *Compiler::Expression( int priority ) { opcode_t *op; opcode_t *oldop; def_t *e; def_t *e2; etype_t type_a; etype_t type_b; char *name; if ( priority == 0 ) { return Term(); } e = Expression( priority - 1 ); while( 1 ) { if ( priority == FUNCTION_PRIORITY ) { if ( lex.Check( "(" ) ) { return ParseFunctionCall( e ); } else if ( ( ( e->type->type == ev_entity ) || ( ( e->type->type == ev_void ) && ( e->ofs < OFS_END ) ) ) && ( lex.Check( "." ) ) ) { if ( lex.pr_token_type != tt_name ) { lex.ParseError( "Expecting function call" ); } name = lex.ParseName(); // look through the defs e2 = program.GetDef( NULL, name, pr_scope, false, &lex ); if ( !e2 ) { lex.ParseError( "Unknown value \"%s\"", name ); } else if ( e2->type->type != ev_function ) { lex.ParseError( "\"%s\" is not a valid function name", name ); } return ParseObjectCall( e2, e ); } //else if ( lex.Check( ";" ) ) //{ // lex.ParseError( "Invalid command - %s", e->name.c_str() ); //} } for( op = pr_opcodes; op->name; op++ ) { if ( op->priority != priority ) { continue; } if ( !lex.Check( op->name ) ) { continue; } if ( op->type_b == &def_void ) { e = Statement( op, e, 0 ); return e; } if ( op->right_associative ) { e2 = Expression( priority ); } else { e2 = Expression( priority - 1 ); } // type check type_a = e->type->type; type_b = e2->type->type; oldop = op; while( ( type_a != op->type_a->type->type ) || ( type_b != op->type_b->type->type ) ) { op++; if ( !op->name || strcmp( op->name, oldop->name ) ) { lex.ParseError( "type mismatch for %s", oldop->name ); } } if ( op->right_associative ) { e = Statement( op, e2, e ); } else { e = Statement( op, e, e2 ); } break; } if ( !op->name ) { // next token isn't at this priority level break; } } return e; }
bool ParseEvent(Event *Ev, Expr *E, Assertion *A, vector<ValueDecl*>& References, ASTContext& Ctx) { E = E->IgnoreImplicit(); if (auto Ref = dyn_cast<DeclRefExpr>(E)) { auto D = Ref->getDecl(); assert(D); // The __tesla_ignore "event" helps TESLA assertions look like ISO C. if (D->getName() == "__tesla_ignore") { Ev->set_type(Event::IGNORE); return true; } // The only other static __tesla_event is the "now" event. if (D->getName() != "__tesla_now") { Report("TESLA static reference must be __tesla_ignore or __tesla_now", E->getLocStart(), Ctx) << E->getSourceRange(); return false; } Ev->set_type(Event::NOW); *Ev->mutable_now()->mutable_location() = A->location(); return true; } else if (auto Bop = dyn_cast<BinaryOperator>(E)) { // This is a call-and-return like "foo(x) == y". Ev->set_type(Event::FUNCTION); return ParseFunctionCall(Ev->mutable_function(), Bop, References, Ctx); } // Otherwise, it's a call to a TESLA "function" like __tesla_predicate(). auto Call = dyn_cast<CallExpr>(E); if (!Call) { Report("Event should look like a function call", E->getLocStart(), Ctx) << E->getSourceRange(); return false; } auto Callee = Call->getDirectCallee(); if (!Callee) { Report("TESLA event referenced indirectly", Call->getLocStart(), Ctx) << Call->getSourceRange(); return false; } if (Callee->getName() == "__tesla_repeat") { Ev->set_type(Event::REPETITION); return ParseRepetition(Ev->mutable_repetition(), Call, A, References, Ctx); } typedef bool (*FnEventParser)(FunctionEvent*, CallExpr*, vector<ValueDecl*>&, ASTContext&); FnEventParser Parser = llvm::StringSwitch<FnEventParser>(Callee->getName()) .Case("__tesla_entered", &ParseFunctionEntry) .Case("__tesla_leaving", &ParseFunctionExit) .Case("__tesla_call", &ParseFunctionCall) .Default(NULL); if (!Parser) { Report("Unknown TESLA event", E->getLocStart(), Ctx) << E->getSourceRange(); return false; } Ev->set_type(Event::FUNCTION); return Parser(Ev->mutable_function(), Call, References, Ctx); }