diff options
Diffstat (limited to 'scripts/gen-s-parser.py')
-rwxr-xr-x | scripts/gen-s-parser.py | 212 |
1 files changed, 106 insertions, 106 deletions
diff --git a/scripts/gen-s-parser.py b/scripts/gen-s-parser.py index 5b18ed340..d6653e112 100755 --- a/scripts/gen-s-parser.py +++ b/scripts/gen-s-parser.py @@ -434,143 +434,143 @@ instructions = [ class CodePrinter: - indents = 0 + indents = 0 - def __enter__(self): - CodePrinter.indents += 1 + def __enter__(self): + CodePrinter.indents += 1 - def __exit__(self, *args): - CodePrinter.indents -= 1 + def __exit__(self, *args): + CodePrinter.indents -= 1 - def indent(self): - # call in a 'with' statement - return self + def indent(self): + # call in a 'with' statement + return self - def print_line(self, line): - print(" " * CodePrinter.indents + line) + 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 __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 _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 not inst: - assert self.expr is None, "Repeated instruction " + full_inst - 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: - 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: - # 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 do_insert(self, full_inst, inst, expr): + if not inst: + assert self.expr is None, "Repeated instruction " + full_inst + 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: + 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: + # 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 insert(self, inst, expr): + self.do_insert(inst, inst, expr) 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) + """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) - printer = CodePrinter() + printer = CodePrinter() - printer.print_line("char op[{}] = {{'\\0'}};".format(inst_length + 1)) - printer.print_line("strncpy(op, s[0]->c_str(), {});".format(inst_length)) + 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)) - printer.print_line("goto parse_error;") + def print_leaf(expr, inst): + 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): - assert node.children - printer.print_line("switch (op[{}]) {{".format(idx)) - with printer.indent(): - if node.expr: - printer.print_line("case '\\0':") + def emit(node, idx=0): + assert node.children + printer.print_line("switch (op[{}]) {{".format(idx)) with printer.indent(): - print_leaf(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 '{}':".format(prefix[0])) - with printer.indent(): - print_leaf(child.expr, child.inst) - printer.print_line("default: goto parse_error;") - printer.print_line("}") + if node.expr: + printer.print_line("case '\\0':") + with printer.indent(): + print_leaf(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 '{}':".format(prefix[0])) + with printer.indent(): + print_leaf(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), s.line, s.col);") + emit(trie) + printer.print_line("parse_error:") + with printer.indent(): + printer.print_line("throw ParseException(std::string(op), s.line, s.col);") def print_header(): - print("// DO NOT EDIT! This file generated by scripts/gen-s-parser.py\n") - print("// clang-format off\n") + print("// DO NOT EDIT! This file generated by scripts/gen-s-parser.py\n") + print("// clang-format off\n") def print_footer(): - print("\n// clang-format on") + print("\n// clang-format on") def generate_with_guard(generator, guard): - print("#ifdef {}".format(guard)) - print("#undef {}".format(guard)) - generator() - print("#endif // {}".format(guard)) + print("#ifdef {}".format(guard)) + print("#undef {}".format(guard)) + generator() + print("#endif // {}".format(guard)) def main(): - if sys.version_info.major != 3: - import datetime - print("It's " + str(datetime.datetime.now().year) + "! Use Python 3!") - sys.exit(1) - print_header() - generate_with_guard(instruction_parser, "INSTRUCTION_PARSER") - print_footer() + if sys.version_info.major != 3: + import datetime + print("It's " + str(datetime.datetime.now().year) + "! Use Python 3!") + sys.exit(1) + print_header() + generate_with_guard(instruction_parser, "INSTRUCTION_PARSER") + print_footer() if __name__ == "__main__": - main() + main() |