File: sample1.py

package info (click to toggle)
pypeg2 2.15.2-2.2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 304 kB
  • sloc: python: 1,649; makefile: 3
file content (133 lines) | stat: -rw-r--r-- 3,962 bytes parent folder | download | duplicates (3)
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#!/usr/bin/python3
"""
Parsing sample

To parse we're giving a text to parse and an thing with a grammar. The default
setting includes skipping of whitespace, so we don't need to take care of that.

The comment parameter is set to C style /* comments */

>>> f = parse("int f(int a, long b) { do_this; do_that; }", Function, comment=comment_c)

Because function has a name() in its grammar, we can access this now as an
attribute. With Python 2.7 this gives Symbol(u'f'), with Python 3.2 it gives Symbol('f'):

>>> f.name
Symbol(...'f')

A Function has an Attribute "parms" in its grammar, which directs to class
Parameters.

>>> f.parms
Parameters([(Symbol(...'a'), <__main__.Parameter object at 0x...>), (Symbol(...'b'), <__main__.Parameter object at 0x...>), ])

Because Parameters is a Namespace, we can access its content by name.

>>> f.parms["a"]
<__main__.Parameter object at 0x...>

Its content are Parameter instances. Parameter has an Attribute "typing".

>>> f.parms["b"].typing
Type(...'long')

The Instructions of our small sample are just words. Because Function is a
List, we can access them one by one.

>>> f
Function([...'do_this', ...'do_that'], name=Symbol(...'f'))
>>> print("f is " + repr(f[0]))
f is ...'do_this'

The result can be composed to a text again.

>>> f.append(Instruction("do_something_else"))
>>> print(compose(f))
int f(int a, long b)
{
    /* on level 1 */
    do_this;
    /* on level 1 */
    do_that;
    /* on level 1 */
    do_something_else;
}
...

pyPEG contains an XML backend, too:

>>> del f[2]
>>> from pypeg2.xmlast import thing2xml
>>> xml = thing2xml(f, pretty=True)
>>> print(xml.decode())
<Function typing="int" name="f">
  <Parameters>
    <Parameter typing="int" name="a"/>
    <Parameter typing="long" name="b"/>
  </Parameters>
  <Instruction>do_this</Instruction>
  <Instruction>do_that</Instruction>
</Function>
...

The XML backend can read XML text and create things:

>>> from pypeg2.xmlast import xml2thing
>>> xml = b'<Function typing="long" name="g"><Parameters><Parameter name="x" typing="int"/></Parameters><Instruction>return</Instruction></Function>'
>>> g = xml2thing(xml, globals())
>>> g.name
Symbol(...'g')
>>> g.typing
Type(...'long')
>>> g.parms["x"].typing
Type(...'int')
>>> print("g[0] is " + repr(g[0]))
g[0] is ...'return'
"""

from __future__ import unicode_literals, print_function
from pypeg2 import *

# A Symbol can be an arbitrary word or one word of an Enum.
# In this easy example there is an Enum.

class Type(Keyword):
    grammar = Enum( K("int"), K("long") )

# Parsing attributes adds them to the resulting thing.
# blank is a callback function. Callback functions are being executed by
# compose(). parse() ignores callback functions. blank inserts " ".
# name() generates a name attribute.

class Parameter(object):
    grammar = attr("typing", Type), blank, name()

# A Namespace is a container for named things.
# csl() creates the grammar for a comma separated list.

class Parameters(Namespace):
    grammar = optional(csl(Parameter))

# This is an example for a user defined callback function, heading().
# endl is a special callback function. It is never executed. Instead it
# triggers the indention system of compose() and will be replaced by "\n".

class Instruction(str):
    def heading(self, parser):
        return "/* on level " + str(parser.indention_level) + " */", endl

    grammar = heading, word, ";", endl

# indent() is a function which marks things for being indented by compose().
# indent() raises the indention level by 1 for each thing which is inside.

block = "{", endl, maybe_some(indent(Instruction)), "}", endl

# If a thing is a List, then parsed things are being put into.

class Function(List):
    grammar = attr("typing", Type), blank, name(), "(", attr("parms", Parameters), ")", endl, block

if __name__ == '__main__':
    import doctest
    doctest.testmod(optionflags=(doctest.ELLIPSIS | doctest.REPORT_ONLY_FIRST_FAILURE))