Commit 2274c67f authored by Igor Dejanovic's avatar Igor Dejanovic

Refactoring PEG support

parent 07519b00
...@@ -8,28 +8,15 @@ ...@@ -8,28 +8,15 @@
####################################################################### #######################################################################
from __future__ import print_function from __future__ import print_function
from kivy.lang import ParserException
__all__ = ['ParserPEG'] __all__ = ['ParserPEG']
from arpeggio import * from arpeggio import *
from arpeggio import RegExMatch as _ from arpeggio import RegExMatch as _
# PEG Grammar
def grammar(): return OneOrMore(rule), EOF
def rule(): return identifier, LEFT_ARROW, ordered_choice, ";"
def ordered_choice(): return sequence, ZeroOrMore(SLASH, sequence)
def sequence(): return OneOrMore(prefix)
def prefix(): return Optional([AND,NOT]), sufix
def sufix(): return expression, Optional([QUESTION, STAR, PLUS])
def expression(): return [regex,(identifier, Not(LEFT_ARROW)),
(OPEN, ordered_choice, CLOSE),
literal]
def regex(): return "r'", _(r"(\\\'|[^\'])*"),"'"
def identifier(): return _(r"[a-zA-Z_]([a-zA-Z_]|[0-9])*")
#def literal(): return [_(r"\'(\\\'|[^\'])*\'"),_(r'"[^"]*"')]
def literal(): return _(r'(\'(\\\'|[^\'])*\')|("[^"]*")')
# PEG Lexical rules
def LEFT_ARROW(): return "<-" def LEFT_ARROW(): return "<-"
def SLASH(): return "/" def SLASH(): return "/"
def STAR(): return "*" def STAR(): return "*"
...@@ -39,22 +26,57 @@ def AND(): return "&" ...@@ -39,22 +26,57 @@ def AND(): return "&"
def NOT(): return "!" def NOT(): return "!"
def OPEN(): return "(" def OPEN(): return "("
def CLOSE(): return ")" def CLOSE(): return ")"
def regex(): return "r'", _(r"(\\\'|[^\'])*"),"'"
def rule_identifier(): return _(r"[a-zA-Z_]([a-zA-Z_]|[0-9])*")
#def literal(): return [_(r"\'(\\\'|[^\'])*\'"),_(r'"[^"]*"')]
def literal(): return _(r'(\'(\\\'|[^\'])*\')|("[^"]*")')
def comment(): return "//", _(".*\n") def comment(): return "//", _(".*\n")
# PEG syntax rules
def grammar(): return OneOrMore(rule), EOF
def rule(): return rule_identifier, LEFT_ARROW, ordered_choice, ";"
def ordered_choice(): return sequence, ZeroOrMore(SLASH, sequence)
def sequence(): return OneOrMore(prefix)
def prefix(): return Optional([AND,NOT]), sufix
def sufix(): return expression, Optional([QUESTION, STAR, PLUS])
def expression(): return [regex,(rule_identifier, Not(LEFT_ARROW)),
(OPEN, ordered_choice, CLOSE),
literal]
# ------------------------------------------------------------------ # ------------------------------------------------------------------
# PEG Semantic Actions # PEG Semantic Actions
class RuleReference(object):
'''
Used for rule reference resolving in the second
pass of the semantic analysis.
'''
def __init__(self, rule_name):
self.rule_name = rule_name
class PEGSemanticAction(SemanticAction): class PEGSemanticAction(SemanticAction):
def _resolve(self, parser, rule_name):
if rule_name in parser.peg_rules:
if parser.debug:
print("Resolving reference {}".format(rule_name))
return parser.peg_rules[rule_name]
else:
raise SemanticError("Rule \"{}\" does not exists."
.format(rule_name))
def second_pass(self, parser, node): def second_pass(self, parser, node):
if isinstance(node, Terminal): if isinstance(node, RuleReference):
return return self._resolve(parser, node.rule_name)
for i, n in enumerate(node.nodes): elif isinstance(node, ParsingExpression):
if isinstance(n, Terminal): for i, n in node.nodes.items():
if n.value in parser.peg_rules: if isinstance(n, RuleReference):
node.nodes[i] = parser.peg_rules[n.value] node[i] = self._resolve(parser, n.rule_name)
else: return node
raise SemanticError("Rule \"%s\" does not exists." % n) else:
raise SemanticError("Invalid type '{}' after first pass."
.format(type(node)))
class SemGrammar(SemanticAction): class SemGrammar(SemanticAction):
...@@ -64,7 +86,7 @@ class SemGrammar(SemanticAction): ...@@ -64,7 +86,7 @@ class SemGrammar(SemanticAction):
class SemRule(PEGSemanticAction): class SemRule(PEGSemanticAction):
def first_pass(self, parser, node, children): def first_pass(self, parser, node, children):
rule_name = children[0].value rule_name = children[0]
if len(children) > 4: if len(children) > 4:
retval = Sequence(nodes=children[2:-1]) retval = Sequence(nodes=children[2:-1])
else: else:
...@@ -99,8 +121,6 @@ class SemOrderedChoice(PEGSemanticAction): ...@@ -99,8 +121,6 @@ class SemOrderedChoice(PEGSemanticAction):
class SemPrefix(PEGSemanticAction): class SemPrefix(PEGSemanticAction):
def first_pass(self, parser, node, children): def first_pass(self, parser, node, children):
if parser.debug:
print("Prefix: {} ".format(str(children)))
if len(children) == 2: if len(children) == 2:
if children[0] == NOT(): if children[0] == NOT():
retval = Not() retval = Not()
...@@ -118,11 +138,7 @@ class SemPrefix(PEGSemanticAction): ...@@ -118,11 +138,7 @@ class SemPrefix(PEGSemanticAction):
class SemSufix(PEGSemanticAction): class SemSufix(PEGSemanticAction):
def first_pass(self, parser, node, children): def first_pass(self, parser, node, children):
if parser.debug:
print("Sufix : {}".format(str(children)))
if len(children) == 2: if len(children) == 2:
if parser.debug:
print("Sufix : {}".format(str(children[1])))
if children[1] == STAR(): if children[1] == STAR():
retval = ZeroOrMore(children[0]) retval = ZeroOrMore(children[0])
elif children[1] == QUESTION(): elif children[1] == QUESTION():
...@@ -141,43 +157,30 @@ class SemSufix(PEGSemanticAction): ...@@ -141,43 +157,30 @@ class SemSufix(PEGSemanticAction):
class SemExpression(PEGSemanticAction): class SemExpression(PEGSemanticAction):
def first_pass(self, parser, node, children): def first_pass(self, parser, node, children):
if parser.debug:
print("Expression : {}".format(str(children)))
if len(children) == 1: if len(children) == 1:
return children[0] return children[0]
else: else:
return children[1] return children[1]
class SemIdentifier(SemanticAction): class SemIdentifier(PEGSemanticAction):
def first_pass(self, parser, node, children): def first_pass(self, parser, node, children):
if parser.debug: return super(SemIdentifier, self).first_pass(parser, node, children)
print("Identifier {}.".format(node.value))
return node
class SemRegEx(SemanticAction): class SemRegEx(SemanticAction):
def first_pass(self, parser, node, children): def first_pass(self, parser, node, children):
if parser.debug: return RegExMatch(children[1])
print("RegEx {}.".format(children[1].value))
return RegExMatch(children[1].value)
class SemLiteral(SemanticAction): class SemLiteral(SemanticAction):
def first_pass(self, parser, node, children): def first_pass(self, parser, node, children):
if parser.debug:
print("Literal: {}".format(node.value))
match_str = node.value[1:-1] match_str = node.value[1:-1]
match_str = match_str.replace("\\'", "'") match_str = match_str.replace("\\'", "'")
match_str = match_str.replace("\\\\", "\\") match_str = match_str.replace("\\\\", "\\")
return StrMatch(match_str) return StrMatch(match_str)
class SemTerminal(SemanticAction):
def first_pass(self, parser, node, children):
return StrMatch(node.value)
grammar.sem = SemGrammar() grammar.sem = SemGrammar()
rule.sem = SemRule() rule.sem = SemRule()
ordered_choice.sem = SemOrderedChoice() ordered_choice.sem = SemOrderedChoice()
...@@ -186,10 +189,8 @@ prefix.sem = SemPrefix() ...@@ -186,10 +189,8 @@ prefix.sem = SemPrefix()
sufix.sem = SemSufix() sufix.sem = SemSufix()
expression.sem = SemExpression() expression.sem = SemExpression()
regex.sem = SemRegEx() regex.sem = SemRegEx()
identifier.sem = SemIdentifier() rule_identifier.sem = SemIdentifier()
literal.sem = SemLiteral() literal.sem = SemLiteral()
for sem in [LEFT_ARROW, SLASH, STAR, QUESTION, PLUS, AND, NOT, OPEN, CLOSE]:
sem.sem = SemTerminal()
class ParserPEG(Parser): class ParserPEG(Parser):
...@@ -210,7 +211,7 @@ class ParserPEG(Parser): ...@@ -210,7 +211,7 @@ class ParserPEG(Parser):
return self.parser_model.parse(self) return self.parser_model.parse(self)
def _from_peg(self, language_def): def _from_peg(self, language_def):
parser = ParserPython(grammar, comment) parser = ParserPython(grammar, comment, reduce_tree=False, debug=True)
parser.root_rule_name = self.root_rule_name parser.root_rule_name = self.root_rule_name
parser.parse(language_def) parser.parse(language_def)
return parser.getASG() return parser.getASG()
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