Skip to content

Commit a3b9268

Browse files
committed
I added the tuple unpacking ability.
Example: rule = (-> (1, 2, 3)):(a, b, c) In order to remove the redudant outer parentheses, I modified the compilePythonExpr inside builder.py. Now it could support: rule = (-> 1, 2, 3):(a, b, c) Also some part related to incremental parsing are modified.
1 parent 3ebc468 commit a3b9268

File tree

10 files changed

+529
-213
lines changed

10 files changed

+529
-213
lines changed

ometa/_generated/parsley.py

Lines changed: 214 additions & 180 deletions
Large diffs are not rendered by default.

ometa/_generated/parsley_tree_transformer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ def _G_pred_182():
532532
self.considerError(lastError, 'termRulePart')
533533
def _G_optional_185():
534534
self._trace(' token("=")', (1425, 1436), self.input.position)
535-
_G_python_186, lastError = "=", None
535+
_G_python_186, lastError = ("="), None
536536
self.considerError(lastError, None)
537537
_G_apply_187, lastError = self._apply(self.rule_token, "token", [_G_python_186])
538538
self.considerError(lastError, None)

ometa/_generated/pymeta_v1.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -247,56 +247,56 @@ def _G_or_81():
247247
self._trace("'n'", (486, 489), self.input.position)
248248
_G_exactly_82, lastError = self.exactly('n')
249249
self.considerError(lastError, None)
250-
_G_python_83, lastError = "\n", None
250+
_G_python_83, lastError = ("\n"), None
251251
self.considerError(lastError, None)
252252
return (_G_python_83, self.currentError)
253253
def _G_or_84():
254254
self._trace("'r'", (520, 523), self.input.position)
255255
_G_exactly_85, lastError = self.exactly('r')
256256
self.considerError(lastError, None)
257-
_G_python_86, lastError = "\r", None
257+
_G_python_86, lastError = ("\r"), None
258258
self.considerError(lastError, None)
259259
return (_G_python_86, self.currentError)
260260
def _G_or_87():
261261
self._trace("'t'", (554, 557), self.input.position)
262262
_G_exactly_88, lastError = self.exactly('t')
263263
self.considerError(lastError, None)
264-
_G_python_89, lastError = "\t", None
264+
_G_python_89, lastError = ("\t"), None
265265
self.considerError(lastError, None)
266266
return (_G_python_89, self.currentError)
267267
def _G_or_90():
268268
self._trace("'b'", (588, 591), self.input.position)
269269
_G_exactly_91, lastError = self.exactly('b')
270270
self.considerError(lastError, None)
271-
_G_python_92, lastError = "\b", None
271+
_G_python_92, lastError = ("\b"), None
272272
self.considerError(lastError, None)
273273
return (_G_python_92, self.currentError)
274274
def _G_or_93():
275275
self._trace("'f'", (622, 625), self.input.position)
276276
_G_exactly_94, lastError = self.exactly('f')
277277
self.considerError(lastError, None)
278-
_G_python_95, lastError = "\f", None
278+
_G_python_95, lastError = ("\f"), None
279279
self.considerError(lastError, None)
280280
return (_G_python_95, self.currentError)
281281
def _G_or_96():
282282
self._trace('\'"\'', (656, 659), self.input.position)
283283
_G_exactly_97, lastError = self.exactly('"')
284284
self.considerError(lastError, None)
285-
_G_python_98, lastError = '"', None
285+
_G_python_98, lastError = ('"'), None
286286
self.considerError(lastError, None)
287287
return (_G_python_98, self.currentError)
288288
def _G_or_99():
289289
self._trace("'\\''", (689, 693), self.input.position)
290290
_G_exactly_100, lastError = self.exactly("'")
291291
self.considerError(lastError, None)
292-
_G_python_101, lastError = "'", None
292+
_G_python_101, lastError = ("'"), None
293293
self.considerError(lastError, None)
294294
return (_G_python_101, self.currentError)
295295
def _G_or_102():
296296
self._trace("'\\\\'", (723, 727), self.input.position)
297297
_G_exactly_103, lastError = self.exactly('\\')
298298
self.considerError(lastError, None)
299-
_G_python_104, lastError = "\\", None
299+
_G_python_104, lastError = ("\\"), None
300300
self.considerError(lastError, None)
301301
return (_G_python_104, self.currentError)
302302
_G_or_105, lastError = self._or([_G_or_81, _G_or_84, _G_or_87, _G_or_90, _G_or_93, _G_or_96, _G_or_99, _G_or_102])

ometa/builder.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ def compilePythonExpr(self, out, expr, debugname=None):
107107
"""
108108
try:
109109
ast.literal_eval(expr)
110-
return self._expr(out, 'python', expr + ', None', debugname)
110+
return self._expr(out, 'python', '(' + expr + '), None', debugname)
111111
except ValueError:
112112
return self._expr(out, 'python',
113113
'eval(%r, self.globals, _locals), None' % (expr,),
@@ -250,9 +250,14 @@ def generate_Bind(self, out, name, expr, debugname=None):
250250
Bind the value of 'expr' to a name in the _locals dict.
251251
"""
252252
v = self._generateNode(out, expr, debugname)
253-
ref = "_locals['%s']" % (name.data,)
254-
out.writeln("%s = %s" %(ref, v))
255-
return ref
253+
if name.data:
254+
ref = "_locals['%s']" % (name.data,)
255+
out.writeln("%s = %s" % (ref, v))
256+
else:
257+
for i, n in enumerate(name.args):
258+
ref = "_locals['%s']" % (n.data,)
259+
out.writeln("%s = %s[%i]" %(ref, v, i))
260+
return v
256261

