Skip to content

Commit

Permalink
Merge pull request #37 from introom/rule_argument
Browse files Browse the repository at this point in the history
invoking rule with argument
  • Loading branch information
habnabit committed Aug 27, 2013
2 parents 30e706e + 5d13432 commit e58c0c6
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 7 deletions.
23 changes: 17 additions & 6 deletions ometa/interp.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -68,6 +68,12 @@ def end(self):
self.callback(*x)


def setNext(self, rule):
if not isinstance(rule, tuple):
rule = (rule, )
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
Expand Down Expand Up @@ -148,10 +154,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:
Expand Down
14 changes: 14 additions & 0 deletions ometa/test/test_tube.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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"])
2 changes: 1 addition & 1 deletion ometa/tube.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)


Expand Down

0 comments on commit e58c0c6

Please sign in to comment.