Exemple #1
0
/// ParseMatchedBinaryArgs - Parse a pair of arguments who are
/// expected to be of the same type. Upon return, if both LHS and RHS
/// are valid then they are guaranteed to have the same type.
///
/// Name - The name token of the expression, for diagnostics.
/// ExpectType - The expected type of the arguments, if known.
void ParserImpl::ParseMatchedBinaryArgs(const Token &Name, 
                                        TypeResult ExpectType,
                                        ExprResult &LHS, ExprResult &RHS) {
  if (Tok.kind == Token::RParen) {
    Error("unexpected end of arguments.", Name);
    ConsumeRParen();
    return;
  }

  // Avoid NumberOrExprResult overhead and give more precise
  // diagnostics when we know the type.
  if (ExpectType.isValid()) {
    LHS = ParseExpr(ExpectType);
    if (Tok.kind == Token::RParen) {
      Error("unexpected end of arguments.", Name);
      ConsumeRParen();
      return;
    }
    RHS = ParseExpr(ExpectType);
  } else {
    NumberOrExprResult LHS_NOE = ParseNumberOrExpr();

    if (Tok.kind == Token::RParen) {
      Error("unexpected end of arguments.", Name);
      ConsumeRParen();
      return;
    }

    if (LHS_NOE.isNumber()) {
      NumberOrExprResult RHS_NOE = ParseNumberOrExpr();
      
      if (RHS_NOE.isNumber()) {
        Error("ambiguous arguments to expression.", Name);
      } else {
        RHS = RHS_NOE.getExpr();
        if (RHS.isValid())
          LHS = ParseNumberToken(RHS.get()->getWidth(), LHS_NOE.getNumber());
      }
    } else {
      LHS = LHS_NOE.getExpr();
      if (!LHS.isValid()) {
        // FIXME: Should suppress ambiguity warnings here.
        RHS = ParseExpr(TypeResult());
      } else {
        RHS = ParseExpr(LHS.get()->getWidth());
      }
    }
  }

  ExpectRParen("unexpected argument to expression.");
}
Exemple #2
0
/// ParseParenExpr - Parse a parenthesized expression with the given
/// \arg ExpectedType. \arg ExpectedType can be invalid if the type
/// cannot be inferred from the context.
///
/// paren-expr = '(' type number ')'
/// paren-expr = '(' identifier [type] expr+ ')
/// paren-expr = '(' ('Read' | 'ReadMSB' | 'ReadLSB') type expr update-list ')'
ExprResult ParserImpl::ParseParenExpr(TypeResult FIXME_UNUSED) {
  if (Tok.kind != Token::LParen) {
    Error("unexpected token.");
    ConsumeAnyToken();
    return ExprResult();
  }

  ConsumeLParen();
  
  // Check for coercion case (w32 11).
  if (Tok.kind == Token::KWWidth) {
    TypeResult ExpectedType = ParseTypeSpecifier();

    if (Tok.kind != Token::Number) {
      Error("coercion can only apply to a number.");
      SkipUntilRParen();
      return ExprResult();
    }
    
    // Make sure this was a type specifier we support.
    ExprResult Res;
    if (ExpectedType.isValid()) 
      Res = ParseNumber(ExpectedType.get());
    else
      ConsumeToken();

    ExpectRParen("unexpected argument in coercion.");  
    return Res;
  }
  
  if (Tok.kind != Token::Identifier) {
    Error("unexpected token, expected expression.");
    SkipUntilRParen();
    return ExprResult();
  }

  Token Name = Tok;
  ConsumeToken();

  // FIXME: Use invalid type (i.e. width==0)?
  Token TypeTok = Tok;
  bool HasType = TypeTok.kind == Token::KWWidth;
  TypeResult Type = HasType ? ParseTypeSpecifier() : Expr::Bool;

  // FIXME: For now just skip to rparen on error. It might be nice
  // to try and actually parse the child nodes though for error
  // messages & better recovery?
  if (!Type.isValid()) {
    SkipUntilRParen();
    return ExprResult();
  }
  Expr::Width ResTy = Type.get();

  unsigned ExprKind;
  bool IsFixed;
  int NumArgs;
  if (!LookupExprInfo(Name, ExprKind, IsFixed, NumArgs)) {
    // FIXME: For now just skip to rparen on error. It might be nice
    // to try and actually parse the child nodes though for error
    // messages & better recovery?
    Error("unknown expression kind.", Name);
    SkipUntilRParen();
    return ExprResult();
  }

  // See if we have to parse this form specially.
  if (NumArgs == -1) {
    switch (ExprKind) {
    case eMacroKind_Concat:
      return ParseConcatParenExpr(Name, ResTy);

    case Expr::Extract:
      return ParseExtractParenExpr(Name, ResTy);

    case eMacroKind_ReadLSB:
    case eMacroKind_ReadMSB:
    case Expr::Read:
      return ParseAnyReadParenExpr(Name, ExprKind, ResTy);

    default:
      Error("internal error, unimplemented special form.", Name);
      SkipUntilRParen();
      return ExprResult(Builder->Constant(0, ResTy));
    }
  }

  switch (NumArgs) {
  case 1:
    return ParseUnaryParenExpr(Name, ExprKind, IsFixed, ResTy);
  case 2:
    return ParseBinaryParenExpr(Name, ExprKind, IsFixed, ResTy);
  case 3:
    if (ExprKind == Expr::Select)
      return ParseSelectParenExpr(Name, ResTy);
  default:
    assert(0 && "Invalid argument kind (number of args).");
    return ExprResult();
  }
}
Exemple #3
0
/// ParseExpr - Parse an expression with the given \arg
/// ExpectedType. \arg ExpectedType can be invalid if the type cannot
/// be inferred from the context.
///
/// expr = false | true
/// expr = <constant>
/// expr = <identifier>
/// expr = [<identifier>:] paren-expr
ExprResult ParserImpl::ParseExpr(TypeResult ExpectedType) {
  // FIXME: Is it right to need to do this here?
  if (Tok.kind == Token::EndOfFile) {
    Error("unexpected end of file.");
    return ExprResult();
  }

  if (Tok.kind == Token::KWFalse || Tok.kind == Token::KWTrue) {
    bool Value = Tok.kind == Token::KWTrue;
    ConsumeToken();
    return ExprResult(Builder->Constant(Value, Expr::Bool));
  }
  
  if (Tok.kind == Token::Number) {
    if (!ExpectedType.isValid()) {
      Error("cannot infer type of number.");
      ConsumeToken();
      return ExprResult();
    }
    
    return ParseNumber(ExpectedType.get());
  }

  const Identifier *Label = 0;
  if (Tok.kind == Token::Identifier) {
    Token LTok = Tok;
    Label = GetOrCreateIdentifier(Tok);
    ConsumeToken();

    if (Tok.kind != Token::Colon) {
      ExprSymTabTy::iterator it = ExprSymTab.find(Label);

      if (it == ExprSymTab.end()) {
        Error("invalid expression label reference.", LTok);
        return ExprResult();
      }

      return it->second;
    }

    ConsumeToken();
    if (ExprSymTab.count(Label)) {
      Error("duplicate expression label definition.", LTok);
      Label = 0;
    }
  }

  Token Start = Tok;
  ExprResult Res = ParseParenExpr(ExpectedType);
  if (!Res.isValid()) {
    // If we know the type, define the identifier just so we don't get
    // use-of-undef errors. 
    // FIXME: Maybe we should let the symbol table map to invalid
    // entries?
    if (Label && ExpectedType.isValid()) {
      ref<Expr> Value = Builder->Constant(0, ExpectedType.get());
      ExprSymTab.insert(std::make_pair(Label, Value));
    }
    return Res;
  } else if (ExpectedType.isValid()) {
    // Type check result.    
    if (Res.get()->getWidth() != ExpectedType.get()) {
      // FIXME: Need more info, and range
      Error("expression has incorrect type.", Start);
      return ExprResult();
    }
  }

  if (Label)
    ExprSymTab.insert(std::make_pair(Label, Res.get()));
  return Res;
}
Exemple #4
0
/// ParseArrayDecl - Parse an array declaration. The lexer should be positioned
/// at the opening 'array'.
///
/// array-declaration = "array" name "[" [ size ] "]" ":" domain "->" range 
///                       "=" array-initializer
/// array-initializer = "symbolic" | "{" { numeric-literal } "}"
DeclResult ParserImpl::ParseArrayDecl() {
  // FIXME: Recovery here is horrible, we need to scan to next decl start or
  // something.
  ConsumeExpectedToken(Token::KWArray);
  
  if (Tok.kind != Token::Identifier) {
    Error("expected identifier token.");
    return DeclResult();
  }

  Token Name = Tok;
  IntegerResult Size;
  TypeResult DomainType;
  TypeResult RangeType;
  std::vector< ref<ConstantExpr> > Values;

  ConsumeToken();
  
  if (Tok.kind != Token::LSquare) {
    Error("expected '['.");
    goto exit;
  }
  ConsumeLSquare();

  if (Tok.kind != Token::RSquare) {
    Size = ParseIntegerConstant(64);
  }
  if (Tok.kind != Token::RSquare) {
    Error("expected ']'.");
    goto exit;
  }
  ConsumeRSquare();
  
  if (Tok.kind != Token::Colon) {
    Error("expected ':'.");
    goto exit;
  }
  ConsumeExpectedToken(Token::Colon);

  DomainType = ParseTypeSpecifier();
  if (Tok.kind != Token::Arrow) {
    Error("expected '->'.");
    goto exit;
  }
  ConsumeExpectedToken(Token::Arrow);

  RangeType = ParseTypeSpecifier();
  if (Tok.kind != Token::Equals) {
    Error("expected '='.");
    goto exit;
  }
  ConsumeExpectedToken(Token::Equals);

  if (Tok.kind == Token::KWSymbolic) {
    ConsumeExpectedToken(Token::KWSymbolic);    
  } else if (Tok.kind == Token::LSquare) {
    ConsumeLSquare();
    while (Tok.kind != Token::RSquare) {
      if (Tok.kind == Token::EndOfFile) {
        Error("unexpected end of file.");
        goto exit;
      }

      ExprResult Res = ParseNumber(RangeType.get());
      if (Res.isValid())
        Values.push_back(cast<ConstantExpr>(Res.get()));
    }
    ConsumeRSquare();
  } else {
    Error("expected 'symbolic' or '['.");
    goto exit;
  }

  // Type check size.
  if (!Size.isValid()) {
    if (Values.empty()) {
      Error("unsized arrays are not yet supported.");
      Size = 1;
    } else {
      Size = Values.size();
    }
  }

  if (!Values.empty()) {
    if (Size.get() != Values.size()) {
      // FIXME: Lame message.
      Error("constant arrays must be completely specified.");
      Values.clear();
    }

    // for (unsigned i = 0; i != Size.get(); ++i) {
    // TODO: Check: Must be constant expression.
    //}
  }

  // FIXME: Validate that size makes sense for domain type.

  if (DomainType.get() != Expr::Int32) {
    Error("array domain must currently be w32.");
    DomainType = Expr::Int32;
    Values.clear();
  }

  if (RangeType.get() != Expr::Int8) {
    Error("array domain must currently be w8.");
    RangeType = Expr::Int8;
    Values.clear();
  }

  // FIXME: Validate that this array is undeclared.

 exit:
  if (!Size.isValid())
    Size = 1;
  if (!DomainType.isValid())
    DomainType = 32;
  if (!RangeType.isValid())
    RangeType = 8;

  // FIXME: Array should take domain and range.
  const Identifier *Label = GetOrCreateIdentifier(Name);
  const Array *Root;
  if (!Values.empty())
    Root = TheArrayCache.CreateArray(Label->Name, Size.get(), &Values[0],
                                     &Values[0] + Values.size());
  else
    Root = TheArrayCache.CreateArray(Label->Name, Size.get());
  ArrayDecl *AD = new ArrayDecl(Label, Size.get(), 
                                DomainType.get(), RangeType.get(), Root);

  ArraySymTab[Label] = AD;

  // Create the initial version reference.
  VersionSymTab.insert(std::make_pair(Label,
                                      UpdateList(Root, NULL)));

  return AD;
}