Пример #1
0
// FIXME: Fortran 2008 stuff.
/// ParseDerivedTypeDefinitionStmt - Parse a type or a class definition.
///
/// [R422]:
///   derived-type-def :=
///     derived-type-stmt
///     [ private-sequence-stmt ] ...
///     component-def-stmt
///     [ component-def-stmt ] ...
///     end-type-stmt
///
/// [R423]:
///   derived-type-stmt :=
///     TYPE [ [ , access-spec ] :: ] type-name
///
/// [R424]:
///   private-sequence-stmt :=
///     PRIVATE or SEQUENCE
///
/// [R425]:
///   component-def-stmt :=
///     type-spec [ [ component-attr-spec-list ] :: ] component-decl-list
///
/// [R426]:
///   component-attr-spec-list :=
///     POINTER or
///     DIMENSION( component-array-spec )
///
/// [R427]:
///   component-array-spec :=
///     explicit-shape-spec-list or
///     deffered-shape-spec-list
///
/// [R428]:
///   component-decl :=
///     component-name [ ( component-array-spec ) ]
///     [ * char-length ] [ component-initialization ]
///
/// [R429]:
///   component-initialization :=
///     = initialization-expr or
///     => NULL()
///
/// [R430]:
///   end-type-stmt :=
///     END TYPE [ type-name ]
bool Parser::ParseDerivedTypeDefinitionStmt() {
  bool IsClass = Tok.is(tok::kw_CLASS);
  auto Loc = ConsumeToken();

  if(ConsumeIfPresent(tok::comma)) {
    //FIXME: access-spec
  }
  ConsumeIfPresent(tok::coloncolon);

  auto ID = Tok.getIdentifierInfo();
  auto IDLoc = Tok.getLocation();
  if(!ExpectAndConsume(tok::identifier)) {
    SkipUntilNextStatement();
    return true;
  } else
    ExpectStatementEnd();

  Actions.ActOnDerivedTypeDecl(Context, Loc, IDLoc, ID);

  // FIXME: private
  if(Tok.is(tok::kw_SEQUENCE)) {
    Actions.ActOnDerivedTypeSequenceStmt(Context, ConsumeToken());
    ExpectStatementEnd();
  }

  bool Done = false;
  while(!Done) {
    switch(Tok.getKind()) {
    case tok::kw_TYPE:
    case tok::kw_CLASS:
    case tok::kw_INTEGER:
    case tok::kw_REAL:
    case tok::kw_COMPLEX:
    case tok::kw_CHARACTER:
    case tok::kw_BYTE:
    case tok::kw_LOGICAL:
    case tok::kw_DOUBLEPRECISION:
    case tok::kw_DOUBLECOMPLEX:
      if(ParseDerivedTypeComponentStmt())
        SkipUntilNextStatement();
      else ExpectStatementEnd();
      break;
    default:
      Done = true;
      break;
    }
  }

  ParseEndTypeStmt();

  Actions.ActOnEndDerivedTypeDecl(Context);
  return false;
error:
  return true;
}
Пример #2
0
Parser::StmtResult Parser::ParseCaseStmt() {
  auto Loc = ConsumeToken();
  if(ConsumeIfPresent(tok::kw_DEFAULT)) {
    ParseTrailingConstructName();
    return Actions.ActOnCaseDefaultStmt(Context, Loc, StmtConstructName, StmtLabel);
  }

  SmallVector<Expr*, 8> Values;

  ExpectAndConsume(tok::l_paren);
  do {
    auto ColonLoc = Tok.getLocation();
    if(ConsumeIfPresent(tok::colon)) {
      auto E = ParseExpectedFollowupExpression(":");
      if(E.isInvalid()) goto error;
      if(E.isUsable())
        Values.push_back(RangeExpr::Create(Context, ColonLoc, nullptr, E.get()));
    } else {
      auto E = ParseExpectedExpression();
      if(E.isInvalid()) goto error;
      ColonLoc = Tok.getLocation();
      if(ConsumeIfPresent(tok::colon)) {
        if(!(IsPresent(tok::comma) || IsPresent(tok::r_paren))) {
          auto E2 = ParseExpectedFollowupExpression(":");
          if(E2.isInvalid()) goto error;
          if(E.isUsable() || E2.isUsable())
            Values.push_back(RangeExpr::Create(Context, ColonLoc, E.get(), E2.get()));
        } else {
          if(E.isUsable())
            Values.push_back(RangeExpr::Create(Context, ColonLoc, E.get(), nullptr));
        }
      } else {
        if(E.isUsable())
          Values.push_back(E.get());
      }
    }
  } while(ConsumeIfPresent(tok::comma));

  if(ExpectAndConsume(tok::r_paren)) {
    ParseTrailingConstructName();
  } else SkipUntilNextStatement();

  return Actions.ActOnCaseStmt(Context, Loc, Values, StmtConstructName, StmtLabel);

error:
  if(SkipUntil(tok::r_paren)) {
    ParseTrailingConstructName();
  } else SkipUntilNextStatement();
  return Actions.ActOnCaseStmt(Context, Loc, Values, StmtConstructName, StmtLabel);
}
Пример #3
0
Parser::StmtResult Parser::ParseSelectCaseStmt() {
  auto Loc = ConsumeToken();

  ExprResult Operand;
  if(ExpectAndConsume(tok::l_paren)) {
    Operand = ParseExpectedFollowupExpression("(");
    if(Operand.isUsable()) {
      if(!ExpectAndConsume(tok::r_paren))
        SkipUntilNextStatement();
    } else SkipUntilNextStatement();
  } else SkipUntilNextStatement();

  return Actions.ActOnSelectCaseStmt(Context, Loc, Operand, StmtConstructName, StmtLabel);
}
Пример #4
0
/// ParseEQUIVALENCEStmt - Parse the EQUIVALENCE statement.
///
///   [R554]:
///     equivalence-stmt :=
///         EQUIVALENCE equivalence-set-list
Parser::StmtResult Parser::ParseEQUIVALENCEStmt() {
  // Check if this is an assignment.
  if (IsNextToken(tok::equal))
    return StmtResult();

  auto Loc = ConsumeToken();
  SmallVector<Stmt*, 8> StmtList;
  SmallVector<Expr*, 8> ObjectList;

  bool OuterError = false;
  while(true) {
    auto PartLoc = Tok.getLocation();
    if(!ExpectAndConsume(tok::l_paren)) {
      if(!SkipUntil(tok::l_paren)) {
        OuterError = true;
        break;
      }
    }

    ObjectList.clear();
    bool InnerError = false;
    do {
      auto E = ParseExpectedExpression();
      if(E.isInvalid()) {
        InnerError = true;
        break;
      } else if(E.isUsable())
        ObjectList.push_back(E.get());
    } while(ConsumeIfPresent(tok::comma));

    auto S = Actions.ActOnEQUIVALENCE(Context, Loc, PartLoc, ObjectList, nullptr);
    if(S.isUsable())
      StmtList.push_back(S.get());

    if(InnerError) {
      if(!SkipUntil(tok::r_paren, true, true)) {
        OuterError = true;
        break;
      }
    }
    if(!ExpectAndConsume(tok::r_paren)) {
      if(!SkipUntil(tok::r_paren)) {
        OuterError = true;
        break;
      }
    }

    if(ConsumeIfPresent(tok::comma)) continue;
    if(IsPresent(tok::l_paren)) {
      ExpectAndConsume(tok::comma);
      continue;
    }
    break;
  }

  if(OuterError) SkipUntilNextStatement();
  else ExpectStatementEnd();

  return Actions.ActOnCompoundStmt(Context, Loc, StmtList, StmtLabel);
}
Пример #5
0
Parser::StmtResult Parser::ParseAmbiguousAssignmentStmt() {
  ParseStatementLabel();
  auto S = ParseAssignmentStmt();
  if(S.isInvalid()) SkipUntilNextStatement();
  else ExpectStatementEnd();
  return S;
}
Пример #6
0
/// ParseCOMMONStmt - Parse the COMMON statement.
///
///   [5.5.2] R557:
///     common-stmt :=
///         COMMON #
///         # [ / [common-block-name] / ] common-block-object-list #
///         # [ [,] / [common-block-name / #
///         #   common-block-object-list ] ...
Parser::StmtResult Parser::ParseCOMMONStmt() {
  // Check if this is an assignment.
  if (IsNextToken(tok::equal))
    return StmtResult();

  auto Loc = ConsumeToken();
  SmallVector<Stmt*, 8> StmtList;
  SmallVector<Expr*, 8> ObjectList;

  SourceLocation BlockIDLoc;
  const IdentifierInfo *BlockID = nullptr;

  bool Error = false;
  do {
    if(ConsumeIfPresent(tok::slash)) {
      if(ConsumeIfPresent(tok::slash))
        BlockID = nullptr;
      else {
        BlockIDLoc = Tok.getLocation();
        BlockID = Tok.getIdentifierInfo();
        if(!ExpectAndConsume(tok::identifier)) {
          Error = true;
          break;
        }
        if(!ExpectAndConsume(tok::slash)) {
          Error = true;
          break;
        }
      }
    } else if(ConsumeIfPresent(tok::slashslash))
      BlockID = nullptr;

    auto IDLoc = Tok.getLocation();
    auto IDInfo = Tok.getIdentifierInfo();
    SmallVector<ArraySpec*, 8> Dimensions;

    if(!ExpectAndConsume(tok::identifier)) {
      Error = true;
      break;
    }
    if(IsPresent(tok::l_paren)) {
      if(ParseArraySpec(Dimensions)) {
        Error = true;
        break;
      }
    }

    Actions.ActOnCOMMON(Context, Loc, BlockIDLoc,
                        IDLoc, BlockID, IDInfo,
                        Dimensions);
  } while(ConsumeIfPresent(tok::comma));


  if(Error) SkipUntilNextStatement();
  else ExpectStatementEnd();

  return Actions.ActOnCompoundStmt(Context, Loc, StmtList, StmtLabel);
}
Пример #7
0
Parser::StmtResult Parser::ParseDoStmt() {
  auto Loc = ConsumeToken();
  auto CurStmtLoc = LocFirstStmtToken;

  ExprResult TerminalStmt;
  VarExpr *DoVar = nullptr;
  ExprResult E1, E2, E3;
  auto EqLoc = Loc;

  if(IsPresent(tok::int_literal_constant)) {
    TerminalStmt = ParseStatementLabelReference();
    if(TerminalStmt.isInvalid()) return StmtError();
  }
  bool isDo = ConsumeIfPresent(tok::comma);
  if(isDo && IsPresent(tok::kw_WHILE))
    return ParseDoWhileStmt(isDo);

  // the do var
  auto IDInfo = Tok.getIdentifierInfo();
  auto IDRange = getTokenRange();
  auto IDLoc = Tok.getLocation();
  if(!ExpectAndConsume(tok::identifier))
    goto error;

  EqLoc = getMaxLocationOfCurrentToken();
  if(Features.FixedForm && !isDo && IsPresent(tok::l_paren))
    return ReparseAmbiguousAssignmentStatement();
  if(!ExpectAndConsume(tok::equal))
    goto error;
  E1 = ParseExpectedFollowupExpression("=");
  if(E1.isInvalid()) goto error;
  if(Features.FixedForm && !isDo && Tok.isAtStartOfStatement())
    return ReparseAmbiguousAssignmentStatement(CurStmtLoc);
  if(!ExpectAndConsume(tok::comma)) goto error;
  E2 = ParseExpectedFollowupExpression(",");
  if(E2.isInvalid()) goto error;
  if(ConsumeIfPresent(tok::comma)) {
    E3 = ParseExpectedFollowupExpression(",");
    if(E3.isInvalid()) goto error;
  }

  if(auto VD = Actions.ExpectVarRefOrDeclImplicitVar(IDLoc, IDInfo))
    DoVar = VarExpr::Create(Context, IDRange, VD);
  return Actions.ActOnDoStmt(Context, Loc, EqLoc, TerminalStmt,
                             DoVar, E1, E2, E3, StmtConstructName, StmtLabel);
error:
  if(IDInfo) {
    if(auto VD = Actions.ExpectVarRefOrDeclImplicitVar(IDLoc, IDInfo))
      DoVar = VarExpr::Create(Context, IDRange, VD);
  }
  SkipUntilNextStatement();
  return Actions.ActOnDoStmt(Context, Loc, EqLoc, TerminalStmt,
                             DoVar, E1, E2, E3, StmtConstructName, StmtLabel);
}
Пример #8
0
/// ParsePARAMETERStmt - Parse the PARAMETER statement.
///
///   [R548]:
///     parameter-stmt :=
///         PARAMETER ( named-constant-def-list )
Parser::StmtResult Parser::ParsePARAMETERStmt() {
  // Check if this is an assignment.
  if (IsNextToken(tok::equal))
    return StmtResult();

  auto Loc = ConsumeToken();

  SmallVector<Stmt*, 8> StmtList;

  if(!ExpectAndConsume(tok::l_paren)) {
    if(!SkipUntil(tok::l_paren))
      return StmtError();
  }

  while(true) {
    auto IDLoc = Tok.getLocation();
    auto II = Tok.getIdentifierInfo();
    if(!ExpectAndConsume(tok::identifier)) {
      if(!SkipUntil(tok::comma)) break;
      else continue;
    }

    auto EqualLoc = Tok.getLocation();
    if(!ExpectAndConsume(tok::equal)) {
      if(!SkipUntil(tok::comma)) break;
      else continue;
    }

    ExprResult ConstExpr = ParseExpression();
    if(ConstExpr.isUsable()) {
      auto Stmt = Actions.ActOnPARAMETER(Context, Loc, EqualLoc,
                                         IDLoc, II,
                                         ConstExpr, nullptr);
      if(Stmt.isUsable())
        StmtList.push_back(Stmt.take());
    }

    if(ConsumeIfPresent(tok::comma))
      continue;
    if(isTokenIdentifier() && !Tok.isAtStartOfStatement()) {
      ExpectAndConsume(tok::comma);
      continue;
    }
    break;
  }

  if(!ExpectAndConsume(tok::r_paren))
    SkipUntilNextStatement();

  return Actions.ActOnCompoundStmt(Context, Loc, StmtList, StmtLabel);
}
Пример #9
0
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);
}
Пример #10
0
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);
}
Пример #11
0
// FIXME: fixed-form THENconstructname
Parser::StmtResult Parser::ParseElseIfStmt() {
  auto Loc = ConsumeToken();
  ExprResult Condition;
  if (!ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "ELSE 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 (!ExpectAndConsumeFixedFormAmbiguous(tok::kw_THEN, diag::err_expected_kw, "THEN"))
    goto error;
  ParseTrailingConstructName();
  return Actions.ActOnElseIfStmt(Context, Loc, Condition, StmtConstructName, StmtLabel);
error:
  SkipUntilNextStatement();
  return Actions.ActOnElseIfStmt(Context, Loc, Condition, StmtConstructName, StmtLabel);
}
Пример #12
0
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);
}
Пример #13
0
/// ParseSAVEStmt - Parse the SAVE statement.
///
///   [R543]:
///     save-stmt :=
///         SAVE [ [::] saved-entity-list ]
Parser::StmtResult Parser::ParseSAVEStmt() {
  // Check if this is an assignment.
  if (IsNextToken(tok::equal))
    return StmtResult();

  auto Loc = ConsumeToken();
  if(Tok.isAtStartOfStatement())
    return Actions.ActOnSAVE(Context, Loc, StmtLabel);

  bool IsSaveStmt = ConsumeIfPresent(tok::coloncolon);
  SmallVector<Stmt *,8> StmtList;
  bool ListParsedOk = true;

  auto IDLoc = Tok.getLocation();
  auto II = Tok.getIdentifierInfo();
  StmtResult Stmt;
  if(ConsumeIfPresent(tok::slash)) {
    IDLoc = Tok.getLocation();
    II = Tok.getIdentifierInfo();
    if(ExpectAndConsume(tok::identifier)) {
      if(!ExpectAndConsume(tok::slash))
        ListParsedOk = false;
      Stmt = Actions.ActOnSAVECommonBlock(Context, Loc, IDLoc, II);
    }
    else ListParsedOk = false;
  }
  else if(ExpectAndConsume(tok::identifier)) {
    if(!IsSaveStmt && Features.FixedForm && (IsPresent(tok::equal) || IsPresent(tok::l_paren)))
      return ReparseAmbiguousAssignmentStatement();
    Stmt = Actions.ActOnSAVE(Context, Loc, IDLoc, II, nullptr);
  } else ListParsedOk = false;

  if(Stmt.isUsable())
    StmtList.push_back(Stmt.get());
  if(ListParsedOk) {
    while(ConsumeIfPresent(tok::comma)) {
      IDLoc = Tok.getLocation();
      II = Tok.getIdentifierInfo();
      if(ConsumeIfPresent(tok::slash)) {
        IDLoc = Tok.getLocation();
        II = Tok.getIdentifierInfo();
        if(!ExpectAndConsume(tok::identifier)) {
          ListParsedOk = false;
          break;
        }
        if(!ExpectAndConsume(tok::slash)) {
          ListParsedOk = false;
          break;
        }
        Stmt = Actions.ActOnSAVECommonBlock(Context, Loc, IDLoc, II);
      }
      else if(ExpectAndConsume(tok::identifier))
        Stmt = Actions.ActOnSAVE(Context, Loc, IDLoc, II, nullptr);
      else {
        ListParsedOk = false;
        break;
      }

      if(Stmt.isUsable())
        StmtList.push_back(Stmt.get());
    }
  }

  if(ListParsedOk) ExpectStatementEnd();
  else SkipUntilNextStatement();

  return Actions.ActOnCompoundStmt(Context, Loc, StmtList, StmtLabel);
}