Commits

Benjamin Dauvergne  committed 7629708 Draft

improve interleave operator
- adapt code from OMeta/JS
- add special treatment so that special behaviour with kleen-start and ?
is kept when also using binding.
---
pymeta/boot.py | 278 ++++++++++++++++++++++++++++++++++++++++++++++------
pymeta/builder.py | 9 ++-
pymeta/grammar.py | 21 ++++-
pymeta/runtime.py | 57 +++++++----
4 files changed, 308 insertions(+), 57 deletions(-)

  • Participants
  • Parent commits 1fb783b

Comments (0)

Files changed (4)

File pymeta/boot.py

     def rule_expr4(self):
         _locals = {'self': self}
         self.locals['expr4'] = _locals
-        def _G_or_1():
-            _G_apply_1, lastError = self._apply(self.rule_expr3, "expr3", [])
+        _G_apply_1, lastError = self._apply(self.rule_anything, "anything", [])
+        self.considerError(lastError)
+        _locals['ne'] = _G_apply_1
+        def _G_or_2():
+            def _G_pred_1():
+                _G_python_1, lastError = eval('ne', self.globals, _locals), None
+                self.considerError(lastError)
+                return (_G_python_1, self.currentError)
+            _G_pred_2, lastError = self.pred(_G_pred_1)
+            self.considerError(lastError)
+            def _G_many1_3():
+                _G_apply_1, lastError = self._apply(self.rule_expr3, "expr3", [])
+                self.considerError(lastError)
+                return (_G_apply_1, self.currentError)
+            _G_many1_4, lastError = self.many(_G_many1_3, _G_many1_3())
+            self.considerError(lastError)
+            _locals['es'] = _G_many1_4
+            _G_python_5, lastError = eval('self.builder.sequence(es)', self.globals, _locals), None
+            self.considerError(lastError)
+            return (_G_python_5, self.currentError)
+        def _G_or_3():
+            def _G_pred_1():
+                _G_python_1, lastError = eval('not ne', self.globals, _locals), None
+                self.considerError(lastError)
+                return (_G_python_1, self.currentError)
+            _G_pred_2, lastError = self.pred(_G_pred_1)
+            self.considerError(lastError)
+            def _G_many_3():
+                _G_apply_1, lastError = self._apply(self.rule_expr3, "expr3", [])
+                self.considerError(lastError)
+                return (_G_apply_1, self.currentError)
+            _G_many_4, lastError = self.many(_G_many_3)
+            self.considerError(lastError)
+            _locals['es'] = _G_many_4
+            _G_python_5, lastError = eval('self.builder.sequence(es)', self.globals, _locals), None
+            self.considerError(lastError)
+            return (_G_python_5, self.currentError)
+        _G_or_4, lastError = self._or([_G_or_2, _G_or_3])
+        self.considerError(lastError)
+        return (_G_or_4, self.currentError)
+
+
+    def rule_expr5(self):
+        _locals = {'self': self}
+        self.locals['expr5'] = _locals
+        _G_apply_1, lastError = self._apply(self.rule_anything, "anything", [])
+        self.considerError(lastError)
+        _locals['ne'] = _G_apply_1
+        def _G_or_2():
+            _G_apply_1, lastError = self._apply(self.rule_interleavePart, "interleavePart", [])
             self.considerError(lastError)
             _locals['e'] = _G_apply_1
             def _G_many1_2():
                 self.considerError(lastError)
                 _G_apply_2, lastError = self._apply(self.rule_token, "token", [_G_python_1])
                 self.considerError(lastError)
-                _G_apply_3, lastError = self._apply(self.rule_expr3, "expr3", [])
+                _G_apply_3, lastError = self._apply(self.rule_interleavePart, "interleavePart", [])
                 self.considerError(lastError)
                 return (_G_apply_3, self.currentError)
             _G_many1_3, lastError = self.many(_G_many1_2, _G_many1_2())
             _G_python_5, lastError = eval('self.builder.interleave(es)', self.globals, _locals), None
             self.considerError(lastError)
             return (_G_python_5, self.currentError)