257262

258263
def generate_Predicate(self, out, expr, debugname=None):

ometa/interp.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,11 @@ def parse_Bind(self, name, expr):
395395
for x in self._eval(expr):
396396
if x is _feed_me: yield x
397397
v, err = x
398-
self._localsStack[-1][name.data] = v
398+
if name.data:
399+
self._localsStack[-1][name.data] = v
400+
else:
401+
for n, val in zip(name.args, v):
402+
self._localsStack[-1][n.data] = val
399403
yield v, err
400404

401405

@@ -637,7 +641,11 @@ def _eval(self, run, expr):
637641

638642
elif name == "Bind":
639643
v, err = self._eval(run, args[1])
640-
self._localsStack[-1][args[0].data] = v
644+
if args[0].data:
645+
self._localsStack[-1][args[0].data] = v
646+
else:
647+
for n, val in zip(args[0].args, v):
648+
self._localsStack[-1][n.data] = val
641649
return v, err
642650

643651
elif name == "Predicate":

ometa/parsley.parsley

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ expr3 = (expr2:e
8181
| -> e
8282
)):r
8383
(':' name:n -> t.Bind(n, r)
84+
| ':(' name:n (',' ws name)*:others ws ')'
85+
(-> [n] + others if others else n):n -> t.Bind(n, r)
8486
| -> r)
8587
|ws ':' name:n
8688
-> t.Bind(n, t.Apply("anything", self.rulename, []))

ometa/test/test_builder.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def test_apply(self):
3838
a = t.Apply("foo", "main", [one, x])
3939
self.assertEqual(writePython(a, ""),
4040
dd("""
41-
_G_python_1, lastError = 1, None
41+
_G_python_1, lastError = (1), None
4242
self.considerError(lastError, None)
4343
_G_python_2, lastError = eval('x', self.globals, _locals), None
4444
self.considerError(lastError, None)
@@ -56,7 +56,7 @@ def test_foreignApply(self):
5656
a = t.ForeignApply("thegrammar", "foo", "main", [one, x])
5757
self.assertEqual(writePython(a, ""),
5858
dd("""
59-
_G_python_1, lastError = 1, None
59+
_G_python_1, lastError = (1), None
6060
self.considerError(lastError, None)
6161
_G_python_2, lastError = eval('x', self.globals, _locals), None
6262
self.considerError(lastError, None)
@@ -75,7 +75,7 @@ def test_superApply(self):
7575
a = t.Apply("super", "main", [one, x])
7676
self.assertEqual(writePython(a, ""),
7777
dd("""
78-
_G_python_1, lastError = 1, None
78+
_G_python_1, lastError = (1), None
7979
self.considerError(lastError, None)
8080
_G_python_2, lastError = eval('x', self.globals, _locals), None
8181
self.considerError(lastError, None)
@@ -238,7 +238,7 @@ def test_bind(self):
238238
_G_exactly_1, lastError = self.exactly('x')
239239
self.considerError(lastError, None)
240240
_locals['var'] = _G_exactly_1
241-
_locals['var']
241+
_G_exactly_1
242242
"""))
243243

244244

ometa/test/test_pymeta.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -640,10 +640,17 @@ def test_lookahead(self):
640640

641641
def test_binding(self):
642642
"""
643-
The result of a parsing expression can be bound to a name.
643+
The result of a parsing expression can be bound to a single name
644+
or names surrounded by parentheses.
644645
"""
645646
g = self.compile("foo = '1':x -> int(x) * 2")
646647
self.assertEqual(g.foo("1"), 2)
648+
g = self.compile("foo = '1':(x) -> int(x) * 2")
649+
self.assertEqual(g.foo("1"), 2)
650+
g = self.compile("foo = (-> 3, 4):(x, y) -> x")
651+
self.assertEqual(g.foo(""), 3)
652+
g = self.compile("foo = (-> 1, 2):(x, y) -> int(x) * 2 + int(y)")
653+
self.assertEqual(g.foo(""), 4)
647654

648655

649656
def test_bindingAccess(self):
@@ -660,6 +667,18 @@ def test_bindingAccess(self):
660667
self.assertEqual(g.apply("stuff")[0], '3')
661668
self.assertEqual(g.locals['stuff']['a'], '1')
662669
self.assertEqual(g.locals['stuff']['c'], '3')
670+
G = self.classTested.makeGrammar(
671+
"stuff = '1':a ('2':(b) | '345':(c, d, e))", 'TestGrammar').createParserClass(OMetaBase, {})
672+
g = G("12")
673+
self.assertEqual(g.apply("stuff")[0], '2')
674+
self.assertEqual(g.locals['stuff']['a'], '1')
675+
self.assertEqual(g.locals['stuff']['b'], '2')
676+
g = G("1345")
677+
self.assertEqual(g.apply("stuff")[0], '345')
678+
self.assertEqual(g.locals['stuff']['a'], '1')
679+
self.assertEqual(g.locals['stuff']['c'], '3')
680+
self.assertEqual(g.locals['stuff']['d'], '4')
681+
self.assertEqual(g.locals['stuff']['e'], '5')
663682

664683

665684
def test_predicate(self):

0 commit comments

Comments
 (0)