1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# -*- coding: utf-8 -*-
##############################################################################
# Name: peg_peg.py
# Purpose: PEG parser definition using PEG itself.
# Author: Igor R. Dejanovic <igor DOT dejanovic AT gmail DOT com>
# Copyright: (c) 2009 Igor R. Dejanovic <igor DOT dejanovic AT gmail DOT com>
# License: MIT License
#
# PEG can be used to describe PEG.
# This example demonstrates building PEG parser using PEG based grammar of PEG
# grammar definition language.
##############################################################################
from arpeggio import *
from arpeggio.export import PMDOTExporter, PTDOTExporter
from arpeggio.peg import ParserPEG
# Semantic actions
from arpeggio.peg import SemGrammar, sem_rule, sem_sequence, sem_ordered_choice,\
sem_sufix, sem_prefix, sem_strmatch, sem_regex, sem_rule_crossref
sem_actions = {
"peggrammar": SemGrammar(),
"rule": sem_rule,
"ordered_choice": sem_ordered_choice,
"sequence": sem_sequence,
"prefix": sem_prefix,
"sufix": sem_sufix,
"expression": SemanticActionSingleChild(),
"regex": sem_regex,
"str_match": sem_strmatch,
"rule_crossref": sem_rule_crossref
}
# PEG defined using PEG itself.
peg_grammar = r"""
peggrammar <- rule+ EOF;
rule <- rule_name LEFT_ARROW ordered_choice ';';
ordered_choice <- sequence (SLASH sequence)*;
sequence <- prefix+;
prefix <- (AND/NOT)? sufix;
sufix <- expression (QUESTION/STAR/PLUS)?;
expression <- regex / rule_crossref
/ (OPEN ordered_choice CLOSE) / str_match;
rule_name <- r'[a-zA-Z_]([a-zA-Z_]|[0-9])*';
rule_crossref <- rule_name;
regex <- 'r\'' r'(\\\'|[^\'])*' '\'';
str_match <- r'\'(\\\'|[^\'])*\'|"[^"]*"';
LEFT_ARROW <- '<-';
SLASH <- '/';
AND <- '&';
NOT <- '!';
QUESTION <- '?';
STAR <- '*';
PLUS <- '+';
OPEN <- '(';
CLOSE <- ')';
DOT <- '.';
comment <- '//' r'.*\n';
"""
def main(debug=False):
# ParserPEG will use ParserPython to parse peg_grammar definition and
# create parser_model for parsing PEG based grammars
# In debug mode dot (graphviz) files for parser model
# and parse tree will be created for visualization.
# Checkout current folder for .dot files.
parser = ParserPEG(peg_grammar, 'peggrammar', debug=debug)
# Now we will use created parser to parse the same peg_grammar used for
# parser initialization. We can parse peg_grammar because it is specified
# using PEG itself.
parser.parse(peg_grammar)
# ASG should be the same as parser.parser_model because semantic
# actions will create PEG parser (tree of ParsingExpressions).
asg = parser.getASG(sem_actions)
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")
# If we replace parser_mode with ASG constructed parser it will still
# parse PEG grammars
parser.parser_model = asg
parser.parse(peg_grammar)
if __name__ == '__main__':
main(debug=True)