+        def _G_or_3():
+            _G_python_1, lastError = eval('ne', self.globals, _locals), None
+            self.considerError(lastError)
+            _G_apply_2, lastError = self._apply(self.rule_expr4, "expr4", [_G_python_1])
+            self.considerError(lastError)
+            return (_G_apply_2, self.currentError)
+        _G_or_4, lastError = self._or([_G_or_2, _G_or_3])
+        self.considerError(lastError)
+        return (_G_or_4, self.currentError)
+
+
+    def rule_interleavePart(self):
+        _locals = {'self': self}
+        self.locals['interleavePart'] = _locals
+        def _G_or_1():
+            _G_python_1, lastError = eval('"("', self.globals, _locals), None
+            self.considerError(lastError)
+            _G_apply_2, lastError = self._apply(self.rule_token, "token", [_G_python_1])
+            self.considerError(lastError)
+            _G_python_3, lastError = eval('True', self.globals, _locals), None
+            self.considerError(lastError)
+            _G_apply_4, lastError = self._apply(self.rule_expr4, "expr4", [_G_python_3])
+            self.considerError(lastError)
+            _locals['e'] = _G_apply_4
+            _G_python_5, lastError = eval('")"', self.globals, _locals), None
+            self.considerError(lastError)
+            _G_apply_6, lastError = self._apply(self.rule_token, "token", [_G_python_5])
+            self.considerError(lastError)
+            _G_python_7, lastError = eval('["1", e]', self.globals, _locals), None
+            self.considerError(lastError)
+            return (_G_python_7, self.currentError)
         def _G_or_2():
-            def _G_many_1():
-                _G_apply_1, lastError = self._apply(self.rule_expr3, "expr3", [])
-                self.considerError(lastError)
-                return (_G_apply_1, self.currentError)
-            _G_many_2, lastError = self.many(_G_many_1)
+            _G_python_1, lastError = eval('True', self.globals, _locals), None
             self.considerError(lastError)
-            _locals['es'] = _G_many_2
-            _G_python_3, lastError = eval('self.builder.sequence(es)', self.globals, _locals), None
+            _G_apply_2, lastError = self._apply(self.rule_expr4, "expr4", [_G_python_1])
             self.considerError(lastError)
-            return (_G_python_3, self.currentError)
+            _locals['part'] = _G_apply_2
+            _G_python_3, lastError = eval('part', self.globals, _locals), None
+            self.considerError(lastError)
+            _G_apply_4, lastError = self._apply(self.rule_modedIPart, "modedIPart", [_G_python_3])
+            self.considerError(lastError)
+            _locals['x'] = _G_apply_4
+            _G_python_5, lastError = eval('x', self.globals, _locals), None
+            self.considerError(lastError)
+            return (_G_python_5, self.currentError)
         _G_or_3, lastError = self._or([_G_or_1, _G_or_2])
         self.considerError(lastError)
         return (_G_or_3, self.currentError)
 
 
