annotate python/pyburg.py @ 319:8d07a4254f04

Work on burg
author Windel Bouwman
date Sat, 18 Jan 2014 18:58:43 +0100
parents e84047f29c78
children 84d67cce67b7
rev   line source
318
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
1 #!/usr/bin/python
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
2
319
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
3 """
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
4 Bottom up rewrite generator.
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
5
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
6 This script takes as input a description of patterns and outputs a
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
7 matcher class that can match trees given the patterns.
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
8
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
9 Patterns are specified as follows:
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
10 reg -> ADDI32(reg, reg) 2 (. add $1 $2 .)
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
11 reg -> MULI32(reg, reg) 3 (. .)
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
12 or a multiply add:
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
13 reg -> ADDI32(MULI32(reg, reg), reg) 4 (. muladd $1, $2, $3 .)
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
14 The general specification pattern is:
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
15 [result] -> [tree] [cost] [template code]
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
16
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
17 A tree is described using parenthesis notation. For example a node X with
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
18 three
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
19 child nodes is described as:
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
20 X(a, b, b)
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
21 Trees can be nested:
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
22 X(Y(a, a), a)
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
23 The 'a' in the example above indicates an open connection to a next tree
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
24 pattern.
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
25
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
26 The generated matcher uses dynamic programming to find the best match of the
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
27 tree. This strategy consists of two steps:
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
28 - label: During this phase the given tree is traversed in a bottom up way.
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
29 each node is labelled with a possible matching rule and the corresponding cost.
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
30 - select: In this step, the tree is traversed again, selecting at each point
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
31 the cheapest way to get to the goal.
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
32
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
33 """
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
34
318
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
35 import sys
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
36 import argparse
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
37 from ppci import Token
319
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
38 import burg_parser # Automatically generated
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
39 from pyyacc import ParserException, EOF
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
40 import baselex
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
41 from tree import Tree
318
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
42
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
43
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
44 class BurgLexer:
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
45 def feed(self, txt):
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
46 tok_spec = [
319
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
47 ('id', r'[A-Za-z][A-Za-z\d_]*', lambda typ, val: (typ, val)),
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
48 ('kw', r'%[A-Za-z][A-Za-z\d_]*', lambda typ, val: (val, val)),
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
49 ('number', r'\d+', lambda typ, val: (typ, int(val))),
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
50 ('STRING', r"'[^']*'", lambda typ, val: ('id', val[1:-1])),
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
51 ('template', r"\(\..*\.\)", lambda typ, val: (typ, val)),
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
52 ('OTHER', r'[:;\|\(\),]', lambda typ, val: (val, val)),
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
53 ('SKIP', r'[ ]', None)
318
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
54 ]
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
55
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
56 lines = txt.split('\n')
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
57
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
58 def tokenize():
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
59 for line in lines:
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
60 line = line.strip()
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
61 if not line:
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
62 continue # Skip empty lines
319
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
63 elif line == '%%':
318
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
64 yield Token('%%', '%%')
319
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
65 else:
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
66 yield from baselex.tokenize(tok_spec, line)
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
67 yield Token(EOF, EOF)
318
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
68 self.tokens = tokenize()
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
69 self.token = self.tokens.__next__()
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
70
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
71 def next_token(self):
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
72 t = self.token
319
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
73 if t.typ != EOF:
318
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
74 self.token = self.tokens.__next__()
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
75 return t
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
76
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
77
319
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
78 class Rule:
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
79 def __init__(self, non_term, tree, cost, template):
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
80 self.non_term = non_term
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
81 self.tree = tree
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
82 self.cost = cost
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
83 self.template = template
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
84 self.nr = 0
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
85
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
86 def __repr__(self):
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
87 return '{} -> {} ${}'.format(self.non_term, self.tree, self.cost)
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
88
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
89
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
90 class Symbol:
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
91 def __init__(self, name):
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
92 self.name = name
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
93
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
94
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
95 class Term(Symbol):
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
96 pass
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
97
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
98
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
99 class Nonterm(Symbol):
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
100 def __init__(self, name):
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
101 super().__init__(name)
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
102 self.rules = []
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
103
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
104
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
105 class BurgSystem:
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
106 def __init__(self):
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
107 self.rules = []
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
108 self.symbols = {}
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
109 self.goal = None
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
110
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
111 def symType(self, t):
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
112 return (s.name for s in self.symbols.values() if type(s) is t)
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
113
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
114 terminals = property(lambda s: s.symType(Term))
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
115
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
116 non_terminals = property(lambda s: s.symType(Nonterm))
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
117
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
118 def add_rule(self, non_term, tree, cost, template):
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
119 rule = Rule(non_term, tree, cost, template)
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
120 self.non_term(rule.non_term)
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
121 self.rules.append(rule)
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
122 rule.nr = len(self.rules)
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
123
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
124 def non_term(self, name):
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
125 if name in self.terminals:
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
126 raise BurgError('Cannot redefine terminal')
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
127 if not self.goal:
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
128 self.goal = name
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
129 self.install(name, Nonterm)
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
130
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
131 def tree(self, name, *args):
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
132 return Tree(name, *args)
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
133
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
134 def install(self, name, t):
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
135 assert type(name) is str
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
136 if name in self.symbols:
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
137 assert type(self.symbols[name]) is t
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
138 return self.symbols[name]
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
139 else:
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
140 self.symbols[name] = t(name)
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
141
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
142 def add_terminal(self, terminal):
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
143 self.install(terminal, Term)
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
144
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
145
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
146 class BurgError(Exception):
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
147 pass
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
148
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
149
318
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
150 class BurgParser(burg_parser.Parser):
319
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
151 """ Derived from automatically generated parser """
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
152 def parse(self, l):
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
153 self.system = BurgSystem()
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
154 super().parse(l)
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
155 return self.system
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
156
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
157
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
158 class BurgGenerator:
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
159 def print(self, *args):
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
160 """ Print helper function that prints to output file """
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
161 print(*args, file=self.output_file)
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
162
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
163 def generate(self, system, output_file):
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
164 """ Generate script that implements the burg spec """
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
165 self.output_file = output_file
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
166 self.system = system
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
167
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
168 self.print('#!/usr/bin/python')
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
169 self.print('from tree import Tree, BaseMatcher, State')
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
170 self.print()
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
171 self.print('class Matcher(BaseMatcher):')
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
172 self.print(' def __init__(self):')
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
173 self.print(' self.kid_functions = {}')
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
174 self.print(' self.nts_map = {}')
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
175 for rule in self.system.rules:
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
176 kids, dummy = self.compute_kids(rule.tree, 't')
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
177 lf = 'lambda t: [{}]'.format(', '.join(kids), rule)
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
178 self.print(' # {}'.format(rule))
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
179 self.print(' self.kid_functions[{}] = {}'.format(rule.nr, lf))
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
180 self.print(' self.nts_map[{}] = {}'.format(rule.nr, dummy))
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
181 self.print('')
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
182 self.emit_state()
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
183 self.print()
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
184 self.print(' def gen(self, tree):')
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
185 self.print(' self.burm_label(tree)')
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
186 self.print(' if not tree.state.has_goal("{}"):'.format(self.system.goal))
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
187 self.print(' raise Exception("Tree not covered")')
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
188 self.print(' self.apply_rules(tree, "{}")'.format(self.system.goal))
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
189
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
190 def emit_record(self, rule, state_var):
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
191 # TODO: check for rules fullfilled (by not using 999999)
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
192 self.print(' nts = self.nts({})'.format(rule.nr))
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
193 self.print(' kids = self.kids(tree, {})'.format(rule.nr))
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
194 self.print(' c = sum(x.state.get_cost(y) for x, y in zip(kids, nts)) + {}'.format(rule.cost))
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
195 self.print(' tree.state.set_cost("{}", c, {})'.format(rule.non_term, rule.nr))
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
196
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
197 def emit_state(self):
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
198 """ Emit a function that assigns a new state to a node """
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
199 self.print(' def burm_state(self, tree):')
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
200 self.print(' tree.state = State()')
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
201 for term in self.system.terminals:
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
202 self.emitcase(term)
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
203 self.print()
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
204
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
205 def emitcase(self, term):
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
206 rules = [rule for rule in self.system.rules if rule.tree.name == term]
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
207 for rule in rules:
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
208 condition = self.emittest(rule.tree, 'tree')
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
209 self.print(' if {}:'.format(condition))
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
210 self.emit_record(rule, 'state')
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
211
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
212 def emit_closure(self):
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
213 for non_terminal in self.system.non_terminals:
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
214 self.print('def closure_{}(self, c):'.format(non_terminal))
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
215 self.print(' pass')
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
216 self.print()
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
217
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
218 def compute_kids(self, t, root_name):
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
219 """ Compute of a pattern the blanks that must be provided from below in the tree """
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
220 if t.name in self.system.non_terminals:
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
221 return [root_name], [t.name]
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
222 else:
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
223 k = []
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
224 nts = []
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
225 for i, c in enumerate(t.children):
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
226 pfx = root_name + '.children[{}]'.format(i)
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
227 kf, dummy = self.compute_kids(c, pfx)
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
228 nts.extend(dummy)
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
229 k.extend(kf)
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
230 return k, nts
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
231
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
232
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
233 def emittest(self, tree, prefix):
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
234 """ Generate condition for a tree pattern """
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
235 ct = (c for c in tree.children if c.name not in self.system.non_terminals)
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
236 child_tests = (self.emittest(c, prefix + '.children[{}]'.format(i)) for i, c in enumerate(ct))
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
237 child_tests = ('({})'.format(ct) for ct in child_tests)
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
238 child_tests = ' and '.join(child_tests)
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
239 child_tests = ' and ' + child_tests if child_tests else ''
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
240 tst = '{}.name == "{}"'.format(prefix, tree.name)
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
241 return tst + child_tests
318
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
242
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
243
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
244 def main():
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
245 # Parse arguments:
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
246 parser = argparse.ArgumentParser(description='pyburg bottom up rewrite system generator compiler compiler')
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
247 parser.add_argument('source', type=argparse.FileType('r'), \
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
248 help='the parser specification')
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
249 parser.add_argument('-o', '--output', type=argparse.FileType('w'), \
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
250 default=sys.stdout)
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
251 args = parser.parse_args()
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
252 src = args.source.read()
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
253 args.source.close()
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
254
319
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
255 # Parse specification into burgsystem:
318
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
256 l = BurgLexer()
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
257 p = BurgParser()
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
258 l.feed(src)
319
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
259 burg_system = p.parse(l)
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
260
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
261 # Generate matcher:
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
262 generator = BurgGenerator()
8d07a4254f04 Work on burg
Windel Bouwman
parents: 318
diff changeset
263 generator.generate(burg_system, args.output)
318
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
264
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
265 if __name__ == '__main__':
e84047f29c78 Add burg and yacc initial attempts
Windel Bouwman
parents:
diff changeset
266 main()