diff options
Diffstat (limited to 'src/wast-parser.h')
-rw-r--r-- | src/wast-parser.h | 175 |
1 files changed, 174 insertions, 1 deletions
diff --git a/src/wast-parser.h b/src/wast-parser.h index a2c06e34..8251df9d 100644 --- a/src/wast-parser.h +++ b/src/wast-parser.h @@ -17,11 +17,15 @@ #ifndef WABT_WAST_PARSER_H_ #define WABT_WAST_PARSER_H_ +#include <array> + +#include "circular-array.h" +#include "ir.h" +#include "intrusive-list.h" #include "wast-lexer.h" namespace wabt { -struct Script; class ErrorHandler; struct WastParseOptions { @@ -29,6 +33,175 @@ struct WastParseOptions { bool debug_parsing = false; }; +typedef std::array<TokenType, 2> TokenTypePair; + +class WastParser { + public: + WastParser(WastLexer*, ErrorHandler*, WastParseOptions*); + + void WABT_PRINTF_FORMAT(3, 4) Error(Location, const char* format, ...); + Result ParseScript(Script*); + + private: + void ErrorUnlessExceptionsAllowed(); + + // Print an error message listing the expected tokens, as well as an example + // of expected input. + Result ErrorExpected(const std::vector<std::string>& expected, + const char* example = nullptr); + + // Print an error message, and and return Result::Error if the next token is + // '('. This is commonly used after parsing a sequence of s-expressions -- if + // no more can be parsed, we know that a following '(' is invalid. This + // function consumes the '(' so a better error message can be provided + // (assuming the following token was unexpected). + Result ErrorIfLpar(const std::vector<std::string>& expected, + const char* example = nullptr); + + // Returns the next token without consuming it. + Token GetToken(); + + // Returns the location of the next token. + Location GetLocation(); + + // Returns the type of the next token. + TokenType Peek(size_t n = 0); + + // Returns the types of the next two tokens. + TokenTypePair PeekPair(); + + // Returns true if the next token's type is equal to the parameter. + bool PeekMatch(TokenType); + + // Returns true if the next token's type is '(' and the following token is + // equal to the parameter. + bool PeekMatchLpar(TokenType); + + // Returns true if the next two tokens can start an Expr. This allows for + // folded expressions, plain instructions and block instructions. + bool PeekMatchExpr(); + + // Returns true if the next token's type is equal to the parameter. If so, + // then the token is consumed. + bool Match(TokenType); + + // Returns true if the next token's type is equal to '(' and the following + // token is equal to the parameter. If so, then the token is consumed. + bool MatchLpar(TokenType); + + // Like Match(), but prints an error message if the token doesn't match, and + // returns Result::Error. + Result Expect(TokenType); + + // Consume one token and return it. + Token Consume(); + + // Give the Match() function a clearer name when used to optionally consume a + // token (used for printing better error messages). + void ConsumeIfLpar() { Match(TokenType::Lpar); } + + typedef bool SynchronizeFunc(TokenTypePair pair); + + // Attempt to synchronize the token stream by dropping tokens until the + // SynchronizeFunc returns true, or until a token limit is reached. This + // function returns Result::Error if the stream was not able to be + // synchronized. + Result Synchronize(SynchronizeFunc); + + void ParseBindVarOpt(std::string* name); + Result ParseVar(Var* out_var); + bool ParseVarOpt(Var* out_var, Var default_var = Var()); + Result ParseOffsetExpr(ExprList* out_expr_list); + Result ParseTextList(std::vector<uint8_t>* out_data); + bool ParseTextListOpt(std::vector<uint8_t>* out_data); + Result ParseVarList(VarVector* out_var_list); + bool ParseVarListOpt(VarVector* out_var_list); + Result ParseValueType(Type* out_type); + Result ParseValueTypeList(TypeVector* out_type_list); + Result ParseQuotedText(std::string* text); + bool ParseOffsetOpt(uint32_t* offset); + bool ParseAlignOpt(uint32_t* align); + Result ParseLimits(Limits*); + Result ParseNat(uint64_t*); + + Result ParseModuleFieldList(Module*); + Result ParseModuleField(Module*); + Result ParseDataModuleField(Module*); + Result ParseElemModuleField(Module*); + Result ParseExceptModuleField(Module*); + Result ParseExportModuleField(Module*); + Result ParseFuncModuleField(Module*); + Result ParseTypeModuleField(Module*); + Result ParseGlobalModuleField(Module*); + Result ParseImportModuleField(Module*); + Result ParseMemoryModuleField(Module*); + Result ParseStartModuleField(Module*); + Result ParseTableModuleField(Module*); + + Result ParseExportDesc(Export*); + Result ParseInlineExports(ModuleFieldList*, ExternalKind); + Result ParseInlineImport(Import*); + Result ParseTypeUseOpt(FuncDeclaration*); + Result ParseFuncSignature(FuncSignature*, BindingHash* param_bindings); + Result ParseBoundValueTypeList(TokenType, TypeVector*, BindingHash*); + Result ParseResultList(TypeVector*); + Result ParseInstrList(ExprList*); + Result ParseTerminatingInstrList(ExprList*); + Result ParseInstr(ExprList*); + Result ParsePlainInstr(std::unique_ptr<Expr>*); + Result ParseConst(Const*); + Result ParseConstList(ConstVector*); + Result ParseBlockInstr(std::unique_ptr<Expr>*); + Result ParseLabelOpt(std::string*); + Result ParseEndLabelOpt(const std::string&); + Result ParseBlock(Block*); + Result ParseExprList(ExprList*); + Result ParseExpr(ExprList*); + Result ParseCatchInstrList(CatchVector* catches); + Result ParseCatchExprList(CatchVector* catches); + Result ParseGlobalType(Global*); + + template <typename T> + Result ParsePlainInstrVar(Location, std::unique_ptr<Expr>*); + + Result ParseCommandList(CommandPtrVector*); + Result ParseCommand(CommandPtr*); + Result ParseAssertExhaustionCommand(CommandPtr*); + Result ParseAssertInvalidCommand(CommandPtr*); + Result ParseAssertMalformedCommand(CommandPtr*); + Result ParseAssertReturnCommand(CommandPtr*); + Result ParseAssertReturnArithmeticNanCommand(CommandPtr*); + Result ParseAssertReturnCanonicalNanCommand(CommandPtr*); + Result ParseAssertTrapCommand(CommandPtr*); + Result ParseAssertUnlinkableCommand(CommandPtr*); + Result ParseActionCommand(CommandPtr*); + Result ParseModuleCommand(CommandPtr*); + Result ParseRegisterCommand(CommandPtr*); + + Result ParseAction(Action*); + Result ParseScriptModule(std::unique_ptr<ScriptModule>*); + + template <typename T> + Result ParseActionCommand(TokenType, CommandPtr*); + template <typename T> + Result ParseAssertActionCommand(TokenType, CommandPtr*); + template <typename T> + Result ParseAssertActionTextCommand(TokenType, CommandPtr*); + template <typename T> + Result ParseAssertScriptModuleCommand(TokenType, CommandPtr*); + + void CheckImportOrdering(Module*); + + WastLexer* lexer_; + Script* script_ = nullptr; + Index last_module_index_ = kInvalidIndex; + ErrorHandler* error_handler_; + int errors_ = 0; + WastParseOptions* options_; + + CircularArray<Token, 2> tokens_; +}; + Result ParseWast(WastLexer* lexer, Script** out_script, ErrorHandler*, |