Move formatting meta around, actually mark stuff up

This commit is contained in:
John Doty 2024-09-10 11:47:22 -07:00
parent 7edf5e06bf
commit 443bf8bd33
3 changed files with 61 additions and 57 deletions

View file

@ -134,7 +134,7 @@ def apply_precedence(js: str, name: str, grammar: parser.Grammar) -> str:
return js
def convert_to_tree_sitter(rule: parser.Rule, grammar: parser.Grammar) -> str:
def convert_to_tree_sitter(rule: parser.Rule, grammar: parser.Grammar) -> str | None:
method = getattr(rule, "convert_to_tree_sitter", None)
if method is not None:
return method(grammar)
@ -146,7 +146,7 @@ def convert_to_tree_sitter(rule: parser.Rule, grammar: parser.Grammar) -> str:
return f"$['{target_name}']"
elif isinstance(rule, parser.AlternativeRule):
final = []
final: list[str] = []
queue = []
has_nothing = False
queue.append(rule)
@ -155,15 +155,17 @@ def convert_to_tree_sitter(rule: parser.Rule, grammar: parser.Grammar) -> str:
if isinstance(part, parser.AlternativeRule):
queue.append(part.right)
queue.append(part.left)
elif isinstance(part, parser.NothingRule):
has_nothing = True
else:
final.append(part)
converted = convert_to_tree_sitter(part, grammar)
if converted is None:
has_nothing = True
else:
final.append(converted)
if len(final) == 0:
raise Exception("Unsupported rule: empty alternative")
result = ", ".join([convert_to_tree_sitter(r, grammar) for r in final])
result = ", ".join(final)
if len(final) > 1:
result = f"choice({result})"
if has_nothing:
@ -172,6 +174,7 @@ def convert_to_tree_sitter(rule: parser.Rule, grammar: parser.Grammar) -> str:
elif isinstance(rule, parser.SequenceRule):
final = []
pieces = []
queue = []
queue.append(rule)
while len(queue) > 0:
@ -179,10 +182,11 @@ def convert_to_tree_sitter(rule: parser.Rule, grammar: parser.Grammar) -> str:
if isinstance(part, parser.SequenceRule):
queue.append(part.second)
queue.append(part.first)
elif isinstance(part, parser.NothingRule):
pass
else:
final.append(part)
piece = convert_to_tree_sitter(part, grammar)
if piece is not None:
pieces.append(piece)
final.append(part)
if len(final) == 0:
raise Exception("Unsupported rule: empty sequence")
@ -196,8 +200,6 @@ def convert_to_tree_sitter(rule: parser.Rule, grammar: parser.Grammar) -> str:
#
# https://github.com/tree-sitter/tree-sitter/issues/372
#
pieces = [convert_to_tree_sitter(r, grammar) for r in final]
def make_seq(pieces: list[str]):
if len(pieces) == 1:
return pieces[0]
@ -223,11 +225,17 @@ def convert_to_tree_sitter(rule: parser.Rule, grammar: parser.Grammar) -> str:
elif isinstance(rule, parser.MetadataRule):
result = convert_to_tree_sitter(rule.rule, grammar)
if result is None:
return None
field = rule.metadata.get("field")
if field is not None:
result = f"field('{field}', {result})"
return result
elif isinstance(rule, parser.NothingRule):
return None
else:
raise ValueError(f"Rule {rule} not supported for tree-sitter")
@ -257,6 +265,8 @@ def emit_tree_sitter_grammar(grammar: parser.Grammar, path: pathlib.Path | str):
body = rule.fn(grammar)
rule_definition = convert_to_tree_sitter(body, grammar)
if rule_definition is None:
raise Exception(f"Tree-sitter does not support the empty rule {rule_name}")
rule_definition = apply_precedence(rule_definition, rule.name, grammar)
f.write(f" '{rule_name}': $ => {rule_definition},")