ExprResult Parser::ParseExpectedConditionExpression(const char *DiagAfter) { if (!ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, DiagAfter)) return ExprError(); ExprResult Condition = ParseExpectedFollowupExpression("("); if(Condition.isInvalid()) return Condition; if (!ExpectAndConsume(tok::r_paren)) return ExprError(); return Condition; }
/// ParseDesignator - Parse a designator. Return null if current token is not a /// designator. /// /// [R601]: /// designator := /// object-name /// or array-element /// or array-section /// or coindexed-named-object /// or complex-part-designator /// or structure-component /// or substring /// /// FIXME: substring for a character array ExprResult Parser::ParseDesignator(bool IsLvalue) { auto E = ParseNameOrCall(); struct ScopedFlag { bool value; bool &dest; ScopedFlag(bool &flag) : dest(flag) { value = flag; } ~ScopedFlag() { dest = value; } }; ScopedFlag Flag(DontResolveIdentifiers); if(DontResolveIdentifiersInSubExpressions) DontResolveIdentifiers = true; while(true) { if(!E.isUsable()) break; if(IsPresent(tok::l_paren)) { auto EType = E.get()->getType(); if(EType->isArrayType()) E = ParseArraySubscript(E); else if(EType->isCharacterType()) E = ParseSubstring(E); else { Diag.Report(Tok.getLocation(), diag::err_unexpected_lparen); return ExprError(); } } else if(IsPresent(tok::percent)) { auto EType = E.get()->getType(); if(EType->isRecordType()) E = ParseStructureComponent(E); else { Diag.Report(Tok.getLocation(), diag::err_unexpected_percent); return ExprError(); } } else if(IsPresent(tok::period)) { auto EType = E.get()->getType(); if(EType->isRecordType()) E = ParseStructureComponent(E); else { Diag.Report(Tok.getLocation(), diag::err_unexpected_period); return ExprError(); } } else break; } return E; }
void AssignmentExpression::analyze(AnalysisContext& context){ for(iter it = assignments.begin(); it != assignments.end(); it++){ AnalysisContext::ResolutionResult result = context.resolve(it->identifier); if(result.success && !result.isPlace){ it->offset = result.offset; }else if(result.isPlace){ context.reportError(ExprError("You cannot assign to an place!")); }else{ context.reportError(ExprError("Variable for assignment could not be resolved!")); } it->expr->analyze(context); } }
ExprResult Parser::ParseRecursiveCallExpression(SourceRange IDRange) { auto Func = Actions.CurrentContextAsFunction(); auto IDLoc = IDRange.Start; if(Func->isSubroutine()) { Diag.Report(IDLoc, diag::err_invalid_subroutine_use) << Func->getIdentifier() << getTokenRange(IDLoc); return ExprError(); } if(!Actions.CheckRecursiveFunction(IDLoc)) return ExprError(); if(!IsPresent(tok::l_paren)) return FunctionRefExpr::Create(Context, IDRange, Func); return ParseCallExpression(IDLoc, Func); }
ExprResult Parser::ParseExpectedExpression() { if(Tok.isAtStartOfStatement()) { Diag.Report(getExpectedLoc(), diag::err_expected_expression); return ExprError(); } return ParseExpression(); }
ExprResult Sema::ActOnDATAConstantExpr(ASTContext &C, SourceLocation RepeatLoc, ExprResult RepeatCount, ExprResult Value) { IntegerConstantExpr *RepeatExpr = nullptr; bool HasErrors = false; if(RepeatCount.isUsable()) { RepeatExpr = dyn_cast<IntegerConstantExpr>(RepeatCount.get()); if(!RepeatExpr || !RepeatExpr->getValue().isStrictlyPositive()) { Diags.Report(RepeatCount.get()->getLocation(), diag::err_expected_integer_gt_0) << RepeatCount.get()->getSourceRange(); HasErrors = true; RepeatExpr = nullptr; } } if(!CheckConstantExpression(Value.get())) HasErrors = true; if(HasErrors) return ExprError(); return RepeatExpr? RepeatedConstantExpr::Create(C, RepeatLoc, RepeatExpr, Value.take()) : Value; }
/// \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(); }
/// ParseTypeConstructorExpression - Parses a type constructor. ExprResult Parser::ParseTypeConstructor(SourceLocation IDLoc, RecordDecl *Record) { SmallVector<Expr*, 8> Arguments; SourceLocation RParenLoc = IDLoc; auto LParenLoc = Tok.getLocation(); auto E = ParseFunctionCallArgumentList(Arguments, RParenLoc); if(E.isInvalid()) return ExprError(); return Actions.ActOnTypeConstructorExpr(Context, IDLoc, LParenLoc, RParenLoc, Record, Arguments); }
/// ParseStructureComponent - Parse a structure component. /// /// R613: /// structure-component := /// designator % data-ref ExprResult Parser::ParseStructureComponent(ExprResult Target) { auto Loc = ConsumeToken(); auto ID = Tok.getIdentifierInfo(); auto IDLoc = Tok.getLocation(); if(!ExpectAndConsume(tok::identifier)) return ExprError(); return Actions.ActOnStructureComponentExpr(Context, Loc, IDLoc, ID, Target.get()); }
/// ParseCallExpression - Parse a call expression ExprResult Parser::ParseCallExpression(SourceLocation IDLoc, FunctionDecl *Function) { SmallVector<Expr*, 8> Arguments; auto Loc = Tok.getLocation(); SourceLocation RParenLoc = Loc; auto Result = ParseFunctionCallArgumentList(Arguments, RParenLoc); if(Result.isInvalid()) return ExprError(); return Actions.ActOnCallExpr(Context, Loc, RParenLoc, IDLoc, Function, Arguments); }
/// Parse the optional KIND or LEN selector. /// /// [R405]: /// kind-selector := /// ( [ KIND = ] scalar-int-initialization-expr ) /// [R425]: /// length-selector := /// ( [ LEN = ] type-param-value ) ExprResult Parser::ParseSelector(bool IsKindSel) { if (ConsumeIfPresent(IsKindSel ? tok::kw_KIND : tok::kw_LEN)) { if (!ExpectAndConsume(tok::equal)) return ExprError(); // TODO: We have a "REAL (KIND(10D0)) :: x" situation. } return ParseExpression(); }
/// 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(); }
/// ParseNameOrCall - Parse a name or a call expression ExprResult Parser::ParseNameOrCall() { auto IDInfo = Tok.getIdentifierInfo(); assert(IDInfo && "Token isn't an identifier"); auto IDRange = getTokenRange(); auto IDLoc = ConsumeToken(); if(DontResolveIdentifiers) return UnresolvedIdentifierExpr::Create(Context, IDRange, IDInfo); // [R504]: // object-name := // name auto Declaration = Actions.ResolveIdentifier(IDInfo); if(!Declaration) { if(IsPresent(tok::l_paren)) Declaration = Actions.ActOnImplicitFunctionDecl(Context, IDLoc, IDInfo); else Declaration = Actions.ActOnImplicitEntityDecl(Context, IDLoc, IDInfo); if(!Declaration) return ExprError(); } else { // INTEGER f // X = f(10) <-- implicit function declaration. if(IsPresent(tok::l_paren)) Declaration = Actions.ActOnPossibleImplicitFunctionDecl(Context, IDLoc, IDInfo, Declaration); } if(VarDecl *VD = dyn_cast<VarDecl>(Declaration)) { // FIXME: function returing array if(IsPresent(tok::l_paren) && VD->isFunctionResult() && isa<FunctionDecl>(Actions.CurContext)) { // FIXME: accessing function results from inner recursive functions return ParseRecursiveCallExpression(IDRange); } // the VarDecl is obtained from a NamedDecl which does not have a type // apply implicit typing rules in case VD does not have a type // FIXME: there should be a way to avoid re-applying the implicit rules // by returning a VarDecl instead of a NamedDecl when looking up a name in // the scope if (VD->getType().isNull()) Actions.ApplyImplicitRulesToArgument(VD,IDRange); return VarExpr::Create(Context, IDRange, VD); } else if(IntrinsicFunctionDecl *IFunc = dyn_cast<IntrinsicFunctionDecl>(Declaration)) { SmallVector<Expr*, 8> Arguments; SourceLocation RParenLoc = Tok.getLocation(); auto Result = ParseFunctionCallArgumentList(Arguments, RParenLoc); if(Result.isInvalid()) return ExprError(); return Actions.ActOnIntrinsicFunctionCallExpr(Context, IDLoc, IFunc, Arguments); } else if(FunctionDecl *Func = dyn_cast<FunctionDecl>(Declaration)) { // FIXME: allow subroutines, but errors in sema if(!IsPresent(tok::l_paren)) return FunctionRefExpr::Create(Context, IDRange, Func); if(!Func->isSubroutine()) { return ParseCallExpression(IDLoc, Func); } } else if(isa<SelfDecl>(Declaration) && isa<FunctionDecl>(Actions.CurContext)) return ParseRecursiveCallExpression(IDRange); else if(auto Record = dyn_cast<RecordDecl>(Declaration)) return ParseTypeConstructor(IDLoc, Record); Diag.Report(IDLoc, diag::err_expected_var); return ExprError(); }
// 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; }