+    def rule_modedIPart(self):
+        _locals = {'self': self}
+        self.locals['modedIPart'] = _locals
+        def _G_or_1():
+            def _G_listpattern_1():
+                _G_exactly_1, lastError = self.exactly('And')
+                self.considerError(lastError)
+                def _G_listpattern_2():
+                    def _G_listpattern_1():
+                        _G_exactly_1, lastError = self.exactly('Many')
+                        self.considerError(lastError)
+                        _G_apply_2, lastError = self._apply(self.rule_anything, "anything", [])
+                        self.considerError(lastError)
+                        _locals['part'] = _G_apply_2
+                        return (_locals['part'], self.currentError)
+                    _G_listpattern_2, lastError = self.listpattern(_G_listpattern_1)
+                    self.considerError(lastError)
+                    return (_G_listpattern_2, self.currentError)
+                _G_listpattern_3, lastError = self.listpattern(_G_listpattern_2)
+                self.considerError(lastError)
+                return (_G_listpattern_3, self.currentError)
+            _G_listpattern_2, lastError = self.listpattern(_G_listpattern_1)
+            self.considerError(lastError)
+            _G_python_3, lastError = eval('["*", part, None]', self.globals, _locals), None
+            self.considerError(lastError)
+            return (_G_python_3, self.currentError)
+        def _G_or_2():
+            def _G_listpattern_1():
+                _G_exactly_1, lastError = self.exactly('And')
+                self.considerError(lastError)
+                def _G_listpattern_2():
+                    def _G_listpattern_1():
+                        _G_exactly_1, lastError = self.exactly('Many1')
+                        self.considerError(lastError)
+                        _G_apply_2, lastError = self._apply(self.rule_anything, "anything", [])
+                        self.considerError(lastError)
+                        _locals['part'] = _G_apply_2
+                        return (_locals['part'], self.currentError)
+                    _G_listpattern_2, lastError = self.listpattern(_G_listpattern_1)
+                    self.considerError(lastError)
+                    return (_G_listpattern_2, self.currentError)
+                _G_listpattern_3, lastError = self.listpattern(_G_listpattern_2)
+                self.considerError(lastError)
+                return (_G_listpattern_3, self.currentError)
+            _G_listpattern_2, lastError = self.listpattern(_G_listpattern_1)
+            self.considerError(lastError)
+            _G_python_3, lastError = eval('["+", part, None]', self.globals, _locals), None
+            self.considerError(lastError)
+            return (_G_python_3, self.currentError)
+        def _G_or_3():
+            def _G_listpattern_1():
+                _G_exactly_1, lastError = self.exactly('And')
+                self.considerError(lastError)
+                def _G_listpattern_2():
+                    def _G_listpattern_1():
+                        _G_exactly_1, lastError = self.exactly('Optional')
+                        self.considerError(lastError)
+                        _G_apply_2, lastError = self._apply(self.rule_anything, "anything", [])
+                        self.considerError(lastError)
+                        _locals['part'] = _G_apply_2
+                        return (_locals['part'], self.currentError)
+                    _G_listpattern_2, lastError = self.listpattern(_G_listpattern_1)
+                    self.considerError(lastError)
+                    return (_G_listpattern_2, self.currentError)
+                _G_listpattern_3, lastError = self.listpattern(_G_listpattern_2)
+                self.considerError(lastError)
+                return (_G_listpattern_3, self.currentError)
+            _G_listpattern_2, lastError = self.listpattern(_G_listpattern_1)
+            self.considerError(lastError)
+            _G_python_3, lastError = eval('["?", part, None]', self.globals, _locals), None
+            self.considerError(lastError)
+            return (_G_python_3, self.currentError)
+        def _G_or_4():
+            def _G_listpattern_1():
+                _G_exactly_1, lastError = self.exactly('And')
+                self.considerError(lastError)
+                def _G_listpattern_2():
+                    def _G_listpattern_1():
+                        _G_exactly_1, lastError = self.exactly('Bind')
+                        self.considerError(lastError)
+                        _G_apply_2, lastError = self._apply(self.rule_anything, "anything", [])
+                        self.considerError(lastError)
+                        _locals['name'] = _G_apply_2
+                        _G_apply_3, lastError = self._apply(self.rule_anything, "anything", [])
+                        self.considerError(lastError)
+                        _locals['part1'] = _G_apply_3
+                        return (_locals['part1'], self.currentError)
+                    _G_listpattern_2, lastError = self.listpattern(_G_listpattern_1)
+                    self.considerError(lastError)
+                    return (_G_listpattern_2, self.currentError)
+                _G_listpattern_3, lastError = self.listpattern(_G_listpattern_2)
+                self.considerError(lastError)
+                return (_G_listpattern_3, self.currentError)
+            _G_listpattern_2, lastError = self.listpattern(_G_listpattern_1)
+            self.considerError(lastError)
+            _locals['e'] = _G_listpattern_2
+            _G_python_3, lastError = eval('part1', self.globals, _locals), None
+            self.considerError(lastError)
+            _G_apply_4, lastError = self._apply(self.rule_modedIPart, "modedIPart", [_G_python_3])
+            self.considerError(lastError)
+            _locals['part2'] = _G_apply_4
+            _G_python_5, lastError = eval('part2[:2] + [name]', self.globals, _locals), None
+            self.considerError(lastError)
+            return (_G_python_5, self.currentError)
+        def _G_or_5():
+            _G_apply_1, lastError = self._apply(self.rule_anything, "anything", [])
+            self.considerError(lastError)
+            _locals['part'] = _G_apply_1
+            _G_python_2, lastError = eval('["1", part, None]', self.globals, _locals), None
+            self.considerError(lastError)
+            return (_G_python_2, self.currentError)
+        _G_or_6, lastError = self._or([_G_or_1, _G_or_2, _G_or_3, _G_or_4, _G_or_5])
+        self.considerError(lastError)
+        return (_G_or_6, self.currentError)
+
+
     def rule_expr(self):
         _locals = {'self': self}
         self.locals['expr'] = _locals
