Commit f592bd95 authored by Igor Dejanovic's avatar Igor Dejanovic

Reworked cross-refs resolving in textx parser construction.

parent 8cd1f69e
...@@ -15,7 +15,7 @@ from collections import namedtuple ...@@ -15,7 +15,7 @@ from collections import namedtuple
from arpeggio import StrMatch, Optional, ZeroOrMore, OneOrMore, Sequence,\ from arpeggio import StrMatch, Optional, ZeroOrMore, OneOrMore, Sequence,\
OrderedChoice, RegExMatch, NoMatch, EOF,\ OrderedChoice, RegExMatch, NoMatch, EOF,\
SemanticAction,ParserPython, Combine, Parser, SemanticActionSingleChild,\ SemanticAction,ParserPython, Combine, Parser, SemanticActionSingleChild,\
SemanticActionBodyWithBraces, Terminal SemanticActionBodyWithBraces, Terminal, ParsingExpression
from arpeggio.export import PMDOTExporter, PTDOTExporter from arpeggio.export import PMDOTExporter, PTDOTExporter
from arpeggio import RegExMatch as _ from arpeggio import RegExMatch as _
...@@ -149,43 +149,37 @@ class TextXModelSA(SemanticAction): ...@@ -149,43 +149,37 @@ class TextXModelSA(SemanticAction):
def second_pass(self, parser, textx_parser): def second_pass(self, parser, textx_parser):
"""Cross reference resolving for parser model.""" """Cross reference resolving for parser model."""
if parser.debug:
print("RESOLVING XTEXT PARSER: second_pass")
resolved_set = set() resolved_set = set()
def resolve(node): def resolve(node):
"""Recursively resolve peg rule references.""" """Recursively resolve peg rule references."""
if node in resolved_set or not hasattr(node, 'nodes'):
return
resolved_set.add(node)
def _inner_resolve(rule): def _inner_resolve(rule):
if parser.debug:
print("Resolving rule: {}".format(rule))
if type(rule) == RuleMatchCrossRef: if type(rule) == RuleMatchCrossRef:
if rule.rule_name in textx_parser._peg_rules: rule_name = rule.rule_name
rule_name = rule.rule_name if rule_name in textx_parser._peg_rules:
rule = textx_parser._peg_rules[rule.rule_name] rule = textx_parser._peg_rules[rule_name]
else:
raise TextXSemanticError('Unexisting rule "{}" at position {}.'\
.format(rule.rule_name, parser.pos_to_linecol(rule.position)))
# Cached rule may be crossref also. assert isinstance(rule, ParsingExpression), type(rule)
while type(rule) == RuleMatchCrossRef: # Recurse
rule_name = rule.rule_name for idx, child in enumerate(rule.nodes):
rule = _inner_resolve(rule) if not child in resolved_set:
# Rewrite rule in the rules map resolved_set.add(rule)
textx_parser._peg_rules[rule_name] = rule rule.nodes[idx] = _inner_resolve(child)
return rule return rule
for idx, rule in enumerate(node.nodes): resolved_set.add(node)
# If crossref resolve _inner_resolve(node)
if type(rule) == RuleMatchCrossRef:
rule = _inner_resolve(rule)
node.nodes[idx] = _inner_resolve(rule)
# If still unresolved raise exception
if type(rule) == RuleMatchCrossRef:
raise TextXSemanticError('Unexisting rule "{}" at position {}.'\
.format(rule.rule_name, parser.pos_to_linecol(rule.position)))
# Depth-First processing
resolve(rule)
resolve(textx_parser.parser_model) resolve(textx_parser.parser_model)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment