コード例 #1
0
ファイル: ParseExec.cpp プロジェクト: carlobertolli/flang
Parser::StmtResult Parser::ParseWriteStmt() {
  SourceLocation Loc = ConsumeToken();

  // clist
  if(!ExpectAndConsume(tok::l_paren))
    return StmtError();

  UnitSpec *US = nullptr;
  FormatSpec *FS = nullptr;

  US = ParseUNITSpec(false);
  if(ConsumeIfPresent(tok::comma)) {
    bool IsFormatLabeled = false;
    if(ConsumeIfPresent(tok::kw_FMT)) {
      if(!ExpectAndConsume(tok::equal))
        return StmtError();
      IsFormatLabeled = true;
    }
    FS = ParseFMTSpec(IsFormatLabeled);
  }

  if(!ExpectAndConsume(tok::r_paren))
    return StmtError();

  // iolist
  SmallVector<ExprResult, 4> OutputItemList;
  ParseIOList(OutputItemList);

  return Actions.ActOnWriteStmt(Context, Loc, US, FS, OutputItemList, StmtLabel);
}
コード例 #2
0
ファイル: ParseSpecStmt.cpp プロジェクト: carlobertolli/flang
/// 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);
}
コード例 #3
0
ファイル: ParseExpr.cpp プロジェクト: ctgriffiths/flang
/// FIXME: todo implied-do
ExprResult Parser::ParseArrayConstructor() {
  auto Loc = ConsumeParenSlash();
  SourceLocation EndLoc = Tok.getLocation();

  SmallVector<Expr*, 16> ExprList;
  if(ConsumeIfPresent(tok::slashr_paren))
    return Actions.ActOnArrayConstructorExpr(Context, Loc, EndLoc, ExprList);
  do {
    auto E = ParseExpectedExpression();
    if(E.isInvalid())
      goto error;
    if(E.isUsable())
      ExprList.push_back(E.get());
  } while(ConsumeIfPresent(tok::comma));

  EndLoc = Tok.getLocation();
  if(!ExpectAndConsume(tok::slashr_paren))
    goto error;

  return Actions.ActOnArrayConstructorExpr(Context, Loc, EndLoc, ExprList);
error:
  EndLoc = Tok.getLocation();
  SkipUntil(tok::slashr_paren);
  return Actions.ActOnArrayConstructorExpr(Context, Loc, EndLoc, ExprList);
}
コード例 #4
0
ファイル: ParseSpecStmt.cpp プロジェクト: carlobertolli/flang
/// 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);
}
コード例 #5
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;
}
コード例 #6
0
ファイル: ParseExec.cpp プロジェクト: carlobertolli/flang
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);
}
コード例 #7
0
ファイル: ParseExpr.cpp プロジェクト: ctgriffiths/flang
/// ParseDataReference - Parse a data reference.
///
///   R611:
///     data-ref :=
///         part-ref [ % part-ref ] ...
ExprResult Parser::ParseDataReference() {
  std::vector<ExprResult> Exprs;

  do {
    ExprResult E = ParsePartReference();
    if (E.isInvalid()) return E;
    Exprs.push_back(E);
  } while (ConsumeIfPresent(tok::percent) || ConsumeIfPresent(tok::period));

  return Actions.ActOnDataReference(Exprs);
}
コード例 #8
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;
}
コード例 #9
0
ファイル: ParseExec.cpp プロジェクト: carlobertolli/flang
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
ファイル: ParseExec.cpp プロジェクト: carlobertolli/flang
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);
}
コード例 #11
0
bool Parser::ParseCharacterStarLengthSpec(DeclSpec &DS) {
  ExprResult Len;
  if(ConsumeIfPresent(tok::l_paren)) {
    if(ConsumeIfPresent(tok::star)) {
      DS.setStartLengthSelector();
    } else Len = ParseExpectedFollowupExpression("(");
    if(!ExpectAndConsume(tok::r_paren))
      return true;
  }
  else Len = ParseExpectedFollowupExpression("*");

  if(Len.isInvalid()) return true;
  if(Len.isUsable())  DS.setLengthSelector(Len.take());
  return false;
}
コード例 #12
0
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;
}
コード例 #13
0
ファイル: ParseExec.cpp プロジェクト: carlobertolli/flang
void Parser::ParseIOList(SmallVectorImpl<ExprResult> &List) {
  while(!Tok.isAtStartOfStatement()) {
    auto E = ParseExpression();
    if(E.isUsable()) List.push_back(E);
    if(!ConsumeIfPresent(tok::comma))
      break;
  }
}
コード例 #14
0
/// 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();
}
コード例 #15
0
ファイル: ParseExec.cpp プロジェクト: carlobertolli/flang
UnitSpec *Parser::ParseUNITSpec(bool IsLabeled) {
  auto Loc = Tok.getLocation();
  if(!ConsumeIfPresent(tok::star)) {
    auto E = ParseExpression();
    if(!E.isInvalid())
      return Actions.ActOnUnitSpec(Context, E, Loc, IsLabeled);
  }
  return Actions.ActOnStarUnitSpec(Context, Loc, IsLabeled);
}
コード例 #16
0
ファイル: ParseExpr.cpp プロジェクト: ctgriffiths/flang
// ParseLevel5Expr - Level-5 expressions are level-4 expressions optionally
// involving the logical operators.
//
//   R717:
//     level-5-expr :=
//         [ level-5-expr equiv-op ] equiv-operand
//   R716:
//     equiv-operand :=
//         [ equiv-operand or-op ] or-operand
//   R715:
//     or-operand :=
//         [ or-operand and-op ] and-operand
//   R714:
//     and-operand :=
//         [ not-op ] level-4-expr
//         
//   R718:
//     not-op :=
//         .NOT.
//   R719:
//     and-op :=
//         .AND.
//   R720:
//     or-op :=
//         .OR.
//   R721:
//     equiv-op :=
//         .EQV.
//      or .NEQV.
Parser::ExprResult Parser::ParseAndOperand() {
  SourceLocation NotLoc = Tok.getLocation();
  bool Negate = ConsumeIfPresent(tok::kw_NOT);

  ExprResult E = ParseLevel4Expr();
  if (E.isInvalid()) return E;

  if (Negate)
    E = Actions.ActOnUnaryExpr(Context, NotLoc, UnaryExpr::Not, E);
  return E;
}
コード例 #17
0
ファイル: ParseSpecStmt.cpp プロジェクト: carlobertolli/flang
/// ParseDIMENSIONStmt - Parse the DIMENSION statement.
///
///   [R535]:
///     dimension-stmt :=
///         DIMENSION [::] array-name ( array-spec ) #
///         # [ , array-name ( array-spec ) ] ...
Parser::StmtResult Parser::ParseDIMENSIONStmt() {
  // Check if this is an assignment.
  if (IsNextToken(tok::equal))
    return StmtResult();

  auto Loc = ConsumeToken();
  ConsumeIfPresent(tok::coloncolon);

  SmallVector<Stmt*, 8> StmtList;
  SmallVector<ArraySpec*, 4> Dimensions;
  while (true) {
    auto IDLoc = Tok.getLocation();
    auto II = Tok.getIdentifierInfo();
    if(!ExpectAndConsume(tok::identifier)) {
      if(!SkipUntil(tok::comma, tok::identifier, true, true)) break;
      if(ConsumeIfPresent(tok::comma)) continue;
      else {
        IDLoc = Tok.getLocation();
        II = Tok.getIdentifierInfo();
        ConsumeToken();
      }
    }

    // FIXME: improve error recovery
    Dimensions.clear();
    if(ParseArraySpec(Dimensions)) return StmtError();

    auto Stmt = Actions.ActOnDIMENSION(Context, Loc, IDLoc, II,
                                       Dimensions, nullptr);
    if(Stmt.isUsable()) StmtList.push_back(Stmt.take());

    if(Tok.isAtStartOfStatement()) break;
    if(!ExpectAndConsume(tok::comma)) {
      if(!SkipUntil(tok::comma)) break;
    }
  }

  return Actions.ActOnCompoundStmt(Context, Loc, StmtList, StmtLabel);
}
コード例 #18
0
ファイル: ParseSpecStmt.cpp プロジェクト: carlobertolli/flang
/// ParseINTRINSICStmt - Parse the INTRINSIC statement.
///
///   [R1216]:
///     intrinsic-stmt :=
///         INTRINSIC [::] intrinsic-procedure-name-list
Parser::StmtResult Parser::ParseINTRINSICStmt(bool IsActuallyExternal) {
  // Check if this is an assignment.
  if (IsNextToken(tok::equal))
    return StmtResult();

  auto Loc = ConsumeToken();
  ConsumeIfPresent(tok::coloncolon);

  SmallVector<Stmt *,8> StmtList;

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

    auto Stmt = IsActuallyExternal?
                  Actions.ActOnEXTERNAL(Context, Loc, IDLoc,
                                        II, nullptr):
                  Actions.ActOnINTRINSIC(Context, Loc, IDLoc,
                                         II, nullptr);
    if(Stmt.isUsable())
      StmtList.push_back(Stmt.take());

    if(Tok.isAtStartOfStatement()) break;
    if(!ExpectAndConsume(tok::comma)) {
      if(!SkipUntil(tok::comma)) break;
    }
  }

  return Actions.ActOnCompoundStmt(Context, Loc, StmtList, StmtLabel);
}
コード例 #19
0
ファイル: ParseSpecStmt.cpp プロジェクト: carlobertolli/flang
/// 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);
}
コード例 #20
0
ファイル: ParseExpr.cpp プロジェクト: ctgriffiths/flang
ExprResult Parser::ParseArraySection(const char *PunctuationTok) {
  ExprResult LB, UB, Stride;
  bool Range = false;

  auto ColonLoc = Tok.getLocation();
  if(ConsumeIfPresent(tok::colon)) {
    Range = true;
    if(!IsPresent(tok::colon) && !IsPresent(tok::comma) && !IsPresent(tok::r_paren)) {
      UB = ParseExpectedFollowupExpression(":");
      if(UB.isInvalid())
        return UB;
    }
  } else {
    LB = ParseExpectedFollowupExpression(PunctuationTok);
    if(LB.isInvalid())
      return LB;
    ColonLoc = Tok.getLocation();
    if(ConsumeIfPresent(tok::colon)) {
      Range = true;
      if(!IsPresent(tok::colon) && !IsPresent(tok::comma) && !IsPresent(tok::r_paren)) {
        UB = ParseExpectedFollowupExpression(":");
        if(UB.isInvalid())
          return UB;
      }
    }
  }
  if(ConsumeIfPresent(tok::colon)) {
    Stride = ParseExpectedFollowupExpression(":");
    if(Stride.isInvalid())
      return Stride;
  }
  if(Stride.isUsable())
    return StridedRangeExpr::Create(Context, ColonLoc, LB.get(),
                                    UB.get(), Stride.get());
  if(Range)
    return RangeExpr::Create(Context, ColonLoc, LB.get(), UB.get());
  return LB;
}
コード例 #21
0
ファイル: ParseExpr.cpp プロジェクト: ctgriffiths/flang
/// 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();
}
コード例 #22
0
ファイル: ParseExec.cpp プロジェクト: carlobertolli/flang
/// 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);
}
コード例 #23
0
ファイル: ParseExpr.cpp プロジェクト: ctgriffiths/flang
/// ParseSubstring - Parse a substring.
///
///   R608:
///     substring :=
///         parent-string ( substring-range )
///   R609:
///     parent-string :=
///         scalar-variable-name
///      or array-element
///      or coindexed-named-object
///      or scalar-structure-component
///      or scalar-constant
///   R610:
///     substring-range :=
///         [ scalar-int-expr ] : [ scalar-int-expr ]
ExprResult Parser::ParseSubstring(ExprResult Target) {
  ExprResult StartingPoint, EndPoint;
  auto Loc = ConsumeParen();

  if(!ConsumeIfPresent(tok::colon)) {
    StartingPoint = ParseExpectedFollowupExpression("(");
    if(StartingPoint.isInvalid())
      SkipUntil(tok::colon, true, true);
    Loc = Tok.getLocation();
    if(!ExpectAndConsume(tok::colon, 0, "", tok::r_paren))
      goto done;
  }

  if(!ConsumeIfPresent(tok::r_paren)) {
    EndPoint = ParseExpectedFollowupExpression(":");
    if(EndPoint.isInvalid())
      SkipUntil(tok::r_paren, true, true);
    ExpectAndConsume(tok::r_paren, 0, "", tok::r_paren);
  }

done:
  return Actions.ActOnSubstringExpr(Context, Loc, Target.get(),
                                    StartingPoint.get(), EndPoint.get());
}
コード例 #24
0
bool Parser::ParseEntityDeclarationList(DeclSpec &DS,
                                        SmallVectorImpl<DeclResult> &Decls) {
  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;
    Decls.push_back(Actions.ActOnEntityDecl(Context, ObjectDS, IDLoc, ID));

  } while(ConsumeIfPresent(tok::comma));
  return false;
}
コード例 #25
0
ファイル: ParseExec.cpp プロジェクト: carlobertolli/flang
FormatSpec *Parser::ParseFMTSpec(bool IsLabeled) {
  auto Loc = Tok.getLocation();
  if(!ConsumeIfPresent(tok::star)) {
    if(Tok.is(tok::int_literal_constant)) {
      auto Destination = ParseStatementLabelReference();
      if(!Destination.isInvalid())
        return Actions.ActOnLabelFormatSpec(Context, Loc, Destination);
    }
    auto E = ParseExpression();
    if(E.isUsable())
      return Actions.ActOnExpressionFormatSpec(Context, Loc, E.get());
    // NB: return empty format string on error.
    return Actions.ActOnExpressionFormatSpec(Context, Loc,
                                             CharacterConstantExpr::Create(Context, Loc, "", Context.CharacterTy));
  }

  return Actions.ActOnStarFormatSpec(Context, Loc);
}
コード例 #26
0
ファイル: ParseExec.cpp プロジェクト: carlobertolli/flang
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);
}
コード例 #27
0
ファイル: ParseExpr.cpp プロジェクト: ctgriffiths/flang
/// 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);
}
コード例 #28
0
ファイル: ParseExpr.cpp プロジェクト: ctgriffiths/flang
// 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;
}
コード例 #29
0
ファイル: ParseSpecStmt.cpp プロジェクト: carlobertolli/flang
/// 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);
}
コード例 #30
0
ファイル: ParseSpecStmt.cpp プロジェクト: carlobertolli/flang
/// 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);
}