1# -*- coding: utf-8 -*- 2####################################################################### 3# Name: cleanpeg.py 4# Purpose: This module is a variation of the original peg.py. 5# The syntax is slightly changed to be more readable and familiar to 6# python users. It is based on the Yash's suggestion - issue 11 7# Author: Igor R. Dejanovic <igor DOT dejanovic AT gmail DOT com> 8# Copyright: (c) 2014-2017 Igor R. Dejanovic <igor DOT dejanovic AT gmail DOT com> 9# License: MIT License 10####################################################################### 11 12from __future__ import print_function, unicode_literals 13 14from arpeggio import Optional, ZeroOrMore, Not, OneOrMore, EOF, ParserPython, \ 15 visit_parse_tree 16from arpeggio import RegExMatch as _ 17from .peg import PEGVisitor 18from .peg import ParserPEG as ParserPEGOrig 19 20__all__ = ['ParserPEG'] 21 22# Lexical invariants 23ASSIGNMENT = "=" 24ORDERED_CHOICE = "/" 25ZERO_OR_MORE = "*" 26ONE_OR_MORE = "+" 27OPTIONAL = "?" 28UNORDERED_GROUP = "#" 29AND = "&" 30NOT = "!" 31OPEN = "(" 32CLOSE = ")" 33 34# PEG syntax rules 35def peggrammar(): return OneOrMore(rule), EOF 36def rule(): return rule_name, ASSIGNMENT, ordered_choice 37def ordered_choice(): return sequence, ZeroOrMore(ORDERED_CHOICE, sequence) 38def sequence(): return OneOrMore(prefix) 39def prefix(): return Optional([AND, NOT]), sufix 40def sufix(): return expression, Optional([OPTIONAL, 41 ZERO_OR_MORE, 42 ONE_OR_MORE, 43 UNORDERED_GROUP]) 44def expression(): return [regex, rule_crossref, 45 (OPEN, ordered_choice, CLOSE), 46 str_match], Not(ASSIGNMENT) 47 48# PEG Lexical rules 49def regex(): return [("r'", _(r'''[^'\\]*(?:\\.[^'\\]*)*'''), "'"), 50 ('r"', _(r'''[^"\\]*(?:\\.[^"\\]*)*'''), '"')] 51def rule_name(): return _(r"[a-zA-Z_]([a-zA-Z_]|[0-9])*") 52def rule_crossref(): return rule_name 53def str_match(): return _(r'''(?s)('[^'\\]*(?:\\.[^'\\]*)*')|''' 54 r'''("[^"\\]*(?:\\.[^"\\]*)*")''') 55def comment(): return "//", _(".*\n") 56 57 58class ParserPEG(ParserPEGOrig): 59 60 def _from_peg(self, language_def): 61 parser = ParserPython(peggrammar, comment, reduce_tree=False, 62 debug=self.debug) 63 parser.root_rule_name = self.root_rule_name 64 parse_tree = parser.parse(language_def) 65 66 return visit_parse_tree(parse_tree, PEGVisitor(self.root_rule_name, 67 self.comment_rule_name, 68 self.ignore_case, 69 debug=self.debug)) 70