Commit 84aaae8f authored by Igor Dejanovic's avatar Igor Dejanovic

Fixing comment model in peg parsers. Some cleanups and docstring fixing.

parent 2c9baecf
......@@ -1381,13 +1381,27 @@ class CrossRef(object):
class ParserPython(Parser):
def __init__(self, language_def, comment_def=None, *args, **kwargs):
"""
Constructs parser from python statements and expressions.
Args:
language_def (python function): A python function that defines
the root rule of the grammar.
comment_def (python function): A python function that defines
the root rule of the comments grammar.
"""
super(ParserPython, self).__init__(*args, **kwargs)
# PEG Abstract Syntax Graph
self.parser_model = self._from_python(language_def)
self.comments_model = self._from_python(comment_def) \
if comment_def else None
self.comments_model = None
if comment_def:
self.comments_model = self._from_python(comment_def)
self.comments_model.root = True
self.comments_model.rule_name = comment_def.__name__
# In debug mode export parser model to dot for
# visualization
......@@ -1397,11 +1411,6 @@ class ParserPython(Parser):
PMDOTExporter().exportFile(self.parser_model,
"{}_parser_model.dot".format(root_rule))
# Comments should be optional and there can be more of them
if self.comments_model:
self.comments_model.root = True
self.comments_model.rule_name = comment_def.__name__
def _parse(self):
return self.parser_model.parse(self)
......
......@@ -56,7 +56,7 @@ class ParserPEG(ParserPEGOrig):
parser.root_rule_name = self.root_rule_name
parse_tree = parser.parse(language_def)
# return parser.getASG(sem_actions=sem_actions)
return visit_parse_tree(parse_tree, PEGVisitor(self.root_rule_name,
self.comment_rule_name,
self.ignore_case,
debug=self.debug))
......@@ -51,10 +51,15 @@ def comment(): return "//", _(".*\n")
class PEGVisitor(PTNodeVisitor):
"""
Visitor that transforms parse tree to a PEG parser for the given language.
"""
def __init__(self, root_rule_name, ignore_case, *args, **kwargs):
def __init__(self, root_rule_name, comment_rule_name, ignore_case,
*args, **kwargs):
super(PEGVisitor, self).__init__(*args, **kwargs)
self.root_rule_name = root_rule_name
self.comment_rule_name = comment_rule_name
self.ignore_case = ignore_case
# Used for linking phase
self.peg_rules = {
......@@ -104,15 +109,17 @@ class PEGVisitor(PTNodeVisitor):
self.resolved.add(node)
return node
# Find root rule
# Find root and comment rules
self.resolved = set()
comment_rule = None
for rule in children:
if rule.rule_name == self.root_rule_name:
self.resolved = set()
resolved_rule = _resolve(rule)
return resolved_rule
root_rule = _resolve(rule)
if rule.rule_name == self.comment_rule_name:
comment_rule = _resolve(rule)
assert False, "Root rule not found!"
assert root_rule, "Root rule not found!"
return root_rule, comment_rule
def visit_rule(self, node, children):
rule_name = children[0]
......@@ -194,13 +201,28 @@ class PEGVisitor(PTNodeVisitor):
class ParserPEG(Parser):
def __init__(self, language_def, root_rule_name, comment_rule_name=None,
*args, **kwargs):
"""
Constructs parser from textual PEG definition.
Args:
language_def (str): A string describing language grammar using
PEG notation.
root_rule_name(str): The name of the root rule.
comment_rule_name(str): The name of the rule for comments.
"""
super(ParserPEG, self).__init__(*args, **kwargs)
self.root_rule_name = root_rule_name
self.comment_rule_name = comment_rule_name
# PEG Abstract Syntax Graph
self.parser_model = self._from_peg(language_def)
self.parser_model, self.comments_model = self._from_peg(language_def)
# Comments should be optional and there can be more of them
if self.comments_model:
self.comments_model.root = True
self.comments_model.rule_name = comment_rule_name
# In debug mode export parser model to dot for
# visualization
......@@ -210,11 +232,6 @@ class ParserPEG(Parser):
PMDOTExporter().exportFile(
self.parser_model, "{}_peg_parser_model.dot".format(root_rule))
# Comments should be optional and there can be more of them
if self.comments_model:
self.comments_model.root = True
self.comments_model.rule_name = comment_rule_name
def _parse(self):
return self.parser_model.parse(self)
......@@ -224,7 +241,7 @@ class ParserPEG(Parser):
parser.root_rule_name = self.root_rule_name
parse_tree = parser.parse(language_def)
# return parser.getASG(sem_actions=sem_actions)
return visit_parse_tree(parse_tree, PEGVisitor(self.root_rule_name,
self.comment_rule_name,
self.ignore_case,
debug=self.debug))
......@@ -63,19 +63,21 @@ def main(debug=False):
# ASG should be the same as parser.parser_model because semantic
# actions will create PEG parser (tree of ParsingExpressions).
asg = visit_parse_tree(parse_tree, PEGVisitor(root_rule_name='peggrammar',
ignore_case=False,
debug=debug))
parser_model, comment_model = visit_parse_tree(
parse_tree, PEGVisitor(root_rule_name='peggrammar',
comment_rule_name='comment',
ignore_case=False,
debug=debug))
if debug:
# This graph should be the same as peg_peg_parser_model.dot because
# they define the same parser.
PMDOTExporter().exportFile(asg,
"peg_peg_asg.dot")
PMDOTExporter().exportFile(parser_model,
"peg_peg_new_parser_model.dot")
# If we replace parser_mode with ASG constructed parser it will still
# parse PEG grammars
parser.parser_model = asg
parser.parser_model = parser_model
parser.parse(peg_grammar)
if __name__ == '__main__':
......
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