Skip to content

Commit 801ff52

Browse files
authored
Reject all nonexistent instructions in sexp format (#1756)
1 parent ec38a51 commit 801ff52

File tree

7 files changed

+886
-225
lines changed

7 files changed

+886
-225
lines changed

scripts/gen-s-parser.py

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -327,26 +327,6 @@ def do_insert(self, full_inst, inst, expr):
327327
def insert(self, inst, expr):
328328
self.do_insert(inst, inst, expr)
329329

330-
def prune(self):
331-
"""Deduplicate siblings that would lead to the same expression."""
332-
if not self.children:
333-
return
334-
for child in self.children.values():
335-
child.prune()
336-
exprs = set(self.expr) if self.expr else set()
337-
for child in self.children.values():
338-
# only prune if all children are terminal
339-
if child.children:
340-
return
341-
exprs.add(child.expr)
342-
if len(exprs) != 1:
343-
# children have different expressions, can't prune
344-
return
345-
# do prune
346-
self.expr = exprs.pop()
347-
self.inst = " | ".join(sorted(c.inst for c in self.children.values()))
348-
self.children = {}
349-
350330

351331
def instruction_parser():
352332
"""Build a trie out of all the instructions, then emit it as C++ code."""
@@ -355,19 +335,25 @@ def instruction_parser():
355335
for inst, expr in instructions:
356336
inst_length = max(inst_length, len(inst))
357337
trie.insert(inst, expr)
358-
trie.prune()
359338

360339
printer = CodePrinter()
361340

362341
printer.print_line("char op[{}] = {{'\\0'}};".format(inst_length + 1))
363342
printer.print_line("strncpy(op, s[0]->c_str(), {});".format(inst_length))
364343

344+
def print_leaf(expr, inst):
345+
printer.print_line("if (strcmp(op, \"{inst}\") == 0) return {expr};"
346+
.format(inst=inst, expr=expr))
347+
printer.print_line("goto parse_error;")
348+
365349
def emit(node, idx=0):
366350
assert node.children
367351
printer.print_line("switch (op[{}]) {{".format(idx))
368352
with printer.indent():
369353
if node.expr:
370-
printer.print_line("case '\\0': return {}; // {}".format(node.expr, node.inst))
354+
printer.print_line("case '\\0':")
355+
with printer.indent():
356+
print_leaf(node.expr, node.inst)
371357
children = sorted(node.children.items(), key=lambda pair: pair[0])
372358
for prefix, child in children:
373359
if child.children:
@@ -377,8 +363,9 @@ def emit(node, idx=0):
377363
printer.print_line("}")
378364
else:
379365
assert child.expr
380-
printer.print_line("case '{}': return {}; // {}"
381-
.format(prefix[0], child.expr, child.inst))
366+
printer.print_line("case '{}':".format(prefix[0]))
367+
with printer.indent():
368+
print_leaf(child.expr, child.inst)
382369
printer.print_line("default: goto parse_error;")
383370
printer.print_line("}")
384371

0 commit comments

Comments
 (0)