//===-- Parser.h ------------------------------------------------*- C++ -*-===// // // The KLEE Symbolic Virtual Machine // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef KLEE_EXPR_PARSER_H #define KLEE_EXPR_PARSER_H #include "klee/Expr.h" #include #include namespace llvm { class MemoryBuffer; } namespace klee { namespace expr { // These are the language types we manipulate. typedef ref ExprHandle; typedef UpdateList VersionHandle; /// Identifier - Wrapper for a uniqued string. struct Identifier { const std::string Name; public: Identifier(const std::string _Name) : Name(_Name) {} }; // FIXME: Do we have a use for tracking source locations? /// Decl - Base class for top level declarations. class Decl { public: enum DeclKind { ArrayDeclKind, ExprVarDeclKind, VersionVarDeclKind, QueryCommandDeclKind, DeclKindLast = QueryCommandDeclKind, VarDeclKindFirst = ExprVarDeclKind, VarDeclKindLast = VersionVarDeclKind, CommandDeclKindFirst = QueryCommandDeclKind, CommandDeclKindLast = QueryCommandDeclKind }; private: DeclKind Kind; public: Decl(DeclKind _Kind); virtual ~Decl() {} /// getKind - Get the decl kind. DeclKind getKind() const { return Kind; } /// dump - Dump the AST node to stderr. virtual void dump() = 0; static bool classof(const Decl *) { return true; } }; /// ArrayDecl - Array declarations. /// /// For example: /// array obj[] : w32 -> w8 = symbolic /// array obj[32] : w32 -> w8 = { ... } class ArrayDecl : public Decl { public: /// Name - The name of this array. const Identifier *Name; /// Size - The maximum array size (or 0 if unspecified). Concrete /// arrays always are specified with a size. const uint64_t Size; /// Domain - The width of indices. const unsigned Domain; /// Range - The width of array contents. const unsigned Range; /// Root - The root array object defined by this decl. const Array *Root; /// Contents - The initial contents of the array. The array is /// symbolic if no contents are specified. The contained /// expressions are guaranteed to be constants. const std::vector Contents; public: ArrayDecl(const Identifier *_Name, uint64_t _Size, unsigned _Domain, unsigned _Range, const Array *_Root) : Decl(ArrayDeclKind), Name(_Name), Size(_Size), Domain(_Domain), Range(_Range), Root(_Root) { } virtual void dump(); static bool classof(const Decl *D) { return D->getKind() == Decl::ArrayDeclKind; } static bool classof(const ArrayDecl *) { return true; } }; /// VarDecl - Variable declarations, used to associate names to /// expressions or array versions outside of expressions. /// /// For example: // FIXME: What syntax are we going to use for this? We need it. class VarDecl : public Decl { public: const Identifier *Name; static bool classof(const Decl *D) { return (Decl::VarDeclKindFirst <= D->getKind() && D->getKind() <= Decl::VarDeclKindLast); } static bool classof(const VarDecl *) { return true; } }; /// ExprVarDecl - Expression variable declarations. class ExprVarDecl : public VarDecl { public: ExprHandle Value; static bool classof(const Decl *D) { return D->getKind() == Decl::ExprVarDeclKind; } static bool classof(const ExprVarDecl *) { return true; } }; /// VersionVarDecl - Array version variable declarations. class VersionVarDecl : public VarDecl { public: VersionHandle Value; static bool classof(const Decl *D) { return D->getKind() == Decl::VersionVarDeclKind; } static bool classof(const VersionVarDecl *) { return true; } }; /// CommandDecl - Base class for language commands. class CommandDecl : public Decl { public: CommandDecl(DeclKind _Kind) : Decl(_Kind) {} static bool classof(const Decl *D) { return (Decl::CommandDeclKindFirst <= D->getKind() && D->getKind() <= Decl::CommandDeclKindLast); } static bool classof(const CommandDecl *) { return true; } }; /// QueryCommand - Query commands. /// /// (query [ ... constraints ... ] expression) /// (query [ ... constraints ... ] expression values) /// (query [ ... constraints ... ] expression values objects) class QueryCommand : public CommandDecl { public: // FIXME: One issue with STP... should we require the FE to // guarantee that these are consistent? That is a cornerstone of // being able to do independence. We may want this as a flag, if // we are to interface with things like SMT. /// Constraints - The list of constraints to assume for this /// expression. const std::vector Constraints; /// Query - The expression being queried. ExprHandle Query; /// Values - The expressions for which counterexamples should be /// given if the query is invalid. const std::vector Values; /// Objects - Symbolic arrays whose initial contents should be /// given if the query is invalid. const std::vector Objects; public: QueryCommand(const std::vector &_Constraints, ExprHandle _Query, const std::vector &_Values, const std::vector &_Objects ) : CommandDecl(QueryCommandDeclKind), Constraints(_Constraints), Query(_Query), Values(_Values), Objects(_Objects) {} virtual void dump(); static bool classof(const Decl *D) { return D->getKind() == QueryCommandDeclKind; } static bool classof(const QueryCommand *) { return true; } }; /// Parser - Public interface for parsing a .pc language file. class Parser { protected: Parser(); public: virtual ~Parser(); /// SetMaxErrors - Suppress anything beyond the first N errors. virtual void SetMaxErrors(unsigned N) = 0; /// GetNumErrors - Return the number of encountered errors. virtual unsigned GetNumErrors() const = 0; /// ParseTopLevelDecl - Parse and return a top level declaration, /// which the caller assumes ownership of. /// /// \return NULL indicates the end of the file has been reached. virtual Decl *ParseTopLevelDecl() = 0; /// CreateParser - Create a parser implementation for the given /// MemoryBuffer. /// /// \arg Name - The name to use in diagnostic messages. static Parser *Create(const std::string Name, const llvm::MemoryBuffer *MB); }; } } #endif