diff 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
line wrap: on
line diff
--- a/python/pyburg.py	Fri Mar 14 13:02:16 2014 +0100
+++ b/python/pyburg.py	Fri Mar 14 15:14:29 2014 +0100
@@ -76,8 +76,7 @@
            ('id', r'[A-Za-z][A-Za-z\d_]*', lambda typ, val: (typ, val)),
            ('kw', r'%[A-Za-z][A-Za-z\d_]*', lambda typ, val: (val, val)),
            ('number', r'\d+', lambda typ, val: (typ, int(val))),
-           ('STRING', r"'[^']*'", lambda typ, val: ('id', val[1:-1])),
-           ('template', r"\(\..*\.\)", lambda typ, val: (typ, val)),
+           ('STRING', r"'[^']*'", lambda typ, val: ('string', val[1:-1])),
            ('OTHER', r'[:;\|\(\),]', lambda typ, val: (val, val)),
            ('SKIP', r'[ ]', None)
             ]
@@ -115,10 +114,11 @@
 class Rule:
     """ A rewrite rule. Specifies a tree that can be rewritten into a result
     at a specific cost """
-    def __init__(self, non_term, tree, cost, template):
+    def __init__(self, non_term, tree, cost, acceptance, template):
         self.non_term = non_term
         self.tree = tree
         self.cost = cost
+        self.acceptance = acceptance
         self.template = template
         self.nr = 0
 
@@ -154,11 +154,11 @@
 
     non_terminals = property(lambda s: s.symType(Nonterm))
 
-    def add_rule(self, non_term, tree, cost, template):
-        template = template[2:-2].strip()
+    def add_rule(self, non_term, tree, cost, acceptance, template):
+        template = template.strip()
         if not template:
             template = 'pass'
-        rule = Rule(non_term, tree, cost, template)
+        rule = Rule(non_term, tree, cost, acceptance, template)
         if len(tree.children) == 0 and tree.name not in self.terminals:
             self.non_term(tree.name).chain_rules.append(rule)
         self.non_term(rule.non_term)
@@ -231,28 +231,35 @@
         self.print()
         for rule in self.system.rules:
             if rule.num_nts > 0:
-                args = ', ' + ', '.join('nt{}'.format(x) for x in range(rule.num_nts))
+                args = ', '.join('c{}'.format(x) for x in range(rule.num_nts))
+                args = ', ' + args
             else:
                 args = ''
+            # Create template function:
             self.print('    def P{}(self, tree{}):'.format(rule.nr, args))
             template = rule.template
-            template = template.replace('$$', 'tree')
-            for i in range(rule.num_nts):
-                template = template.replace('${}'.format(i+1), 'nt{}'.format(i))
             for t in template.split(';'):
                 self.print('        {}'.format(t.strip()))
+            # Create acceptance function:
+            if rule.acceptance:
+                self.print('    def A{}(self, tree):'.format(rule.nr))
+                for t in rule.acceptance.split(';'):
+                    self.print('        {}'.format(t.strip()))
         self.emit_state()
         self.print('    def gen(self, tree):')
         self.print('        self.burm_label(tree)')
         self.print('        if not tree.state.has_goal("{}"):'.format(self.system.goal))
-        self.print('          raise Exception("Tree {} not covered".format(tree))')
+        self.print('            raise Exception("Tree {} not covered".format(tree))')
         self.print('        return self.apply_rules(tree, "{}")'.format(self.system.goal))
 
     def emit_record(self, rule, state_var):
         # TODO: check for rules fullfilled (by not using 999999)
+        acc = ''
+        if rule.acceptance:
+            acc = ' and self.A{}(tree)'.format(rule.nr)
         self.print('            nts = self.nts({})'.format(rule.nr))
         self.print('            kids = self.kids(tree, {})'.format(rule.nr))
-        self.print('            if all(x.state.has_goal(y) for x, y in zip(kids, nts)):')
+        self.print('            if all(x.state.has_goal(y) for x, y in zip(kids, nts)){}:'.format(acc))
         self.print('                c = sum(x.state.get_cost(y) for x, y in zip(kids, nts)) + {}'.format(rule.cost))
         self.print('                tree.state.set_cost("{}", c, {})'.format(rule.non_term, rule.nr))
         for cr in self.system.symbols[rule.non_term].chain_rules: