1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
|
/*
* Copyright 2016 WebAssembly Community Group participants
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef WABT_WAST_PARSER_H_
#define WABT_WAST_PARSER_H_
#include <array>
#include <memory>
#include <unordered_map>
#include "wabt/circular-array.h"
#include "wabt/error.h"
#include "wabt/feature.h"
#include "wabt/intrusive-list.h"
#include "wabt/ir.h"
#include "wabt/wast-lexer.h"
namespace wabt {
struct WastParseOptions {
WastParseOptions(const Features& features) : features(features) {}
Features features;
bool debug_parsing = false;
};
using TokenTypePair = std::array<TokenType, 2>;
class WastParser {
public:
WastParser(WastLexer*, Errors*, WastParseOptions*);
void WABT_PRINTF_FORMAT(3, 4) Error(Location, const char* format, ...);
Result ParseModule(std::unique_ptr<Module>* out_module);
Result ParseScript(std::unique_ptr<Script>* out_script);
std::unique_ptr<Script> ReleaseScript();
private:
enum class ConstType {
Normal,
Expectation,
};
void ErrorUnlessOpcodeEnabled(const Token&);
// 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, size_t n = 0);
// 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 two tokens are form reference type - (ref $t)
bool PeekMatchRefType();
// 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); }
using SynchronizeFunc = bool(*)(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);
bool ParseBindVarOpt(std::string* name);
Result ParseVar(Var* out_var);
bool ParseVarOpt(Var* out_var, Var default_var = Var());
Result ParseOffsetExpr(ExprList* out_expr_list);
bool ParseOffsetExprOpt(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 ParseElemExprOpt(ExprList* out_elem_expr);
bool ParseElemExprListOpt(ExprListVector* out_list);
bool ParseElemExprVarListOpt(ExprListVector* out_list);
Result ParseValueType(Var* out_type);
Result ParseValueTypeList(
TypeVector* out_type_list,
std::unordered_map<uint32_t, std::string>* type_names);
Result ParseRefKind(Type* out_type);
Result ParseRefType(Type* out_type);
bool ParseRefTypeOpt(Type* out_type);
Result ParseQuotedText(std::string* text, bool check_utf8 = true);
bool ParseOffsetOpt(Address* offset);
bool ParseAlignOpt(Address* align);
Result ParseMemidx(Location loc, Var* memidx);
Result ParseLimitsIndex(Limits*);
Result ParseLimits(Limits*);
Result ParseNat(uint64_t*, bool is_64);
Result ParseModuleFieldList(Module*);
Result ParseModuleField(Module*);
Result ParseDataModuleField(Module*);
Result ParseElemModuleField(Module*);
Result ParseTagModuleField(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 ParseUnboundFuncSignature(FuncSignature*);
Result ParseBoundValueTypeList(TokenType,
TypeVector*,
BindingHash*,
std::unordered_map<uint32_t, std::string>*,
Index binding_index_offset = 0);
Result ParseUnboundValueTypeList(TokenType,
TypeVector*,
std::unordered_map<uint32_t, std::string>*);
Result ParseResultList(TypeVector*,
std::unordered_map<uint32_t, std::string>*);
Result ParseInstrList(ExprList*);
Result ParseTerminatingInstrList(ExprList*);
Result ParseInstr(ExprList*);
Result ParseCodeMetadataAnnotation(ExprList*);
Result ParsePlainInstr(std::unique_ptr<Expr>*);
Result ParseF32(Const*, ConstType type);
Result ParseF64(Const*, ConstType type);
Result ParseConst(Const*, ConstType type);
Result ParseExpectedValues(ExpectationPtr*);
Result ParseEither(ConstVector*);
Result ParseExternref(Const*);
Result ParseExpectedNan(ExpectedNan* expected);
Result ParseConstList(ConstVector*, ConstType type);
Result ParseBlockInstr(std::unique_ptr<Expr>*);
Result ParseLabelOpt(std::string*);
Result ParseEndLabelOpt(const std::string&);
Result ParseBlockDeclaration(BlockDeclaration*);
Result ParseBlock(Block*);
Result ParseExprList(ExprList*);
Result ParseExpr(ExprList*);
Result ParseCatchInstrList(CatchVector* catches);
Result ParseCatchExprList(CatchVector* catches);
Result ParseGlobalType(Global*);
Result ParseField(Field*);
Result ParseFieldList(std::vector<Field>*);
template <typename T>
Result ParsePlainInstrVar(Location, std::unique_ptr<Expr>*);
template <typename T>
Result ParseMemoryInstrVar(Location, std::unique_ptr<Expr>*);
template <typename T>
Result ParseLoadStoreInstr(Location, Token, std::unique_ptr<Expr>*);
template <typename T>
Result ParseSIMDLoadStoreInstr(Location loc,
Token token,
std::unique_ptr<Expr>* out_expr);
template <typename T>
Result ParseMemoryExpr(Location, std::unique_ptr<Expr>*);
template <typename T>
Result ParseMemoryBinaryExpr(Location, std::unique_ptr<Expr>*);
Result ParseSimdLane(Location, uint64_t*);
Result ParseCommandList(Script*, CommandPtrVector*);
Result ParseCommand(Script*, CommandPtr*);
Result ParseAssertExceptionCommand(CommandPtr*);
Result ParseAssertExhaustionCommand(CommandPtr*);
Result ParseAssertInvalidCommand(CommandPtr*);
Result ParseAssertMalformedCommand(CommandPtr*);
Result ParseAssertReturnCommand(CommandPtr*);
Result ParseAssertReturnFuncCommand(CommandPtr*);
Result ParseAssertTrapCommand(CommandPtr*);
Result ParseAssertUnlinkableCommand(CommandPtr*);
Result ParseActionCommand(CommandPtr*);
Result ParseModuleCommand(Script*, CommandPtr*);
Result ParseRegisterCommand(CommandPtr*);
Result ParseInputCommand(CommandPtr*);
Result ParseOutputCommand(CommandPtr*);
Result ParseAction(ActionPtr*);
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*);
Result ParseSimdV128Const(Const*, TokenType, ConstType);
void CheckImportOrdering(Module*);
WastLexer* lexer_;
Index last_module_index_ = kInvalidIndex;
Errors* errors_;
WastParseOptions* options_;
CircularArray<Token, 2> tokens_;
};
Result ParseWatModule(WastLexer* lexer,
std::unique_ptr<Module>* out_module,
Errors*,
WastParseOptions* options);
Result ParseWastScript(WastLexer* lexer,
std::unique_ptr<Script>* out_script,
Errors*,
WastParseOptions* options);
} // namespace wabt
#endif /* WABT_WAST_PARSER_H_ */
|