comparison python/pyburg.py @ 357:818be710e13d

Added acceptance function to burg
author Windel Bouwman
date Fri, 14 Mar 2014 15:14:29 +0100
parents 5477e499b039
children d2ddfe134c48
comparison
equal deleted inserted replaced
356:52492b304adf 357:818be710e13d
74 def feed(self, txt): 74 def feed(self, txt):
75 tok_spec = [ 75 tok_spec = [
76 ('id', r'[A-Za-z][A-Za-z\d_]*', lambda typ, val: (typ, val)), 76 ('id', r'[A-Za-z][A-Za-z\d_]*', lambda typ, val: (typ, val)),
77 ('kw', r'%[A-Za-z][A-Za-z\d_]*', lambda typ, val: (val, val)), 77 ('kw', r'%[A-Za-z][A-Za-z\d_]*', lambda typ, val: (val, val)),
78 ('number', r'\d+', lambda typ, val: (typ, int(val))), 78 ('number', r'\d+', lambda typ, val: (typ, int(val))),
79 ('STRING', r"'[^']*'", lambda typ, val: ('id', val[1:-1])), 79 ('STRING', r"'[^']*'", lambda typ, val: ('string', val[1:-1])),
80 ('template', r"\(\..*\.\)", lambda typ, val: (typ, val)),
81 ('OTHER', r'[:;\|\(\),]', lambda typ, val: (val, val)), 80 ('OTHER', r'[:;\|\(\),]', lambda typ, val: (val, val)),
82 ('SKIP', r'[ ]', None) 81 ('SKIP', r'[ ]', None)
83 ] 82 ]
84 83
85 lines = txt.split('\n') 84 lines = txt.split('\n')
113 112
114 113
115 class Rule: 114 class Rule:
116 """ A rewrite rule. Specifies a tree that can be rewritten into a result 115 """ A rewrite rule. Specifies a tree that can be rewritten into a result
117 at a specific cost """ 116 at a specific cost """
118 def __init__(self, non_term, tree, cost, template): 117 def __init__(self, non_term, tree, cost, acceptance, template):
119 self.non_term = non_term 118 self.non_term = non_term
120 self.tree = tree 119 self.tree = tree
121 self.cost = cost 120 self.cost = cost
121 self.acceptance = acceptance
122 self.template = template 122 self.template = template
123 self.nr = 0 123 self.nr = 0
124 124
125 def __repr__(self): 125 def __repr__(self):
126 return '{} -> {} ${}'.format(self.non_term, self.tree, self.cost) 126 return '{} -> {} ${}'.format(self.non_term, self.tree, self.cost)
152 152
153 terminals = property(lambda s: s.symType(Term)) 153 terminals = property(lambda s: s.symType(Term))
154 154
155 non_terminals = property(lambda s: s.symType(Nonterm)) 155 non_terminals = property(lambda s: s.symType(Nonterm))
156 156
157 def add_rule(self, non_term, tree, cost, template): 157 def add_rule(self, non_term, tree, cost, acceptance, template):
158 template = template[2:-2].strip() 158 template = template.strip()
159 if not template: 159 if not template:
160 template = 'pass' 160 template = 'pass'
161 rule = Rule(non_term, tree, cost, template) 161 rule = Rule(non_term, tree, cost, acceptance, template)
162 if len(tree.children) == 0 and tree.name not in self.terminals: 162 if len(tree.children) == 0 and tree.name not in self.terminals:
163 self.non_term(tree.name).chain_rules.append(rule) 163 self.non_term(tree.name).chain_rules.append(rule)
164 self.non_term(rule.non_term) 164 self.non_term(rule.non_term)
165 self.rules.append(rule) 165 self.rules.append(rule)
166 rule.nr = len(self.rules) 166 rule.nr = len(self.rules)
229 self.print(' self.nts_map[{}] = {}'.format(rule.nr, dummy)) 229 self.print(' self.nts_map[{}] = {}'.format(rule.nr, dummy))
230 self.print(' self.pat_f[{}] = {}'.format(rule.nr, pf)) 230 self.print(' self.pat_f[{}] = {}'.format(rule.nr, pf))
231 self.print() 231 self.print()
232 for rule in self.system.rules: 232 for rule in self.system.rules:
233 if rule.num_nts > 0: 233 if rule.num_nts > 0:
234 args = ', ' + ', '.join('nt{}'.format(x) for x in range(rule.num_nts)) 234 args = ', '.join('c{}'.format(x) for x in range(rule.num_nts))
235 args = ', ' + args
235 else: 236 else:
236 args = '' 237 args = ''
238 # Create template function:
237 self.print(' def P{}(self, tree{}):'.format(rule.nr, args)) 239 self.print(' def P{}(self, tree{}):'.format(rule.nr, args))
238 template = rule.template 240 template = rule.template
239 template = template.replace('$$', 'tree')
240 for i in range(rule.num_nts):
241 template = template.replace('${}'.format(i+1), 'nt{}'.format(i))
242 for t in template.split(';'): 241 for t in template.split(';'):
243 self.print(' {}'.format(t.strip())) 242 self.print(' {}'.format(t.strip()))
243 # Create acceptance function:
244 if rule.acceptance:
245 self.print(' def A{}(self, tree):'.format(rule.nr))
246 for t in rule.acceptance.split(';'):
247 self.print(' {}'.format(t.strip()))
244 self.emit_state() 248 self.emit_state()
245 self.print(' def gen(self, tree):') 249 self.print(' def gen(self, tree):')
246 self.print(' self.burm_label(tree)') 250 self.print(' self.burm_label(tree)')
247 self.print(' if not tree.state.has_goal("{}"):'.format(self.system.goal)) 251 self.print(' if not tree.state.has_goal("{}"):'.format(self.system.goal))
248 self.print(' raise Exception("Tree {} not covered".format(tree))') 252 self.print(' raise Exception("Tree {} not covered".format(tree))')
249 self.print(' return self.apply_rules(tree, "{}")'.format(self.system.goal)) 253 self.print(' return self.apply_rules(tree, "{}")'.format(self.system.goal))
250 254
251 def emit_record(self, rule, state_var): 255 def emit_record(self, rule, state_var):
252 # TODO: check for rules fullfilled (by not using 999999) 256 # TODO: check for rules fullfilled (by not using 999999)
257 acc = ''
258 if rule.acceptance:
259 acc = ' and self.A{}(tree)'.format(rule.nr)
253 self.print(' nts = self.nts({})'.format(rule.nr)) 260 self.print(' nts = self.nts({})'.format(rule.nr))
254 self.print(' kids = self.kids(tree, {})'.format(rule.nr)) 261 self.print(' kids = self.kids(tree, {})'.format(rule.nr))
255 self.print(' if all(x.state.has_goal(y) for x, y in zip(kids, nts)):') 262 self.print(' if all(x.state.has_goal(y) for x, y in zip(kids, nts)){}:'.format(acc))
256 self.print(' c = sum(x.state.get_cost(y) for x, y in zip(kids, nts)) + {}'.format(rule.cost)) 263 self.print(' c = sum(x.state.get_cost(y) for x, y in zip(kids, nts)) + {}'.format(rule.cost))
257 self.print(' tree.state.set_cost("{}", c, {})'.format(rule.non_term, rule.nr)) 264 self.print(' tree.state.set_cost("{}", c, {})'.format(rule.non_term, rule.nr))
258 for cr in self.system.symbols[rule.non_term].chain_rules: 265 for cr in self.system.symbols[rule.non_term].chain_rules:
259 self.print(' # Chain rule: {}'.format(cr)) 266 self.print(' # Chain rule: {}'.format(cr))
260 self.print(' tree.state.set_cost("{}", c + {}, {})'.format(cr.non_term, cr.cost, cr.nr)) 267 self.print(' tree.state.set_cost("{}", c + {}, {})'.format(cr.non_term, cr.cost, cr.nr))