-        _G_apply_1, lastError = self._apply(self.rule_expr4, "expr4", [])
+        def _G_or_1():
+            _G_python_1, lastError = eval('True', self.globals, _locals), None
+            self.considerError(lastError)
+            _G_apply_2, lastError = self._apply(self.rule_expr5, "expr5", [_G_python_1])
+            self.considerError(lastError)
+            _locals['e'] = _G_apply_2
+            def _G_many1_3():
+                _G_python_1, lastError = eval("'|'", self.globals, _locals), None
+                self.considerError(lastError)
+                _G_apply_2, lastError = self._apply(self.rule_token, "token", [_G_python_1])
+                self.considerError(lastError)
+                _G_python_3, lastError = eval('True', self.globals, _locals), None
+                self.considerError(lastError)
+                _G_apply_4, lastError = self._apply(self.rule_expr5, "expr5", [_G_python_3])
+                self.considerError(lastError)
+                return (_G_apply_4, self.currentError)
+            _G_many1_4, lastError = self.many(_G_many1_3, _G_many1_3())
+            self.considerError(lastError)
+            _locals['es'] = _G_many1_4
+            _G_python_5, lastError = eval('es.insert(0, e)', self.globals, _locals), None
+            self.considerError(lastError)
+            _G_python_6, lastError = eval('self.builder._or(es)', self.globals, _locals), None
+            self.considerError(lastError)
+            return (_G_python_6, self.currentError)
+        def _G_or_2():
+            _G_python_1, lastError = eval('False', self.globals, _locals), None
+            self.considerError(lastError)
+            _G_apply_2, lastError = self._apply(self.rule_expr5, "expr5", [_G_python_1])
+            self.considerError(lastError)
+            return (_G_apply_2, self.currentError)
+        _G_or_3, lastError = self._or([_G_or_1, _G_or_2])
         self.considerError(lastError)
-        _locals['e'] = _G_apply_1
-        def _G_many_2():
-            _G_python_1, lastError = eval("'|'", self.globals, _locals), None
-            self.considerError(lastError)
-            _G_apply_2, lastError = self._apply(self.rule_token, "token", [_G_python_1])
-            self.considerError(lastError)
-            _G_apply_3, lastError = self._apply(self.rule_expr4, "expr4", [])
-            self.considerError(lastError)
-            return (_G_apply_3, self.currentError)
-        _G_many_3, lastError = self.many(_G_many_2)
-        self.considerError(lastError)
-        _locals['es'] = _G_many_3
-        _G_python_4, lastError = eval('es.insert(0, e)', self.globals, _locals), None
-        self.considerError(lastError)
-        _G_python_5, lastError = eval('self.builder._or(es)', self.globals, _locals), None
-        self.considerError(lastError)
-        return (_G_python_5, self.currentError)
+        return (_G_or_3, self.currentError)
 
 
     def rule_ruleValue(self):
         self.considerError(lastError)
         _G_python_6, lastError = eval('setattr(self, "name", n)', self.globals, _locals), None
         self.considerError(lastError)
-        _G_apply_7, lastError = self._apply(self.rule_expr4, "expr4", [])
+        _G_python_7, lastError = eval('False', self.globals, _locals), None
         self.considerError(lastError)
-        _locals['args'] = _G_apply_7
-        def _G_or_8():
+        _G_apply_8, lastError = self._apply(self.rule_expr5, "expr5", [_G_python_7])
+        self.considerError(lastError)
+        _locals['args'] = _G_apply_8
+        def _G_or_9():
             _G_python_1, lastError = eval('"="', self.globals, _locals), None
             self.considerError(lastError)
             _G_apply_2, lastError = self._apply(self.rule_token, "token", [_G_python_1])
             _G_python_4, lastError = eval('self.builder.sequence([args, e])', self.globals, _locals), None
             self.considerError(lastError)
             return (_G_python_4, self.currentError)
-        def _G_or_9():
+        def _G_or_10():
             _G_python_1, lastError = eval('args', self.globals, _locals), None
             self.considerError(lastError)
             return (_G_python_1, self.currentError)
-        _G_or_10, lastError = self._or([_G_or_8, _G_or_9])
+        _G_or_11, lastError = self._or([_G_or_9, _G_or_10])
         self.considerError(lastError)
-        return (_G_or_10, self.currentError)
+        return (_G_or_11, self.currentError)
 
 
     def rule_rule(self):

