From 5aa2e182f12d17e8dcdd7f8e3df68616c3e61b5a Mon Sep 17 00:00:00 2001 From: Thomas Lively <7121787+tlively@users.noreply.github.com> Date: Mon, 11 Jul 2022 15:14:51 -0700 Subject: [Parser] Start to parse instructions (#4789) Update gen-s-parser.py to produce a second version of its parsing code that works with the new wat parser. The new version automatically replaces the `s` element argument in the existing parser with the `ctx` and `in` arguments used by the new parser, so adding new instructions will not require any additional work in gen-s-parser.py after this change. Also add stub `make***` functions to the new wat parser, with a few filled out, namely `makeNop`, `makeUnreachable`, `makeConst`, and `makeRefNull`. Update the `global` parser to parse global initializer instructions and update wat-kitchen-sink.wast to demonstrate that the instructions are parsed correctly. Adding new instruction classes will require adding a new `make***` function to wat-parser.cpp in additional to wasm-s-parser.{h,cpp} after this change, but adding a trivial failing implementation is good enough for the time being, so I don't expect this to appreciably increase our maintenance burden in the near term. The infrastructure for parsing folded instructions, instructions with operands, and control flow instructions will be implemented in future PRs. --- scripts/gen-s-parser.py | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) (limited to 'scripts') diff --git a/scripts/gen-s-parser.py b/scripts/gen-s-parser.py index d0848622f..eb921a6b9 100755 --- a/scripts/gen-s-parser.py +++ b/scripts/gen-s-parser.py @@ -693,7 +693,7 @@ class Node: self.do_insert(inst, inst, expr) -def instruction_parser(): +def instruction_parser(new_parser=False): """Build a trie out of all the instructions, then emit it as C++ code.""" trie = Node() inst_length = 0 @@ -703,12 +703,23 @@ def instruction_parser(): printer = CodePrinter() - printer.print_line("char op[{}] = {{'\\0'}};".format(inst_length + 1)) - printer.print_line("strncpy(op, s[0]->c_str(), {});".format(inst_length)) + if not new_parser: + printer.print_line("char op[{}] = {{'\\0'}};".format(inst_length + 1)) + printer.print_line("strncpy(op, s[0]->c_str(), {});".format(inst_length)) def print_leaf(expr, inst): - printer.print_line("if (strcmp(op, \"{inst}\") == 0) {{ return {expr}; }}" - .format(inst=inst, expr=expr)) + if new_parser: + expr = expr.replace("()", "(ctx)") + expr = expr.replace("(s", "(ctx, in") + printer.print_line("if (op == \"{inst}\"sv) {{".format(inst=inst)) + with printer.indent(): + printer.print_line("auto ret = {expr};".format(expr=expr)) + printer.print_line("CHECK_ERR(ret);") + printer.print_line("return *ret;") + printer.print_line("}") + else: + printer.print_line("if (strcmp(op, \"{inst}\") == 0) {{ return {expr}; }}" + .format(inst=inst, expr=expr)) printer.print_line("goto parse_error;") def emit(node, idx=0): @@ -737,7 +748,10 @@ def instruction_parser(): emit(trie) printer.print_line("parse_error:") with printer.indent(): - printer.print_line("throw ParseException(std::string(op), s.line, s.col);") + if new_parser: + printer.print_line("return in.err(\"unrecognized instruction\");") + else: + printer.print_line("throw ParseException(std::string(op), s.line, s.col);") def print_header(): @@ -763,6 +777,8 @@ def main(): sys.exit(1) print_header() generate_with_guard(instruction_parser, "INSTRUCTION_PARSER") + print() + generate_with_guard(lambda: instruction_parser(True), "NEW_INSTRUCTION_PARSER") print_footer() -- cgit v1.2.3