/* * 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. */ #include "wast-lexer.h" #include #include #include "config.h" #include "circular-array.h" #include "lexer-source.h" #include "wast-parser.h" #include "wast-parser-lexer-shared.h" /* must be included after so some typedefs will be defined */ #include "wast-parser-gen.hh" /*!max:re2c */ #define INITIAL_LEXER_BUFFER_SIZE (64 * 1024) #define NAME_TO_VALUE(name) WABT_TOKEN_TYPE_##name #define LOOKAHEAD(name) \ SetLookaheadToken(NAME_TO_VALUE(name)); \ next_pos_ = cursor_; \ continue #define RETURN(name) \ SetToken(NAME_TO_VALUE(name)); \ return PopLookaheadToken(lval, loc); #define RETURN_LPAR(name) \ SetToken(NAME_TO_VALUE(name)); \ if (IsLookaheadLpar()) { \ SetLocation(loc); \ return NAME_TO_VALUE(LPAR_##name); \ } \ return PopLookaheadToken(lval, loc); #define ERROR(...) \ SetLocation(loc); \ wast_parser_error(loc, this, parser, __VA_ARGS__) #define BEGIN(c) cond = (c) #define FILL(n) \ do { \ if (WABT_FAILED(Fill(loc, parser, (n)))) { \ int value = NAME_TO_VALUE(EOF); \ SetToken(value); \ return PopLookaheadToken(lval, loc); \ } \ } while (0) #define MAYBE_MALFORMED_UTF8(desc) \ if (!(eof_ && limit_ - cursor_ <= YYMAXFILL)) { \ ERROR("malformed utf-8%s", desc); \ } \ continue #define yytext (next_pos_) #define yyleng (cursor_ - next_pos_) /* p must be a pointer somewhere in the lexer buffer */ #define FILE_OFFSET(p) ((p) - (buffer_) + buffer_file_offset_) #define COLUMN(p) (FILE_OFFSET(p) - line_file_offset_ + 1) #define COMMENT_NESTING (comment_nesting_) #define NEWLINE \ do { \ line_++; \ line_file_offset_ = FILE_OFFSET(cursor_); \ } while (0) #define TYPE(type_) SetType(Type::type_) #define OPCODE(name) SetOpcode(Opcode::name); #define LITERAL(type_) SetLiteral(LiteralType::type_) namespace wabt { struct WastLexer::LexToken { Location loc_; int value_; Token lval_; }; struct WastLexer::Lookahead { CircularArray tokens_; }; WastLexer::WastLexer(std::unique_ptr source, const char* filename) : source_(std::move(source)), line_finder_(source_->Clone()), filename_(filename), line_(1), comment_nesting_(0), buffer_file_offset_(0), line_file_offset_(0), lookahead_(new WastLexer::Lookahead()), token_(nullptr), eof_(false), buffer_(nullptr), buffer_size_(0), marker_(nullptr), next_pos_(nullptr), cursor_(nullptr), limit_(nullptr) {} WastLexer::~WastLexer() { delete[] buffer_; delete lookahead_; } // static std::unique_ptr WastLexer::CreateFileLexer(const char* filename) { std::unique_ptr source(new LexerSourceFile(filename)); return std::unique_ptr(new WastLexer(std::move(source), filename)); } // static std::unique_ptr WastLexer::CreateBufferLexer(const char* filename, const void* data, size_t size) { std::unique_ptr source(new LexerSourceBuffer(data, size)); return std::unique_ptr(new WastLexer(std::move(source), filename)); } bool WastLexer::IsLookaheadLpar() { return lookahead_->tokens_.size() == 2 // ignore current token && lookahead_->tokens_[0].value_ == WABT_TOKEN_TYPE_LPAR; } int WastLexer::PopLookaheadToken(Token* lval, Location* loc) { WastLexer::LexToken* tok = &lookahead_->tokens_.front(); *loc = tok->loc_; *lval = tok->lval_; int Result = tok->value_; lookahead_->tokens_.pop_front(); if (lookahead_->tokens_.empty()) token_ = nullptr; return Result; \ } void WastLexer::PushLookaheadToken() { WastLexer::LexToken tok; lookahead_->tokens_.push_back(tok); token_ = &lookahead_->tokens_.back(); } void WastLexer::SetLiteral(LiteralType lit_typ) { token_->lval_.literal.type = lit_typ; token_->lval_.literal.text.start = yytext; token_->lval_.literal.text.length = yyleng; } void WastLexer::SetLocation(Location* loc) { loc->filename = filename_; loc->line = line_; loc->first_column = COLUMN(next_pos_); loc->last_column = COLUMN(cursor_); } void WastLexer::SetLookaheadToken(int value) { SetToken(value); PushLookaheadToken(); } void WastLexer::SetOpcode(Opcode opc) { token_->lval_.opcode = opc; } void WastLexer::SetText() { token_->lval_.text.start = yytext; token_->lval_.text.length = yyleng; } void WastLexer::SetTextAt(size_t offset) { token_->lval_.text.start = yytext + offset; token_->lval_.text.length = yyleng - offset; } void WastLexer::SetToken(int value) { SetLocation(&token_->loc_); token_->value_ = value; next_pos_ = cursor_; } void WastLexer::SetType(Type ty) { token_->lval_.type = ty; } Result WastLexer::Fill(Location* loc, WastParser* parser, size_t need) { if (eof_) return Result::Error; size_t free = next_pos_ - buffer_; assert(static_cast(cursor_ - buffer_) >= free); // Our buffer is too small, need to realloc. if (free < need) { char* old_buffer = buffer_; size_t old_buffer_size = buffer_size_; size_t new_buffer_size = old_buffer_size ? old_buffer_size * 2 : INITIAL_LEXER_BUFFER_SIZE; // Make sure there is enough space for the bytes requested (need) and an // additional YYMAXFILL bytes which is needed for the re2c lexer // implementation when the eof is reached. while ((new_buffer_size - old_buffer_size) + free < need + YYMAXFILL) new_buffer_size *= 2; char* new_buffer = new char[new_buffer_size]; if (limit_ > next_pos_) memmove(new_buffer, next_pos_, limit_ - next_pos_); buffer_ = new_buffer; buffer_size_ = new_buffer_size; next_pos_ = new_buffer + (next_pos_ - old_buffer) - free; marker_ = new_buffer + (marker_ - old_buffer) - free; cursor_ = new_buffer + (cursor_ - old_buffer) - free; limit_ = new_buffer + (limit_ - old_buffer) - free; buffer_file_offset_ += free; free += new_buffer_size - old_buffer_size; delete[] old_buffer; } else { // Shift everything down to make more room in the buffer. if (limit_ > next_pos_) memmove(buffer_, next_pos_, limit_ - next_pos_); next_pos_ -= free; marker_ -= free; cursor_ -= free; limit_ -= free; buffer_file_offset_ += free; } // Read the new data into the buffer. limit_ += source_->Fill(limit_, free); // If at the end of file, need to fill YYMAXFILL more characters with "fake // characters", that are not a lexeme nor a lexeme suffix. see // http://re2c.org/examples/example_03.html. if (limit_ < buffer_ + buffer_size_ - YYMAXFILL) { eof_ = true; // Fill with 0xff, since that is an invalid utf-8 byte. memset(limit_, 0xff, YYMAXFILL); limit_ += YYMAXFILL; } return Result::Ok; } int WastLexer::GetToken(Token* lval, Location* loc, WastParser* parser) { /*!types:re2c*/ YYCONDTYPE cond = YYCOND_i; // i is the initial state. if (!lookahead_->tokens_.empty()) { return PopLookaheadToken(lval, loc); } PushLookaheadToken(); for (;;) { next_pos_ = cursor_; /*!re2c re2c:condprefix = YYCOND_; re2c:condenumprefix = YYCOND_; re2c:define:YYCTYPE = "unsigned char"; re2c:define:YYCURSOR = cursor_; re2c:define:YYMARKER = marker_; re2c:define:YYLIMIT = limit_; re2c:define:YYFILL = "FILL"; re2c:define:YYGETCONDITION = "cond"; re2c:define:YYGETCONDITION:naked = 1; re2c:define:YYSETCONDITION = "BEGIN"; digit = [0-9]; hexdigit = [0-9a-fA-F]; num = digit+; hexnum = hexdigit+; letter = [a-zA-Z]; symbol = [+\-*\\/^~=<>!?@#$%&|:`.']; character = [^"\\\x00-\x1f] | "\\" [nrt\\'"] | "\\" hexdigit hexdigit; sign = [+-]; nat = num | "0x" hexnum; int = sign nat; hexfloat = sign? "0x" hexnum ("." hexdigit*)? "p" sign? num; infinity = sign? "inf"; nan = sign? "nan" | sign? "nan:0x" hexnum; float = sign? num "." digit* | sign? num ("." digit*)? [eE] sign? num; text = '"' character* '"'; name = "$" (letter | digit | "_" | symbol)+; // Should be ([\x21-\x7e] \ [()"; ])+ , but re2c doesn't like this... reserved = [\x21\x23-\x27\x2a-\x3a\x3c-\x7e]+; "(" { LOOKAHEAD(LPAR); } ")" { RETURN(RPAR); } nat { LITERAL(Int); RETURN(NAT); } int { LITERAL(Int); RETURN(INT); } float { LITERAL(Float); RETURN(FLOAT); } hexfloat { LITERAL(Hexfloat); RETURN(FLOAT); } infinity { LITERAL(Infinity); RETURN(FLOAT); } nan { LITERAL(Nan); RETURN(FLOAT); } text { SetText(); RETURN(TEXT); } '"' => BAD_TEXT { continue; } character { continue; } "\n" => i { ERROR("newline in string"); NEWLINE; continue; } "\\". { ERROR("bad escape \"%.*s\"", static_cast(yyleng), yytext); continue; } '"' => i { SetText(); RETURN(TEXT); } [^] { ERROR("illegal character in string"); continue; } * { MAYBE_MALFORMED_UTF8(" in string"); } "i32" { TYPE(I32); RETURN(VALUE_TYPE); } "i64" { TYPE(I64); RETURN(VALUE_TYPE); } "f32" { TYPE(F32); RETURN(VALUE_TYPE); } "f64" { TYPE(F64); RETURN(VALUE_TYPE); } "anyfunc" { RETURN(ANYFUNC); } "mut" { RETURN(MUT); } "nop" { RETURN(NOP); } "block" { RETURN(BLOCK); } "if" { RETURN(IF); } "then" { RETURN(THEN); } "else" { RETURN(ELSE); } "loop" { RETURN(LOOP); } "br" { RETURN(BR); } "br_if" { RETURN(BR_IF); } "br_table" { RETURN(BR_TABLE); } "call" { RETURN(CALL); } "call_indirect" { RETURN(CALL_INDIRECT); } "drop" { RETURN(DROP); } "end" { RETURN(END); } "return" { RETURN(RETURN); } "get_local" { RETURN(GET_LOCAL); } "set_local" { RETURN(SET_LOCAL); } "tee_local" { RETURN(TEE_LOCAL); } "get_global" { RETURN(GET_GLOBAL); } "set_global" { RETURN(SET_GLOBAL); } "i32.load" { OPCODE(I32Load); RETURN(LOAD); } "i64.load" { OPCODE(I64Load); RETURN(LOAD); } "f32.load" { OPCODE(F32Load); RETURN(LOAD); } "f64.load" { OPCODE(F64Load); RETURN(LOAD); } "i32.store" { OPCODE(I32Store); RETURN(STORE); } "i64.store" { OPCODE(I64Store); RETURN(STORE); } "f32.store" { OPCODE(F32Store); RETURN(STORE); } "f64.store" { OPCODE(F64Store); RETURN(STORE); } "i32.load8_s" { OPCODE(I32Load8S); RETURN(LOAD); } "i64.load8_s" { OPCODE(I64Load8S); RETURN(LOAD); } "i32.load8_u" { OPCODE(I32Load8U); RETURN(LOAD); } "i64.load8_u" { OPCODE(I64Load8U); RETURN(LOAD); } "i32.load16_s" { OPCODE(I32Load16S); RETURN(LOAD); } "i64.load16_s" { OPCODE(I64Load16S); RETURN(LOAD); } "i32.load16_u" { OPCODE(I32Load16U); RETURN(LOAD); } "i64.load16_u" { OPCODE(I64Load16U); RETURN(LOAD); } "i64.load32_s" { OPCODE(I64Load32S); RETURN(LOAD); } "i64.load32_u" { OPCODE(I64Load32U); RETURN(LOAD); } "i32.store8" { OPCODE(I32Store8); RETURN(STORE); } "i64.store8" { OPCODE(I64Store8); RETURN(STORE); } "i32.store16" { OPCODE(I32Store16); RETURN(STORE); } "i64.store16" { OPCODE(I64Store16); RETURN(STORE); } "i64.store32" { OPCODE(I64Store32); RETURN(STORE); } "offset=" nat { SetTextAt(7); RETURN(OFFSET_EQ_NAT); } "align=" nat { SetTextAt(6); RETURN(ALIGN_EQ_NAT); } "i32.const" { TYPE(I32); RETURN(CONST); } "i64.const" { TYPE(I64); RETURN(CONST); } "f32.const" { TYPE(F32); RETURN(CONST); } "f64.const" { TYPE(F64); RETURN(CONST); } "i32.eqz" { OPCODE(I32Eqz); RETURN(CONVERT); } "i64.eqz" { OPCODE(I64Eqz); RETURN(CONVERT); } "i32.clz" { OPCODE(I32Clz); RETURN(UNARY); } "i64.clz" { OPCODE(I64Clz); RETURN(UNARY); } "i32.ctz" { OPCODE(I32Ctz); RETURN(UNARY); } "i64.ctz" { OPCODE(I64Ctz); RETURN(UNARY); } "i32.popcnt" { OPCODE(I32Popcnt); RETURN(UNARY); } "i64.popcnt" { OPCODE(I64Popcnt); RETURN(UNARY); } "f32.neg" { OPCODE(F32Neg); RETURN(UNARY); } "f64.neg" { OPCODE(F64Neg); RETURN(UNARY); } "f32.abs" { OPCODE(F32Abs); RETURN(UNARY); } "f64.abs" { OPCODE(F64Abs); RETURN(UNARY); } "f32.sqrt" { OPCODE(F32Sqrt); RETURN(UNARY); } "f64.sqrt" { OPCODE(F64Sqrt); RETURN(UNARY); } "f32.ceil" { OPCODE(F32Ceil); RETURN(UNARY); } "f64.ceil" { OPCODE(F64Ceil); RETURN(UNARY); } "f32.floor" { OPCODE(F32Floor); RETURN(UNARY); } "f64.floor" { OPCODE(F64Floor); RETURN(UNARY); } "f32.trunc" { OPCODE(F32Trunc); RETURN(UNARY); } "f64.trunc" { OPCODE(F64Trunc); RETURN(UNARY); } "f32.nearest" { OPCODE(F32Nearest); RETURN(UNARY); } "f64.nearest" { OPCODE(F64Nearest); RETURN(UNARY); } "i32.add" { OPCODE(I32Add); RETURN(BINARY); } "i64.add" { OPCODE(I64Add); RETURN(BINARY); } "i32.sub" { OPCODE(I32Sub); RETURN(BINARY); } "i64.sub" { OPCODE(I64Sub); RETURN(BINARY); } "i32.mul" { OPCODE(I32Mul); RETURN(BINARY); } "i64.mul" { OPCODE(I64Mul); RETURN(BINARY); } "i32.div_s" { OPCODE(I32DivS); RETURN(BINARY); } "i64.div_s" { OPCODE(I64DivS); RETURN(BINARY); } "i32.div_u" { OPCODE(I32DivU); RETURN(BINARY); } "i64.div_u" { OPCODE(I64DivU); RETURN(BINARY); } "i32.rem_s" { OPCODE(I32RemS); RETURN(BINARY); } "i64.rem_s" { OPCODE(I64RemS); RETURN(BINARY); } "i32.rem_u" { OPCODE(I32RemU); RETURN(BINARY); } "i64.rem_u" { OPCODE(I64RemU); RETURN(BINARY); } "i32.and" { OPCODE(I32And); RETURN(BINARY); } "i64.and" { OPCODE(I64And); RETURN(BINARY); } "i32.or" { OPCODE(I32Or); RETURN(BINARY); } "i64.or" { OPCODE(I64Or); RETURN(BINARY); } "i32.xor" { OPCODE(I32Xor); RETURN(BINARY); } "i64.xor" { OPCODE(I64Xor); RETURN(BINARY); } "i32.shl" { OPCODE(I32Shl); RETURN(BINARY); } "i64.shl" { OPCODE(I64Shl); RETURN(BINARY); } "i32.shr_s" { OPCODE(I32ShrS); RETURN(BINARY); } "i64.shr_s" { OPCODE(I64ShrS); RETURN(BINARY); } "i32.shr_u" { OPCODE(I32ShrU); RETURN(BINARY); } "i64.shr_u" { OPCODE(I64ShrU); RETURN(BINARY); } "i32.rotl" { OPCODE(I32Rotl); RETURN(BINARY); } "i64.rotl" { OPCODE(I64Rotl); RETURN(BINARY); } "i32.rotr" { OPCODE(I32Rotr); RETURN(BINARY); } "i64.rotr" { OPCODE(I64Rotr); RETURN(BINARY); } "f32.add" { OPCODE(F32Add); RETURN(BINARY); } "f64.add" { OPCODE(F64Add); RETURN(BINARY); } "f32.sub" { OPCODE(F32Sub); RETURN(BINARY); } "f64.sub" { OPCODE(F64Sub); RETURN(BINARY); } "f32.mul" { OPCODE(F32Mul); RETURN(BINARY); } "f64.mul" { OPCODE(F64Mul); RETURN(BINARY); } "f32.div" { OPCODE(F32Div); RETURN(BINARY); } "f64.div" { OPCODE(F64Div); RETURN(BINARY); } "f32.min" { OPCODE(F32Min); RETURN(BINARY); } "f64.min" { OPCODE(F64Min); RETURN(BINARY); } "f32.max" { OPCODE(F32Max); RETURN(BINARY); } "f64.max" { OPCODE(F64Max); RETURN(BINARY); } "f32.copysign" { OPCODE(F32Copysign); RETURN(BINARY); } "f64.copysign" { OPCODE(F64Copysign); RETURN(BINARY); } "i32.eq" { OPCODE(I32Eq); RETURN(COMPARE); } "i64.eq" { OPCODE(I64Eq); RETURN(COMPARE); } "i32.ne" { OPCODE(I32Ne); RETURN(COMPARE); } "i64.ne" { OPCODE(I64Ne); RETURN(COMPARE); } "i32.lt_s" { OPCODE(I32LtS); RETURN(COMPARE); } "i64.lt_s" { OPCODE(I64LtS); RETURN(COMPARE); } "i32.lt_u" { OPCODE(I32LtU); RETURN(COMPARE); } "i64.lt_u" { OPCODE(I64LtU); RETURN(COMPARE); } "i32.le_s" { OPCODE(I32LeS); RETURN(COMPARE); } "i64.le_s" { OPCODE(I64LeS); RETURN(COMPARE); } "i32.le_u" { OPCODE(I32LeU); RETURN(COMPARE); } "i64.le_u" { OPCODE(I64LeU); RETURN(COMPARE); } "i32.gt_s" { OPCODE(I32GtS); RETURN(COMPARE); } "i64.gt_s" { OPCODE(I64GtS); RETURN(COMPARE); } "i32.gt_u" { OPCODE(I32GtU); RETURN(COMPARE); } "i64.gt_u" { OPCODE(I64GtU); RETURN(COMPARE); } "i32.ge_s" { OPCODE(I32GeS); RETURN(COMPARE); } "i64.ge_s" { OPCODE(I64GeS); RETURN(COMPARE); } "i32.ge_u" { OPCODE(I32GeU); RETURN(COMPARE); } "i64.ge_u" { OPCODE(I64GeU); RETURN(COMPARE); } "f32.eq" { OPCODE(F32Eq); RETURN(COMPARE); } "f64.eq" { OPCODE(F64Eq); RETURN(COMPARE); } "f32.ne" { OPCODE(F32Ne); RETURN(COMPARE); } "f64.ne" { OPCODE(F64Ne); RETURN(COMPARE); } "f32.lt" { OPCODE(F32Lt); RETURN(COMPARE); } "f64.lt" { OPCODE(F64Lt); RETURN(COMPARE); } "f32.le" { OPCODE(F32Le); RETURN(COMPARE); } "f64.le" { OPCODE(F64Le); RETURN(COMPARE); } "f32.gt" { OPCODE(F32Gt); RETURN(COMPARE); } "f64.gt" { OPCODE(F64Gt); RETURN(COMPARE); } "f32.ge" { OPCODE(F32Ge); RETURN(COMPARE); } "f64.ge" { OPCODE(F64Ge); RETURN(COMPARE); } "i64.extend_s/i32" { OPCODE(I64ExtendSI32); RETURN(CONVERT); } "i64.extend_u/i32" { OPCODE(I64ExtendUI32); RETURN(CONVERT); } "i32.wrap/i64" { OPCODE(I32WrapI64); RETURN(CONVERT); } "i32.trunc_s/f32" { OPCODE(I32TruncSF32); RETURN(CONVERT); } "i64.trunc_s/f32" { OPCODE(I64TruncSF32); RETURN(CONVERT); } "i32.trunc_s/f64" { OPCODE(I32TruncSF64); RETURN(CONVERT); } "i64.trunc_s/f64" { OPCODE(I64TruncSF64); RETURN(CONVERT); } "i32.trunc_u/f32" { OPCODE(I32TruncUF32); RETURN(CONVERT); } "i64.trunc_u/f32" { OPCODE(I64TruncUF32); RETURN(CONVERT); } "i32.trunc_u/f64" { OPCODE(I32TruncUF64); RETURN(CONVERT); } "i64.trunc_u/f64" { OPCODE(I64TruncUF64); RETURN(CONVERT); } "f32.convert_s/i32" { OPCODE(F32ConvertSI32); RETURN(CONVERT); } "f64.convert_s/i32" { OPCODE(F64ConvertSI32); RETURN(CONVERT); } "f32.convert_s/i64" { OPCODE(F32ConvertSI64); RETURN(CONVERT); } "f64.convert_s/i64" { OPCODE(F64ConvertSI64); RETURN(CONVERT); } "f32.convert_u/i32" { OPCODE(F32ConvertUI32); RETURN(CONVERT); } "f64.convert_u/i32" { OPCODE(F64ConvertUI32); RETURN(CONVERT); } "f32.convert_u/i64" { OPCODE(F32ConvertUI64); RETURN(CONVERT); } "f64.convert_u/i64" { OPCODE(F64ConvertUI64); RETURN(CONVERT); } "f64.promote/f32" { OPCODE(F64PromoteF32); RETURN(CONVERT); } "f32.demote/f64" { OPCODE(F32DemoteF64); RETURN(CONVERT); } "f32.reinterpret/i32" { OPCODE(F32ReinterpretI32); RETURN(CONVERT); } "i32.reinterpret/f32" { OPCODE(I32ReinterpretF32); RETURN(CONVERT); } "f64.reinterpret/i64" { OPCODE(F64ReinterpretI64); RETURN(CONVERT); } "i64.reinterpret/f64" { OPCODE(I64ReinterpretF64); RETURN(CONVERT); } "select" { RETURN(SELECT); } "unreachable" { RETURN(UNREACHABLE); } "current_memory" { RETURN(CURRENT_MEMORY); } "grow_memory" { RETURN(GROW_MEMORY); } "type" { RETURN(TYPE); } "func" { RETURN(FUNC); } "param" { RETURN(PARAM); } "result" { RETURN(RESULT); } "local" { RETURN(LOCAL); } "global" { RETURN(GLOBAL); } "module" { RETURN(MODULE); } "binary" { RETURN(BIN); } "quote" { RETURN(QUOTE); } "table" { RETURN(TABLE); } "memory" { RETURN(MEMORY); } "start" { RETURN(START); } "elem" { RETURN(ELEM); } "data" { RETURN(DATA); } "offset" { RETURN(OFFSET); } "import" { RETURN(IMPORT); } "export" { RETURN(EXPORT); } "except" { RETURN(EXCEPT); } "register" { RETURN(REGISTER); } "invoke" { RETURN(INVOKE); } "get" { RETURN(GET); } "assert_malformed" { RETURN(ASSERT_MALFORMED); } "assert_invalid" { RETURN(ASSERT_INVALID); } "assert_unlinkable" { RETURN(ASSERT_UNLINKABLE); } "assert_return" { RETURN(ASSERT_RETURN); } "assert_return_canonical_nan" { RETURN(ASSERT_RETURN_CANONICAL_NAN); } "assert_return_arithmetic_nan" { RETURN(ASSERT_RETURN_ARITHMETIC_NAN); } "assert_trap" { RETURN(ASSERT_TRAP); } "assert_exhaustion" { RETURN(ASSERT_EXHAUSTION); } "try" { RETURN(TRY); } "catch" { RETURN_LPAR(CATCH); } "catch_all" { RETURN_LPAR(CATCH_ALL); } "throw" { RETURN(THROW); } "rethrow" { RETURN(RETHROW); } name { SetText(); RETURN(VAR); } ";;" => LINE_COMMENT { continue; } "\n" => i { NEWLINE; continue; } [^\n]+ { continue; } "(;" => BLOCK_COMMENT { COMMENT_NESTING = 1; continue; } "(;" { COMMENT_NESTING++; continue; } ";)" { if (--COMMENT_NESTING == 0) BEGIN(YYCOND_i); continue; } "\n" { NEWLINE; continue; } [^] { continue; } * { MAYBE_MALFORMED_UTF8(" in block comment"); } "\n" { NEWLINE; continue; } [ \t\r]+ { continue; } reserved { ERROR("unexpected token \"%.*s\"", static_cast(yyleng), yytext); continue; } [^] { ERROR("unexpected char"); continue; } <*> * { MAYBE_MALFORMED_UTF8(""); } */ } } } // namespace wabt