File pymeta/builder.py

         self._interleave([lambda: expr1, lambda: expr2, ... , lambda: exprN]).
         """
         if len(exprs) > 1:
-            fnames = [self._newThunkFor("interleave", expr) for expr in exprs]
-            return self._expr('interleave', 'self._interleave([%s])' % (', '.join(fnames)))
+            args = []
+            print 'exprs', exprs
+            for x, expr, name in exprs:
+                args.append(repr(x))
+                args.append(self._newThunkFor("interleave", expr))
+                args.append(repr(name))
+            return self._expr('interleave', 'self._interleave(_locals, %s)' % (', '.join(args)))
         else:
             return self._generateNode(exprs[0])
 

File pymeta/grammar.py

           |token(':') name:n
            -> self.builder.bind(self.builder.apply("anything", self.name), n)
 
-expr4 = expr3:e (token("&&") expr3)+:es !(es.insert(0, e))
+expr4 :ne = ?(ne) expr3+:es -> self.builder.sequence(es)
+          | ?(not ne) expr3*:es -> self.builder.sequence(es)
+
+expr5 :ne = interleavePart:e (token("&&") interleavePart)+:es !(es.insert(0, e))
           -> self.builder.interleave(es)
-     | expr3*:es -> self.builder.sequence(es)
+        | expr4(ne)
 
-expr = expr4:e (token('|') expr4)*:es !(es.insert(0, e))
+interleavePart = token("(") expr4(True):e token(")") -> ["1", e]
+ | expr4(True):part modedIPart(part):x -> x
+
+modedIPart = ['And' [['Many' :part]]]     -> ["*", part, None]
+           | ['And' [['Many1' :part]]]    -> ["+", part, None]
+           | ['And' [['Optional' :part]]] -> ["?", part, None]
+           | ['And' [['Bind' :name :part1]]]:e modedIPart(part1):part2 -> part2[:2] + [name]
+           | :part                      -> ["1", part, None]
+
+expr = expr5(True):e (token('|') expr5(True))+:es !(es.insert(0, e))
           -> self.builder._or(es)
+      | expr5(False)
 
 ruleValue = token("->") -> self.ruleValueExpr()
 
 
 rulePart :requiredName = noindentation name:n ?(n == requiredName)
                             !(setattr(self, "name", n))
-                            expr4:args
+                            expr5(False):args
                             (token("=") expr:e
                                -> self.builder.sequence([args, e])
                             |  -> args)

File pymeta/runtime.py

             e[1] = expected('range between %r and %r' % (c1, c2))
             raise _MaybeParseError(*e)
 
-    def _interleave(self, fns):
+    def _interleave(self, _locals, *args):
         """
         Call each of a list of functions in sequence until all succeed at least
         ontime, rewinding the input between each.
 
         @param fns: A list of no-argument callables.
         """
-        result = []
-        errors1 = []
-        errors2 = []
+        args = list(args)
+        currInput = self.input
+        errors = []
+        ans = [None]*(len(args)/3)
+        for idx in range(0, len(args), 3):
+            mod, fun, name = args[idx:idx+3]
+            ans[idx/3] = [] if mod in ('*', '+') else None
         while True:
-            for f in fns:
-                try:
-                    m = self.input
-                    ret, err = f()
-                    fns.remove(f)
-                    result.append(ret)
-                    errors1.append(err)
-                    break
-                except _MaybeParseError, e:
-                    self.input = m
-                    errors2.append(e)
-                    continue
+            idx = 0
+            all_done = True
+            for idx in range(0, len(args), 3):
+                mod, fun, name = args[idx:idx+3]
+                if args[idx] != '0':
+                    try:
+                        self.input = currInput
+                        v, e = fun()
+                        if args[idx] == '*':
+                            ans[idx/3].append(v)
+                        elif args[idx] == '+':
+                            ans[idx/3].append(v)
+                            args[idx] = '*'
+                        elif args[idx] in ('?','1'):
+                            ans[idx/3] = v
+                            args[idx] = '0'
+                        else:
+                            raise ValueError('invalid mode in OMeta._interleave')
+                        errors.append(e)
+                        currInput = self.input
+                        break
+                    except _MaybeParseError, e:
+                        all_done = all_done and args[idx] in ('*', '?')
             else:
-                if fns:
-                    raise _MaybeParseError(*joinErrors(errors2))
+                if all_done:
+                    for idx in range(0, len(args), 3):
+                        mod, fun, name = args[idx:idx+3]
+                        if name:
+                            _locals[name] = ans[idx/3]
+                    return ans, joinErrors(errors)
                 else:
-                    return result, joinErrors(errors1)
+                    raise _MaybeParseError(*joinErrors(errors))
 
     def pythonExpr(self, endChars="\r\n"):
         """