From 66d8d0361126ffeaf291db8dd84e7f28805800e9 Mon Sep 17 00:00:00 2001 From: introom Date: Wed, 7 Aug 2013 11:15:35 +0800 Subject: [PATCH 1/4] invoking rule with argument --- ometa/interp.py | 25 +++++++++++++++++++------ ometa/runtime.py | 1 - ometa/tube.py | 2 +- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/ometa/interp.py b/ometa/interp.py index 0db97a7..e4d162b 100644 --- a/ometa/interp.py +++ b/ometa/interp.py @@ -20,13 +20,13 @@ class TrampolinedGrammarInterpreter(object): An interpreter for OMeta grammars that processes input incrementally. """ - def __init__(self, grammar, ruleName, callback=None, globals=None): + def __init__(self, grammar, rule, callback=None, globals=None): self.grammar = grammar self.position = 0 self.callback = callback self.globals = globals or {} self.rules = decomposeGrammar(grammar) - self.next = self.apply(ruleName, None, ()) + self.next = self.setNext(rule) self._localsStack = [] self.currentResult = None self.input = InputStream([], 0) @@ -68,6 +68,14 @@ def end(self): self.callback(*x) + def setNext(self, rule): + if isinstance(rule, basestring): + rule = (rule, ) + if not isinstance(rule, (list, tuple)): + raise TypeError("rule should be a string, list or a tuple.") + return self.apply(rule[0], None, rule[1:]) + + ## Implementation note: each method, instead of being a function ## returning a value, is a generator that will yield '_feed_me' an ## arbitrary number of times, then finally yield the value of the @@ -148,10 +156,15 @@ def apply(self, ruleName, codeName, args): Invoke a rule, optionally with arguments. """ argvals = [] - for a in args: - for x in self._eval(a): - if x is _feed_me: yield x - argvals.append(x[0]) + # we tell whether a rule is a manually set one by the codeName + # if it's None, then we think it's set by setNext + if codeName is None: + argvals = args + else: + for a in args: + for x in self._eval(a): + if x is _feed_me: yield x + argvals.append(x[0]) _locals = {} self._localsStack.append(_locals) try: diff --git a/ometa/runtime.py b/ometa/runtime.py index 3b13f38..a27170d 100644 --- a/ometa/runtime.py +++ b/ometa/runtime.py @@ -131,7 +131,6 @@ def joinErrors(errors): """ if len(errors) == 1: return errors[0] - highestPos = -1 results = set() trail = None diff --git a/ometa/tube.py b/ometa/tube.py index bfffe3f..54eb03b 100644 --- a/ometa/tube.py +++ b/ometa/tube.py @@ -26,7 +26,7 @@ def _setupInterp(self): 'initial'. """ self._interp = TrampolinedGrammarInterpreter( - grammar=self.grammar, ruleName=self.receiver.currentRule, + grammar=self.grammar, rule=self.receiver.currentRule, callback=None, globals=self.bindings) From d2ffc54ae7dc452188fe1416de2c7114ea9c05f1 Mon Sep 17 00:00:00 2001 From: introom Date: Thu, 8 Aug 2013 15:34:19 +0800 Subject: [PATCH 2/4] modified per hab's comment --- ometa/interp.py | 3 +-- ometa/test/test_tube.py | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/ometa/interp.py b/ometa/interp.py index e4d162b..0990bc5 100644 --- a/ometa/interp.py +++ b/ometa/interp.py @@ -71,8 +71,7 @@ def end(self): def setNext(self, rule): if isinstance(rule, basestring): rule = (rule, ) - if not isinstance(rule, (list, tuple)): - raise TypeError("rule should be a string, list or a tuple.") + rule = tuple(rule) return self.apply(rule[0], None, rule[1:]) diff --git a/ometa/test/test_tube.py b/ometa/test/test_tube.py index 8179192..82da0e8 100644 --- a/ometa/test/test_tube.py +++ b/ometa/test/test_tube.py @@ -34,6 +34,7 @@ def setUp(self): _grammar = r""" delimiter = '\r\n' initial = <(~delimiter anything)*>:val delimiter -> receiver.receive(val) + witharg :arg1 :arg2 = <(~delimiter anything)*>:a delimiter -> receiver.receive(arg1+arg2+a) """ self.grammar = self._parseGrammar(_grammar) @@ -75,3 +76,16 @@ def test_bindings(self): bindings = {'SMALL_INT': 3} TrampolinedParser(self._parseGrammar(grammar), receiver, bindings).receive('0') self.assertEqual(receiver.received, [3]) + + + def test_currentRuleWithArgs(self): + """ + TrampolinedParser should be able to invoke curruent rule with args. + """ + receiver = TrampolinedReceiver() + receiver.currentRule = "witharg", "nice ", "day" + trampolinedParser = TrampolinedParser(self.grammar, receiver, {}) + buf = b' oh yes\r\n' + for c in iterbytes(buf): + trampolinedParser.receive(c) + self.assertEqual(receiver.received, ["nice day oh yes"]) From 04326867dc5e6c9c31a16248383f69800fcf7401 Mon Sep 17 00:00:00 2001 From: introom Date: Thu, 8 Aug 2013 22:57:49 +0800 Subject: [PATCH 3/4] update setNext --- ometa/interp.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ometa/interp.py b/ometa/interp.py index 0990bc5..004c0f5 100644 --- a/ometa/interp.py +++ b/ometa/interp.py @@ -69,9 +69,8 @@ def end(self): def setNext(self, rule): - if isinstance(rule, basestring): + if not isinstance(rule, tuple): rule = (rule, ) - rule = tuple(rule) return self.apply(rule[0], None, rule[1:]) From 9e7de248c1b0807ca32da8d26caa1470634f3a08 Mon Sep 17 00:00:00 2001 From: introom Date: Thu, 8 Aug 2013 23:17:22 +0800 Subject: [PATCH 4/4] syntax modification --- ometa/runtime.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ometa/runtime.py b/ometa/runtime.py index a27170d..3b13f38 100644 --- a/ometa/runtime.py +++ b/ometa/runtime.py @@ -131,6 +131,7 @@ def joinErrors(errors): """ if len(errors) == 1: return errors[0] + highestPos = -1 results = set() trail = None