bool Parser::ParseDerivedTypeComponentStmt() { // type-spec DeclSpec DS; if(ParseDeclarationTypeSpec(DS, true, false)) return true; // component-attr-spec if(ConsumeIfPresent(tok::comma)) { do { auto Kind = Tok.getKind(); auto Loc = Tok.getLocation(); auto ID = Tok.getIdentifierInfo(); if(!ExpectAndConsume(tok::identifier)) return true; if(Kind == tok::kw_POINTER) Actions.ActOnAttrSpec(Loc, DS, DeclSpec::AS_pointer); else if(Kind == tok::kw_DIMENSION) { if(ParseDimensionAttributeSpec(Loc, DS)) return true; } else { if(isAttributeSpec(Kind)) Diag.Report(Loc, diag::err_use_of_attr_spec_in_type_decl) << ID; else Diag.Report(Loc, diag::err_expected_attr_spec); if(!SkipUntil(tok::coloncolon, true, true)) return true; break; } } while(ConsumeIfPresent(tok::comma)); if(!ExpectAndConsume(tok::coloncolon)) return true; } else ConsumeIfPresent(tok::coloncolon); // component-decl-list do { auto IDLoc = Tok.getLocation(); auto ID = Tok.getIdentifierInfo(); if(!ExpectAndConsume(tok::identifier)) return true; DeclSpec ObjectDS(DS); if(ParseObjectArraySpec(IDLoc, ObjectDS)) return true; if(ParseObjectCharLength(IDLoc, ObjectDS)) return true; // FIXME: initialization expressions Actions.ActOnDerivedTypeFieldDecl(Context, ObjectDS, IDLoc, ID); } while(ConsumeIfPresent(tok::comma)); return false; }
/// ParseIMPLICITStmt - Parse the IMPLICIT statement. /// /// [R560]: /// implicit-stmt := /// IMPLICIT implicit-spec-list /// or IMPLICIT NONE Parser::StmtResult Parser::ParseIMPLICITStmt() { // Check if this is an assignment. if (IsNextToken(tok::equal)) return StmtResult(); auto Loc = ConsumeToken(); if (ConsumeIfPresent(tok::kw_NONE)) { auto Result = Actions.ActOnIMPLICIT(Context, Loc, StmtLabel); ExpectStatementEnd(); return Result; } SmallVector<Stmt*, 8> StmtList; while(true) { // FIXME: improved error recovery DeclSpec DS; if (ParseDeclarationTypeSpec(DS, false)) return StmtError(); if(!ExpectAndConsume(tok::l_paren)) { if(!SkipUntil(tok::l_paren)) break; } bool InnerError = false; while(true) { auto FirstLoc = Tok.getLocation(); auto First = Tok.getIdentifierInfo(); if(!ExpectAndConsume(tok::identifier, diag::err_expected_letter)) { if(!SkipUntil(tok::comma)) { InnerError = true; break; } continue; } if(First->getName().size() > 1) { Diag.Report(FirstLoc, diag::err_expected_letter); } const IdentifierInfo *Second = nullptr; if (ConsumeIfPresent(tok::minus)) { auto SecondLoc = Tok.getLocation(); Second = Tok.getIdentifierInfo(); if(!ExpectAndConsume(tok::identifier, diag::err_expected_letter)) { if(!SkipUntil(tok::comma)) { InnerError = true; break; } continue; } if(Second->getName().size() > 1) { Diag.Report(SecondLoc, diag::err_expected_letter); } } auto Stmt = Actions.ActOnIMPLICIT(Context, Loc, DS, std::make_pair(First, Second), nullptr); if(Stmt.isUsable()) StmtList.push_back(Stmt.take()); if(ConsumeIfPresent(tok::comma)) continue; break; } if(InnerError && Tok.isAtStartOfStatement()) break; if(!ExpectAndConsume(tok::r_paren)) { if(!SkipUntil(tok::r_paren)) break; } if(Tok.isAtStartOfStatement()) break; if(!ExpectAndConsume(tok::comma)) { if(!SkipUntil(tok::comma)) break; } } ExpectStatementEnd(); return Actions.ActOnCompoundStmt(Context, Loc, StmtList, StmtLabel); }
/// ParseTypeDeclarationStmt - Parse a type-declaration-stmt construct. /// /// [R501]: /// type-declaration-stmt := /// declaration-type-spec [ [ , attr-spec ] ... :: ] entity-decl-list bool Parser::ParseTypeDeclarationStmt(SmallVectorImpl<DeclResult> &Decls) { DeclSpec DS; if (ParseDeclarationTypeSpec(DS)) return true; while (ConsumeIfPresent(tok::comma)) { // [R502]: // attr-spec := // access-spec // or ALLOCATABLE // or ASYNCHRONOUS // or CODIMENSION lbracket coarray-spec rbracket // or CONTIGUOUS // or DIMENSION ( array-spec ) // or EXTERNAL // or INTENT ( intent-spec ) // or INTRINSIC // or language-binding-spec // TODO! // or OPTIONAL // or PARAMETER // or POINTER // or PROTECTED // or SAVE // or TARGET // or VALUE // or VOLATILE auto Kind = Tok.getKind(); auto Loc = Tok.getLocation(); if(!ExpectAndConsume(tok::identifier)) { goto error; } switch (Kind) { default: Diag.ReportError(Loc, "unknown attribute specification"); goto error; case tok::kw_ALLOCATABLE: Actions.ActOnAttrSpec(Loc, DS, DeclSpec::AS_allocatable); break; case tok::kw_ASYNCHRONOUS: Actions.ActOnAttrSpec(Loc, DS, DeclSpec::AS_asynchronous); break; case tok::kw_CODIMENSION: Actions.ActOnAttrSpec(Loc, DS, DeclSpec::AS_codimension); // FIXME: Parse the coarray-spec. break; case tok::kw_CONTIGUOUS: Actions.ActOnAttrSpec(Loc, DS, DeclSpec::AS_contiguous); break; case tok::kw_DIMENSION: if (ParseDimensionAttributeSpec(Loc, DS)) goto error; break; case tok::kw_EXTERNAL: Actions.ActOnAttrSpec(Loc, DS, DeclSpec::AS_external); break; case tok::kw_INTENT: // FIXME: if(!ExpectAndConsume(tok::l_paren)) goto error; switch (Tok.getKind()) { default: Diag.ReportError(Tok.getLocation(), "invalid INTENT specifier"); goto error; case tok::kw_IN: Actions.ActOnIntentSpec(Loc, DS, DeclSpec::IS_in); break; case tok::kw_OUT: Actions.ActOnIntentSpec(Loc, DS, DeclSpec::IS_out); break; case tok::kw_INOUT: Actions.ActOnIntentSpec(Loc, DS, DeclSpec::IS_inout); break; } Lex(); if(!ExpectAndConsume(tok::r_paren)) goto error; break; case tok::kw_INTRINSIC: Actions.ActOnAttrSpec(Loc, DS, DeclSpec::AS_intrinsic); break; case tok::kw_OPTIONAL: Actions.ActOnAttrSpec(Loc, DS, DeclSpec::AS_optional); break; case tok::kw_PARAMETER: Actions.ActOnAttrSpec(Loc, DS, DeclSpec::AS_parameter); break; case tok::kw_POINTER: Actions.ActOnAttrSpec(Loc, DS, DeclSpec::AS_pointer); break; case tok::kw_PROTECTED: Actions.ActOnAttrSpec(Loc, DS, DeclSpec::AS_protected); break; case tok::kw_SAVE: Actions.ActOnAttrSpec(Loc, DS, DeclSpec::AS_save); break; case tok::kw_TARGET: Actions.ActOnAttrSpec(Loc, DS, DeclSpec::AS_target); break; case tok::kw_VALUE: Actions.ActOnAttrSpec(Loc, DS, DeclSpec::AS_value); break; case tok::kw_VOLATILE: Actions.ActOnAttrSpec(Loc, DS, DeclSpec::AS_volatile); break; // Access Control Specifiers case tok::kw_PUBLIC: Actions.ActOnAccessSpec(Loc, DS, DeclSpec::AC_public); break; case tok::kw_PRIVATE: Actions.ActOnAccessSpec(Loc, DS, DeclSpec::AC_private); break; } } ConsumeIfPresent(tok::coloncolon); if (ParseEntityDeclarationList(DS, Decls)) return true; return false; error: return true; }