Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
/// 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);
}
Ejemplo n.º 3
0
/// 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;
}