diff options
Diffstat (limited to 'scripts/gen-s-parser.py')
-rwxr-xr-x | scripts/gen-s-parser.py | 408 |
1 files changed, 408 insertions, 0 deletions
diff --git a/scripts/gen-s-parser.py b/scripts/gen-s-parser.py new file mode 100755 index 000000000..00989ab43 --- /dev/null +++ b/scripts/gen-s-parser.py @@ -0,0 +1,408 @@ +#!/usr/bin/env python3 +# +# Copyright 2018 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. + +instructions = [ + ("unreachable", "makeUnreachable()"), + ("nop", "makeNop()"), + ("block", "makeBlock(s)"), + ("loop", "makeLoop(s)"), + ("if", "makeIf(s)"), + ("then", "makeThenOrElse(s)"), + ("else", "makeThenOrElse(s)"), + ("br", "makeBreak(s)"), + ("br_if", "makeBreak(s)"), + ("br_table", "makeBreakTable(s)"), + ("return", "makeReturn(s)"), + ("call", "makeCall(s)"), + ("call_indirect", "makeCallIndirect(s)"), + ("drop", "makeDrop(s)"), + ("select", "makeSelect(s)"), + ("get_local", "makeGetLocal(s)"), + ("set_local", "makeSetLocal(s)"), + ("tee_local", "makeTeeLocal(s)"), + ("get_global", "makeGetGlobal(s)"), + ("set_global", "makeSetGlobal(s)"), + ("i32.load", "makeLoad(s, i32, /*isAtomic=*/false)"), + ("i64.load", "makeLoad(s, i64, /*isAtomic=*/false)"), + ("f32.load", "makeLoad(s, f32, /*isAtomic=*/false)"), + ("f64.load", "makeLoad(s, f64, /*isAtomic=*/false)"), + ("i32.load8_s", "makeLoad(s, i32, /*isAtomic=*/false)"), + ("i32.load8_u", "makeLoad(s, i32, /*isAtomic=*/false)"), + ("i32.load16_s", "makeLoad(s, i32, /*isAtomic=*/false)"), + ("i32.load16_u", "makeLoad(s, i32, /*isAtomic=*/false)"), + ("i64.load8_s", "makeLoad(s, i64, /*isAtomic=*/false)"), + ("i64.load8_u", "makeLoad(s, i64, /*isAtomic=*/false)"), + ("i64.load16_s", "makeLoad(s, i64, /*isAtomic=*/false)"), + ("i64.load16_u", "makeLoad(s, i64, /*isAtomic=*/false)"), + ("i64.load32_s", "makeLoad(s, i64, /*isAtomic=*/false)"), + ("i64.load32_u", "makeLoad(s, i64, /*isAtomic=*/false)"), + ("i32.store", "makeStore(s, i32, /*isAtomic=*/false)"), + ("i64.store", "makeStore(s, i64, /*isAtomic=*/false)"), + ("f32.store", "makeStore(s, f32, /*isAtomic=*/false)"), + ("f64.store", "makeStore(s, f64, /*isAtomic=*/false)"), + ("i32.store8", "makeStore(s, i32, /*isAtomic=*/false)"), + ("i32.store16", "makeStore(s, i32, /*isAtomic=*/false)"), + ("i64.store8", "makeStore(s, i64, /*isAtomic=*/false)"), + ("i64.store16", "makeStore(s, i64, /*isAtomic=*/false)"), + ("i64.store32", "makeStore(s, i64, /*isAtomic=*/false)"), + ("current_memory", "makeHost(s, HostOp::CurrentMemory)"), + ("grow_memory", "makeHost(s, HostOp::GrowMemory)"), + ("i32.const", "makeConst(s, i32)"), + ("i64.const", "makeConst(s, i64)"), + ("f32.const", "makeConst(s, f32)"), + ("f64.const", "makeConst(s, f64)"), + ("i32.eqz", "makeUnary(s, UnaryOp::EqZInt32)"), + ("i32.eq", "makeBinary(s, BinaryOp::EqInt32)"), + ("i32.ne", "makeBinary(s, BinaryOp::NeInt32)"), + ("i32.lt_s", "makeBinary(s, BinaryOp::LtSInt32)"), + ("i32.lt_u", "makeBinary(s, BinaryOp::LtUInt32)"), + ("i32.gt_s", "makeBinary(s, BinaryOp::GtSInt32)"), + ("i32.gt_u", "makeBinary(s, BinaryOp::GtUInt32)"), + ("i32.le_s", "makeBinary(s, BinaryOp::LeSInt32)"), + ("i32.le_u", "makeBinary(s, BinaryOp::LeUInt32)"), + ("i32.ge_s", "makeBinary(s, BinaryOp::GeSInt32)"), + ("i32.ge_u", "makeBinary(s, BinaryOp::GeUInt32)"), + ("i64.eqz", "makeUnary(s, UnaryOp::EqZInt64)"), + ("i64.eq", "makeBinary(s, BinaryOp::EqInt64)"), + ("i64.ne", "makeBinary(s, BinaryOp::NeInt64)"), + ("i64.lt_s", "makeBinary(s, BinaryOp::LtSInt64)"), + ("i64.lt_u", "makeBinary(s, BinaryOp::LtUInt64)"), + ("i64.gt_s", "makeBinary(s, BinaryOp::GtSInt64)"), + ("i64.gt_u", "makeBinary(s, BinaryOp::GtUInt64)"), + ("i64.le_s", "makeBinary(s, BinaryOp::LeSInt64)"), + ("i64.le_u", "makeBinary(s, BinaryOp::LeUInt64)"), + ("i64.ge_s", "makeBinary(s, BinaryOp::GeSInt64)"), + ("i64.ge_u", "makeBinary(s, BinaryOp::GeUInt64)"), + ("f32.eq", "makeBinary(s, BinaryOp::EqFloat32)"), + ("f32.ne", "makeBinary(s, BinaryOp::NeFloat32)"), + ("f32.lt", "makeBinary(s, BinaryOp::LtFloat32)"), + ("f32.gt", "makeBinary(s, BinaryOp::GtFloat32)"), + ("f32.le", "makeBinary(s, BinaryOp::LeFloat32)"), + ("f32.ge", "makeBinary(s, BinaryOp::GeFloat32)"), + ("f64.eq", "makeBinary(s, BinaryOp::EqFloat64)"), + ("f64.ne", "makeBinary(s, BinaryOp::NeFloat64)"), + ("f64.lt", "makeBinary(s, BinaryOp::LtFloat64)"), + ("f64.gt", "makeBinary(s, BinaryOp::GtFloat64)"), + ("f64.le", "makeBinary(s, BinaryOp::LeFloat64)"), + ("f64.ge", "makeBinary(s, BinaryOp::GeFloat64)"), + ("i32.clz", "makeUnary(s, UnaryOp::ClzInt32)"), + ("i32.ctz", "makeUnary(s, UnaryOp::CtzInt32)"), + ("i32.popcnt", "makeUnary(s, UnaryOp::PopcntInt32)"), + ("i32.add", "makeBinary(s, BinaryOp::AddInt32)"), + ("i32.sub", "makeBinary(s, BinaryOp::SubInt32)"), + ("i32.mul", "makeBinary(s, BinaryOp::MulInt32)"), + ("i32.div_s", "makeBinary(s, BinaryOp::DivSInt32)"), + ("i32.div_u", "makeBinary(s, BinaryOp::DivUInt32)"), + ("i32.rem_s", "makeBinary(s, BinaryOp::RemSInt32)"), + ("i32.rem_u", "makeBinary(s, BinaryOp::RemUInt32)"), + ("i32.and", "makeBinary(s, BinaryOp::AndInt32)"), + ("i32.or", "makeBinary(s, BinaryOp::OrInt32)"), + ("i32.xor", "makeBinary(s, BinaryOp::XorInt32)"), + ("i32.shl", "makeBinary(s, BinaryOp::ShlInt32)"), + ("i32.shr_s", "makeBinary(s, BinaryOp::ShrSInt32)"), + ("i32.shr_u", "makeBinary(s, BinaryOp::ShrUInt32)"), + ("i32.rotl", "makeBinary(s, BinaryOp::RotLInt32)"), + ("i32.rotr", "makeBinary(s, BinaryOp::RotRInt32)"), + ("i64.clz", "makeUnary(s, UnaryOp::ClzInt64)"), + ("i64.ctz", "makeUnary(s, UnaryOp::CtzInt64)"), + ("i64.popcnt", "makeUnary(s, UnaryOp::PopcntInt64)"), + ("i64.add", "makeBinary(s, BinaryOp::AddInt64)"), + ("i64.sub", "makeBinary(s, BinaryOp::SubInt64)"), + ("i64.mul", "makeBinary(s, BinaryOp::MulInt64)"), + ("i64.div_s", "makeBinary(s, BinaryOp::DivSInt64)"), + ("i64.div_u", "makeBinary(s, BinaryOp::DivUInt64)"), + ("i64.rem_s", "makeBinary(s, BinaryOp::RemSInt64)"), + ("i64.rem_u", "makeBinary(s, BinaryOp::RemUInt64)"), + ("i64.and", "makeBinary(s, BinaryOp::AndInt64)"), + ("i64.or", "makeBinary(s, BinaryOp::OrInt64)"), + ("i64.xor", "makeBinary(s, BinaryOp::XorInt64)"), + ("i64.shl", "makeBinary(s, BinaryOp::ShlInt64)"), + ("i64.shr_s", "makeBinary(s, BinaryOp::ShrSInt64)"), + ("i64.shr_u", "makeBinary(s, BinaryOp::ShrUInt64)"), + ("i64.rotl", "makeBinary(s, BinaryOp::RotLInt64)"), + ("i64.rotr", "makeBinary(s, BinaryOp::RotRInt64)"), + ("f32.abs", "makeUnary(s, UnaryOp::AbsFloat32)"), + ("f32.neg", "makeUnary(s, UnaryOp::NegFloat32)"), + ("f32.ceil", "makeUnary(s, UnaryOp::CeilFloat32)"), + ("f32.floor", "makeUnary(s, UnaryOp::FloorFloat32)"), + ("f32.trunc", "makeUnary(s, UnaryOp::TruncFloat32)"), + ("f32.nearest", "makeUnary(s, UnaryOp::NearestFloat32)"), + ("f32.sqrt", "makeUnary(s, UnaryOp::SqrtFloat32)"), + ("f32.add", "makeBinary(s, BinaryOp::AddFloat32)"), + ("f32.sub", "makeBinary(s, BinaryOp::SubFloat32)"), + ("f32.mul", "makeBinary(s, BinaryOp::MulFloat32)"), + ("f32.div", "makeBinary(s, BinaryOp::DivFloat32)"), + ("f32.min", "makeBinary(s, BinaryOp::MinFloat32)"), + ("f32.max", "makeBinary(s, BinaryOp::MaxFloat32)"), + ("f32.copysign", "makeBinary(s, BinaryOp::CopySignFloat32)"), + ("f64.abs", "makeUnary(s, UnaryOp::AbsFloat64)"), + ("f64.neg", "makeUnary(s, UnaryOp::NegFloat64)"), + ("f64.ceil", "makeUnary(s, UnaryOp::CeilFloat64)"), + ("f64.floor", "makeUnary(s, UnaryOp::FloorFloat64)"), + ("f64.trunc", "makeUnary(s, UnaryOp::TruncFloat64)"), + ("f64.nearest", "makeUnary(s, UnaryOp::NearestFloat64)"), + ("f64.sqrt", "makeUnary(s, UnaryOp::SqrtFloat64)"), + ("f64.add", "makeBinary(s, BinaryOp::AddFloat64)"), + ("f64.sub", "makeBinary(s, BinaryOp::SubFloat64)"), + ("f64.mul", "makeBinary(s, BinaryOp::MulFloat64)"), + ("f64.div", "makeBinary(s, BinaryOp::DivFloat64)"), + ("f64.min", "makeBinary(s, BinaryOp::MinFloat64)"), + ("f64.max", "makeBinary(s, BinaryOp::MaxFloat64)"), + ("f64.copysign", "makeBinary(s, BinaryOp::CopySignFloat64)"), + ("i32.wrap/i64", "makeUnary(s, UnaryOp::WrapInt64)"), + ("i32.trunc_s/f32", "makeUnary(s, UnaryOp::TruncSFloat32ToInt32)"), + ("i32.trunc_u/f32", "makeUnary(s, UnaryOp::TruncUFloat32ToInt32)"), + ("i32.trunc_s/f64", "makeUnary(s, UnaryOp::TruncSFloat64ToInt32)"), + ("i32.trunc_u/f64", "makeUnary(s, UnaryOp::TruncUFloat64ToInt32)"), + ("i64.extend_s/i32", "makeUnary(s, UnaryOp::ExtendSInt32)"), + ("i64.extend_u/i32", "makeUnary(s, UnaryOp::ExtendUInt32)"), + ("i64.trunc_s/f32", "makeUnary(s, UnaryOp::TruncSFloat32ToInt64)"), + ("i64.trunc_u/f32", "makeUnary(s, UnaryOp::TruncUFloat32ToInt64)"), + ("i64.trunc_s/f64", "makeUnary(s, UnaryOp::TruncSFloat64ToInt64)"), + ("i64.trunc_u/f64", "makeUnary(s, UnaryOp::TruncUFloat64ToInt64)"), + ("f32.convert_s/i32", "makeUnary(s, UnaryOp::ConvertSInt32ToFloat32)"), + ("f32.convert_u/i32", "makeUnary(s, UnaryOp::ConvertUInt32ToFloat32)"), + ("f32.convert_s/i64", "makeUnary(s, UnaryOp::ConvertSInt64ToFloat32)"), + ("f32.convert_u/i64", "makeUnary(s, UnaryOp::ConvertUInt64ToFloat32)"), + ("f32.demote/f64", "makeUnary(s, UnaryOp::DemoteFloat64)"), + ("f64.convert_s/i32", "makeUnary(s, UnaryOp::ConvertSInt32ToFloat64)"), + ("f64.convert_u/i32", "makeUnary(s, UnaryOp::ConvertUInt32ToFloat64)"), + ("f64.convert_s/i64", "makeUnary(s, UnaryOp::ConvertSInt64ToFloat64)"), + ("f64.convert_u/i64", "makeUnary(s, UnaryOp::ConvertUInt64ToFloat64)"), + ("f64.promote/f32", "makeUnary(s, UnaryOp::PromoteFloat32)"), + ("i32.reinterpret/f32", "makeUnary(s, UnaryOp::ReinterpretFloat32)"), + ("i64.reinterpret/f64", "makeUnary(s, UnaryOp::ReinterpretFloat64)"), + ("f32.reinterpret/i32", "makeUnary(s, UnaryOp::ReinterpretInt32)"), + ("f64.reinterpret/i64", "makeUnary(s, UnaryOp::ReinterpretInt64)"), + ("i32.extend8_s", "makeUnary(s, UnaryOp::ExtendS8Int32)"), + ("i32.extend16_s", "makeUnary(s, UnaryOp::ExtendS16Int32)"), + ("i64.extend8_s", "makeUnary(s, UnaryOp::ExtendS8Int64)"), + ("i64.extend16_s", "makeUnary(s, UnaryOp::ExtendS16Int64)"), + ("i64.extend32_s", "makeUnary(s, UnaryOp::ExtendS32Int64)"), + # atomic instructions + ("wake", "makeAtomicWake(s)"), + ("i32.wait", "makeAtomicWait(s, i32)"), + ("i64.wait", "makeAtomicWait(s, i64)"), + ("i32.atomic.load8_u", "makeLoad(s, i32, /*isAtomic=*/true)"), + ("i32.atomic.load16_u", "makeLoad(s, i32, /*isAtomic=*/true)"), + ("i32.atomic.load", "makeLoad(s, i32, /*isAtomic=*/true)"), + ("i64.atomic.load8_u", "makeLoad(s, i64, /*isAtomic=*/true)"), + ("i64.atomic.load16_u", "makeLoad(s, i64, /*isAtomic=*/true)"), + ("i64.atomic.load32_u", "makeLoad(s, i64, /*isAtomic=*/true)"), + ("i64.atomic.load", "makeLoad(s, i64, /*isAtomic=*/true)"), + ("i32.atomic.store8", "makeStore(s, i32, /*isAtomic=*/true)"), + ("i32.atomic.store16", "makeStore(s, i32, /*isAtomic=*/true)"), + ("i32.atomic.store", "makeStore(s, i32, /*isAtomic=*/true)"), + ("i64.atomic.store8", "makeStore(s, i64, /*isAtomic=*/true)"), + ("i64.atomic.store16", "makeStore(s, i64, /*isAtomic=*/true)"), + ("i64.atomic.store32", "makeStore(s, i64, /*isAtomic=*/true)"), + ("i64.atomic.store", "makeStore(s, i64, /*isAtomic=*/true)"), + ("i32.atomic.rmw8_u.add", "makeAtomicRMWOrCmpxchg(s, i32)"), + ("i32.atomic.rmw16_u.add", "makeAtomicRMWOrCmpxchg(s, i32)"), + ("i32.atomic.rmw.add", "makeAtomicRMWOrCmpxchg(s, i32)"), + ("i64.atomic.rmw8_u.add", "makeAtomicRMWOrCmpxchg(s, i64)"), + ("i64.atomic.rmw16_u.add", "makeAtomicRMWOrCmpxchg(s, i64)"), + ("i64.atomic.rmw32_u.add", "makeAtomicRMWOrCmpxchg(s, i64)"), + ("i64.atomic.rmw.add", "makeAtomicRMWOrCmpxchg(s, i64)"), + ("i32.atomic.rmw8_u.sub", "makeAtomicRMWOrCmpxchg(s, i32)"), + ("i32.atomic.rmw16_u.sub", "makeAtomicRMWOrCmpxchg(s, i32)"), + ("i32.atomic.rmw.sub", "makeAtomicRMWOrCmpxchg(s, i32)"), + ("i64.atomic.rmw8_u.sub", "makeAtomicRMWOrCmpxchg(s, i64)"), + ("i64.atomic.rmw16_u.sub", "makeAtomicRMWOrCmpxchg(s, i64)"), + ("i64.atomic.rmw32_u.sub", "makeAtomicRMWOrCmpxchg(s, i64)"), + ("i64.atomic.rmw.sub", "makeAtomicRMWOrCmpxchg(s, i64)"), + ("i32.atomic.rmw8_u.and", "makeAtomicRMWOrCmpxchg(s, i32)"), + ("i32.atomic.rmw16_u.and", "makeAtomicRMWOrCmpxchg(s, i32)"), + ("i32.atomic.rmw.and", "makeAtomicRMWOrCmpxchg(s, i32)"), + ("i64.atomic.rmw8_u.and", "makeAtomicRMWOrCmpxchg(s, i64)"), + ("i64.atomic.rmw16_u.and", "makeAtomicRMWOrCmpxchg(s, i64)"), + ("i64.atomic.rmw32_u.and", "makeAtomicRMWOrCmpxchg(s, i64)"), + ("i64.atomic.rmw.and", "makeAtomicRMWOrCmpxchg(s, i64)"), + ("i32.atomic.rmw8_u.or", "makeAtomicRMWOrCmpxchg(s, i32)"), + ("i32.atomic.rmw16_u.or", "makeAtomicRMWOrCmpxchg(s, i32)"), + ("i32.atomic.rmw.or", "makeAtomicRMWOrCmpxchg(s, i32)"), + ("i64.atomic.rmw8_u.or", "makeAtomicRMWOrCmpxchg(s, i64)"), + ("i64.atomic.rmw16_u.or", "makeAtomicRMWOrCmpxchg(s, i64)"), + ("i64.atomic.rmw32_u.or", "makeAtomicRMWOrCmpxchg(s, i64)"), + ("i64.atomic.rmw.or", "makeAtomicRMWOrCmpxchg(s, i64)"), + ("i32.atomic.rmw8_u.xor", "makeAtomicRMWOrCmpxchg(s, i32)"), + ("i32.atomic.rmw16_u.xor", "makeAtomicRMWOrCmpxchg(s, i32)"), + ("i32.atomic.rmw.xor", "makeAtomicRMWOrCmpxchg(s, i32)"), + ("i64.atomic.rmw8_u.xor", "makeAtomicRMWOrCmpxchg(s, i64)"), + ("i64.atomic.rmw16_u.xor", "makeAtomicRMWOrCmpxchg(s, i64)"), + ("i64.atomic.rmw32_u.xor", "makeAtomicRMWOrCmpxchg(s, i64)"), + ("i64.atomic.rmw.xor", "makeAtomicRMWOrCmpxchg(s, i64)"), + ("i32.atomic.rmw8_u.xchg", "makeAtomicRMWOrCmpxchg(s, i32)"), + ("i32.atomic.rmw16_u.xchg", "makeAtomicRMWOrCmpxchg(s, i32)"), + ("i32.atomic.rmw.xchg", "makeAtomicRMWOrCmpxchg(s, i32)"), + ("i64.atomic.rmw8_u.xchg", "makeAtomicRMWOrCmpxchg(s, i64)"), + ("i64.atomic.rmw16_u.xchg", "makeAtomicRMWOrCmpxchg(s, i64)"), + ("i64.atomic.rmw32_u.xchg", "makeAtomicRMWOrCmpxchg(s, i64)"), + ("i64.atomic.rmw.xchg", "makeAtomicRMWOrCmpxchg(s, i64)"), + ("i32.atomic.rmw8_u.cmpxchg", "makeAtomicRMWOrCmpxchg(s, i32)"), + ("i32.atomic.rmw16_u.cmpxchg", "makeAtomicRMWOrCmpxchg(s, i32)"), + ("i32.atomic.rmw.cmpxchg", "makeAtomicRMWOrCmpxchg(s, i32)"), + ("i64.atomic.rmw8_u.cmpxchg", "makeAtomicRMWOrCmpxchg(s, i64)"), + ("i64.atomic.rmw16_u.cmpxchg", "makeAtomicRMWOrCmpxchg(s, i64)"), + ("i64.atomic.rmw32_u.cmpxchg", "makeAtomicRMWOrCmpxchg(s, i64)"), + ("i64.atomic.rmw.cmpxchg", "makeAtomicRMWOrCmpxchg(s, i64)") +] + + +class CodePrinter: + indents = 0 + + def __enter__(self): + CodePrinter.indents += 1 + + def __exit__(self, *args): + CodePrinter.indents -= 1 + + def indent(self): + # call in a 'with' statement + return self + + def print_line(self, line): + print(" " * CodePrinter.indents + line) + + +class Node: + def __init__(self, expr=None, children=None, inst=None): + # the expression to return if this is the string has ended + self.expr = expr + # map unique strings to children nodes + self.children = children if children else {} + # full instruction leading to this node + self.inst = inst + + def _common_prefix(a, b): + """Return the common prefix of two strings.""" + prefix = [] + while a and b and a[0] == b[0]: + prefix.append(a[0]) + a = a[1:] + b = b[1:] + return "".join(prefix) + + def do_insert(self, full_inst, inst, expr): + if inst is "": + assert self.expr is None, "Repeated instruction" + self.expr = expr + self.inst = full_inst + return + # find key with shared prefix + prefix, key = "", None + for k in self.children: + prefix = Node._common_prefix(inst, k) + if prefix is not "": + key = k + break + if key is None: + # unique prefix, insert and stop + self.children[inst] = Node(expr, inst=full_inst) + return + key_remainder = key[len(prefix):] + if key_remainder is not "": + # split key and move everything after the prefix to a new node + child = self.children.pop(key) + self.children[prefix] = Node(children={key_remainder: child}) + # update key for recursive insert + key = prefix + # chop off prefix and recurse + self.children[key].do_insert(full_inst, inst[len(key):], expr) + + def insert(self, inst, expr): + self.do_insert(inst, inst, expr) + + def prune(self): + """Deduplicate siblings that would lead to the same expression.""" + if not self.children: + return + for child in self.children.values(): + child.prune() + exprs = set(self.expr) if self.expr else set() + for child in self.children.values(): + # only prune if all children are terminal + if child.children: + return + exprs.add(child.expr) + if len(exprs) != 1: + # children have different expressions, can't prune + return + # do prune + self.expr = exprs.pop() + self.inst = " | ".join(sorted(c.inst for c in self.children.values())) + self.children = {} + + +def instruction_parser(): + """Build a trie out of all the instructions, then emit it as C++ code.""" + trie = Node() + inst_length = 0 + for inst, expr in instructions: + inst_length = max(inst_length, len(inst)) + trie.insert(inst, expr) + trie.prune() + + printer = CodePrinter() + + printer.print_line("char op[{}] = {{'\\0'}};".format(inst_length + 1)) + printer.print_line("strncpy(op, s[0]->c_str(), {});".format(inst_length)) + + def emit(node, idx=0): + assert node.children + printer.print_line("switch (op[{}]) {{".format(idx)) + with printer.indent(): + if node.expr: + printer.print_line("case '\\0': return {}; // {}".format(node.expr, node.inst)) + children = sorted(node.children.items(), key=lambda pair: pair[0]) + for prefix, child in children: + if child.children: + printer.print_line("case '{}': {{".format(prefix[0])) + with printer.indent(): + emit(child, idx + len(prefix)) + printer.print_line("}") + else: + assert child.expr + printer.print_line("case '{}': return {}; // {}" + .format(prefix[0], child.expr, child.inst)) + printer.print_line("default: goto parse_error;") + printer.print_line("}") + + emit(trie) + printer.print_line("parse_error:") + with printer.indent(): + printer.print_line("throw ParseException(std::string(op));") + + +def print_header(): + print("// DO NOT EDIT! This file generated by scripts/gen-s-parser.py\n") + + +def generate_with_guard(generator, guard): + print("#ifdef {}".format(guard)) + print("#undef {}".format(guard)) + generator() + print("#endif // {}".format(guard)) + + +def main(): + print_header() + generate_with_guard(instruction_parser, "INSTRUCTION_PARSER") + + +if __name__ == "__main__": + main() |