Parser::StmtResult Parser::ParseGotoStmt() { SourceLocation Loc = ConsumeToken(); if(ConsumeIfPresent(tok::l_paren)) { // computed goto. SmallVector<Expr*, 4> Targets; do { auto E = ParseStatementLabelReference(); if(E.isInvalid()) break; Targets.append(1, E.get()); } while(ConsumeIfPresent(tok::comma)); ExprResult Operand; bool ParseOperand = true; if(!ExpectAndConsume(tok::r_paren)) { if(!SkipUntil(tok::r_paren)) ParseOperand = false; } if(ParseOperand) Operand = ParseExpectedExpression(); return Actions.ActOnComputedGotoStmt(Context, Loc, Targets, Operand, StmtLabel); } auto Destination = ParseStatementLabelReference(); if(Destination.isInvalid()) { if(!IsPresent(tok::identifier)) { Diag.Report(getExpectedLoc(), diag::err_expected_stmt_label_after) << "GO TO"; return StmtError(); } auto IDInfo = Tok.getIdentifierInfo(); auto IDLoc = ConsumeToken(); auto VD = Actions.ExpectVarRef(IDLoc, IDInfo); if(!VD) return StmtError(); auto Var = VarExpr::Create(Context, IDLoc, VD); // Assigned goto SmallVector<Expr*, 4> AllowedValues; if(ConsumeIfPresent(tok::l_paren)) { do { auto E = ParseStatementLabelReference(); if(E.isInvalid()) { Diag.Report(getExpectedLoc(), diag::err_expected_stmt_label); SkipUntilNextStatement(); return Actions.ActOnAssignedGotoStmt(Context, Loc, Var, AllowedValues, StmtLabel); } AllowedValues.append(1, E.get()); } while(ConsumeIfPresent(tok::comma)); ExpectAndConsume(tok::r_paren); } return Actions.ActOnAssignedGotoStmt(Context, Loc, Var, AllowedValues, StmtLabel); } // Uncoditional goto return Actions.ActOnGotoStmt(Context, Loc, Destination, StmtLabel); }
ExprResult Parser::ParseExpectedExpression() { if(Tok.isAtStartOfStatement()) { Diag.Report(getExpectedLoc(), diag::err_expected_expression); return ExprError(); } return ParseExpression(); }
Parser::StmtResult Parser::ParseAssignStmt() { SourceLocation Loc = ConsumeToken(); auto Value = ParseStatementLabelReference(false); if(Value.isInvalid()) { Diag.Report(getExpectedLoc(), diag::err_expected_stmt_label_after) << "ASSIGN"; return StmtError(); } ConsumeToken(); if(!ExpectAndConsumeFixedFormAmbiguous(tok::kw_TO, diag::err_expected_kw, "to")) return StmtError(); auto IDInfo = Tok.getIdentifierInfo(); auto IDRange = getTokenRange(); auto IDLoc = Tok.getLocation(); if(!ExpectAndConsume(tok::identifier)) return StmtError(); auto VD = Actions.ExpectVarRefOrDeclImplicitVar(IDLoc, IDInfo); if(!VD) return StmtError(); auto Var = VarExpr::Create(Context, IDRange, VD); return Actions.ActOnAssignStmt(Context, Loc, Value, Var, StmtLabel); }
/// \brief Looks at the next token to see if it's an expression /// and calls ParseExpression if it is, or reports an expected expression /// error. ExprResult Parser::ParseExpectedFollowupExpression(const char *DiagAfter) { if(Tok.isAtStartOfStatement()) { Diag.Report(getExpectedLoc(), diag::err_expected_expression_after) << DiagAfter; return ExprError(); } return ParseExpression(); }
bool Parser::ParseObjectCharLength(SourceLocation Loc, DeclSpec &DS) { if(DS.getTypeSpecType() == TST_character && ConsumeIfPresent(tok::star)) { if (DS.hasLengthSelector()) Diag.Report(getExpectedLoc(), diag::err_duplicate_len_selector); return ParseCharacterStarLengthSpec(DS); } return false; }
/// ParseFunctionCallArgumentList - Parses an argument list to a call expression. ExprResult Parser::ParseFunctionCallArgumentList(SmallVectorImpl<Expr*> &Args, SourceLocation &RParenLoc) { if(!ExpectAndConsume(tok::l_paren)) return ExprError(); RParenLoc = getExpectedLoc(); if(ConsumeIfPresent(tok::r_paren)) return ExprResult(); auto PunctuationTok = "("; do { if(Tok.isAtStartOfStatement()) break; auto E = ParseExpectedFollowupExpression(PunctuationTok); if(E.isInvalid()) SkipUntil(tok::comma, tok::r_paren, true, true); else Args.push_back(E.get()); PunctuationTok = ","; } while (ConsumeIfPresent(tok::comma)); RParenLoc = getExpectedLoc(); ExpectAndConsume(tok::r_paren, 0, "", tok::r_paren); return ExprResult(); }
/// ParseAssignmentStmt /// [R732]: /// assignment-stmt := /// variable = expr Parser::StmtResult Parser::ParseAssignmentStmt() { ExprResult LHS = ParsePrimaryExpr(true); if(LHS.isInvalid()) return StmtError(); SourceLocation Loc = Tok.getLocation(); if(!ConsumeIfPresent(tok::equal)) { Diag.Report(getExpectedLoc(),diag::err_expected_equal); return StmtError(); } ExprResult RHS = ParseExpectedFollowupExpression("="); if(RHS.isInvalid()) return StmtError(); return Actions.ActOnAssignmentStmt(Context, Loc, LHS, RHS, StmtLabel); }
Parser::StmtResult Parser::ParseCallStmt() { auto Loc = ConsumeToken(); SourceLocation RParenLoc = getExpectedLoc(); auto ID = Tok.getIdentifierInfo(); auto IDLoc = Tok.getLocation(); if(!ExpectAndConsume(tok::identifier)) return StmtError(); SmallVector<Expr*, 8> Arguments; if(!Tok.isAtStartOfStatement()) { if(ParseFunctionCallArgumentList(Arguments, RParenLoc).isInvalid()) SkipUntilNextStatement(); } return Actions.ActOnCallStmt(Context, Loc, RParenLoc, IDLoc, ID, Arguments, StmtLabel); }
/// ParseArrauSubscript - Parse an Array Subscript Expression ExprResult Parser::ParseArraySubscript(ExprResult Target) { SmallVector<Expr*, 8> ExprList; auto Loc = ConsumeParen(); bool IgnoreRParen = false; auto PunctuationTok = "("; do { if(Tok.isAtStartOfStatement()) IgnoreRParen = true; auto E = ParseArraySection(PunctuationTok); if(E.isInvalid()) SkipUntil(tok::comma, tok::r_paren, true, true); if(E.isUsable()) ExprList.push_back(E.get()); PunctuationTok = ","; } while(ConsumeIfPresent(tok::comma)); auto RParenLoc = getExpectedLoc(); if(!IgnoreRParen) ExpectAndConsume(tok::r_paren, 0, "", tok::r_paren); return Actions.ActOnSubscriptExpr(Context, Loc, RParenLoc, Target.get(), ExprList); }
Parser::StmtResult Parser::ParseIfStmt() { auto Loc = ConsumeToken(); ExprResult Condition; if (!ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "IF")) goto error; Condition = ParseExpectedFollowupExpression("("); if(Condition.isInvalid()) { if(!SkipUntil(tok::r_paren, true, true)) goto error; } if (!ExpectAndConsume(tok::r_paren)) goto error; if(Features.FixedForm && !Tok.isAtStartOfStatement()) ReLexAmbiguousIdentifier(FixedFormAmbiguities.getMatcherForKeywordsAfterIF()); if (!ConsumeIfPresent(tok::kw_THEN)) { // if-stmt if(Tok.isAtStartOfStatement()) { Diag.Report(getExpectedLoc(), diag::err_expected_executable_stmt); return StmtError(); } auto Result = Actions.ActOnIfStmt(Context, Loc, Condition, StmtConstructName, StmtLabel); if(Result.isInvalid()) return Result; // NB: Don't give the action stmt my label StmtLabel = nullptr; auto Action = ParseActionStmt(); Actions.ActOnEndIfStmt(Context, Loc, ConstructName(SourceLocation(), nullptr), nullptr); return Action.isInvalid()? StmtError() : Result; } // if-construct. return Actions.ActOnIfStmt(Context, Loc, Condition, StmtConstructName, StmtLabel); error: SkipUntilNextStatement(); return Actions.ActOnIfStmt(Context, Loc, Condition, StmtConstructName, StmtLabel); }
// ParsePrimaryExpr - Parse a primary expression. // // [R701]: // primary := // constant // or designator // or array-constructor // or structure-constructor // or function-reference // or type-param-inquiry // or type-param-name // or ( expr ) Parser::ExprResult Parser::ParsePrimaryExpr(bool IsLvalue) { ExprResult E; SourceLocation Loc = Tok.getLocation(); // FIXME: Add rest of the primary expressions. switch (Tok.getKind()) { default: if (isTokenIdentifier()) goto possible_keyword_as_ident; Diag.Report(getExpectedLoc(), diag::err_expected_expression); return ExprError(); case tok::error: Lex(); return ExprError(); case tok::l_paren: { ConsumeParen(); E = ParseExpression(); // complex constant. if(ConsumeIfPresent(tok::comma)) { if(E.isInvalid()) return E; auto ImPart = ParseExpectedFollowupExpression(","); if(ImPart.isInvalid()) return ImPart; E = Actions.ActOnComplexConstantExpr(Context, Loc, getMaxLocationOfCurrentToken(), E, ImPart); } ExpectAndConsume(tok::r_paren, 0, "", tok::r_paren); break; } case tok::l_parenslash : { return ParseArrayConstructor(); break; } case tok::logical_literal_constant: { std::string NumStr; CleanLiteral(Tok, NumStr); StringRef Data(NumStr); std::pair<StringRef, StringRef> StrPair = Data.split('_'); E = LogicalConstantExpr::Create(Context, getTokenRange(), StrPair.first, Context.LogicalTy); SetKindSelector(cast<ConstantExpr>(E.get()), StrPair.second); ConsumeToken(); break; } case tok::binary_boz_constant: case tok::octal_boz_constant: case tok::hex_boz_constant: { std::string NumStr; CleanLiteral(Tok, NumStr); StringRef Data(NumStr); std::pair<StringRef, StringRef> StrPair = Data.split('_'); E = BOZConstantExpr::Create(Context, Loc, getMaxLocationOfCurrentToken(), StrPair.first); SetKindSelector(cast<ConstantExpr>(E.get()), StrPair.second); ConsumeToken(); break; } case tok::char_literal_constant: { std::string NumStr; CleanLiteral(Tok, NumStr); E = CharacterConstantExpr::Create(Context, getTokenRange(), StringRef(NumStr), Context.CharacterTy); ConsumeToken(); // Possible substring if(IsPresent(tok::l_paren)) return ParseSubstring(E); break; } case tok::int_literal_constant: { std::string NumStr; CleanLiteral(Tok, NumStr); StringRef Data(NumStr); std::pair<StringRef, StringRef> StrPair = Data.split('_'); E = IntegerConstantExpr::Create(Context, getTokenRange(), StrPair.first); SetKindSelector(cast<ConstantExpr>(E.get()), StrPair.second); Lex(); break; } case tok::real_literal_constant: { std::string NumStr; CleanLiteral(Tok, NumStr); StringRef Data(NumStr); std::pair<StringRef, StringRef> StrPair = Data.split('_'); E = RealConstantExpr::Create(Context, getTokenRange(), NumStr, Context.RealTy); SetKindSelector(cast<ConstantExpr>(E.get()), StrPair.second); ConsumeToken(); break; } case tok::double_precision_literal_constant: { std::string NumStr; CleanLiteral(Tok, NumStr); // Replace the d/D exponent into e exponent for(size_t I = 0, Len = NumStr.length(); I < Len; ++I) { if(NumStr[I] == 'd' || NumStr[I] == 'D') { NumStr[I] = 'e'; break; } else if(NumStr[I] == '_') break; } StringRef Data(NumStr); std::pair<StringRef, StringRef> StrPair = Data.split('_'); E = RealConstantExpr::Create(Context, getTokenRange(), NumStr, Context.DoublePrecisionTy); SetKindSelector(cast<ConstantExpr>(E.get()), StrPair.second); ConsumeToken(); break; } case tok::identifier: possible_keyword_as_ident: E = Parser::ParseDesignator(IsLvalue); if (E.isInvalid()) return E; break; case tok::minus: Lex(); E = Parser::ParsePrimaryExpr(); if (E.isInvalid()) return E; E = Actions.ActOnUnaryExpr(Context, Loc, UnaryExpr::Minus, E); break; case tok::plus: Lex(); E = Parser::ParsePrimaryExpr(); if (E.isInvalid()) return E; E = Actions.ActOnUnaryExpr(Context, Loc, UnaryExpr::Plus, E); break; } return E; }