Skip to content

Commit 9e3e2e7

Browse files
committed
Merge branch 'document-protocol-parsing', remote-tracking branches 'eevee/expr-cache' and 'eevee/more-faster'
3 parents c71546a + bf14483 + 13c0d57 commit 9e3e2e7

File tree

2 files changed

+55
-31
lines changed

2 files changed

+55
-31
lines changed

ometa/builder.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ def __init__(self, tree, grammarText):
3232
self.tree = tree
3333
self.grammarText = grammarText
3434
self.gensymCounter = 0
35+
self.compiledExprCache = None
3536

3637

3738
def _generate(self, out, expr, retrn=False, debugname=None):
@@ -109,9 +110,19 @@ def compilePythonExpr(self, out, expr, debugname=None):
109110
ast.literal_eval(expr)
110111
return self._expr(out, 'python', '(' + expr + '), None', debugname)
111112
except ValueError:
112-
return self._expr(out, 'python',
113-
'eval(%r, self.globals, _locals), None' % (expr,),
114-
debugname)
113+
if self.compiledExprCache is None:
114+
return self._expr(out, 'python',
115+
'eval(%r, self.globals, _locals), None' % (expr,),
116+
debugname)
117+
else:
118+
if expr in self.compiledExprCache:
119+
sym = self.compiledExprCache[expr]
120+
else:
121+
sym = self.compiledExprCache[expr] = self._gensym('expr')
122+
123+
return self._expr(out, 'python',
124+
'eval(self.%s, self.globals, _locals), None' % (sym,),
125+
debugname)
115126

116127
def _convertArgs(self, out, rawArgs, debugname):
117128
return [self._generateNode(out, x, debugname) for x in rawArgs]
@@ -325,6 +336,7 @@ def generate_Rule(self, prevOut, name, expr, debugname=None):
325336

326337
def generate_Grammar(self, out, name, takesTreeInput, rules,
327338
debugname=None):
339+
self.compiledExprCache = {}
328340
self.takesTreeInput = takesTreeInput.tag.name == 'true'
329341
out.writeln("def createParserClass(GrammarBase, ruleGlobals):")
330342
funcOut = out.indent()
@@ -338,6 +350,8 @@ def generate_Grammar(self, out, name, takesTreeInput, rules,
338350
out.writeln("")
339351
if self.takesTreeInput:
340352
out.writeln("tree = %s" % self.takesTreeInput)
353+
for expr, sym in self.compiledExprCache.items():
354+
out.writeln("%s = compile(%r, '<string>', 'eval')" % (sym, expr))
341355
funcOut.writeln(
342356
"if %s.globals is not None:" % (name.data,))
343357
out.writeln("%s.globals = %s.globals.copy()" % (name.data,
@@ -347,6 +361,7 @@ def generate_Grammar(self, out, name, takesTreeInput, rules,
347361
"else:")
348362
out.writeln("%s.globals = ruleGlobals" % (name.data,))
349363
funcOut.writeln("return " + name.data)
364+
self.compiledExprCache = None
350365

351366

352367
class _Term2PythonAction(object):

ometa/runtime.py

Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22
"""
33
Code needed to run a grammar after it has been compiled.
44
"""
5-
import string
65
import time
7-
import operator
86
from textwrap import dedent
97
from terml.nodes import coerceToTerm, Term, termMaker as t
108
from ometa.builder import moduleFromGrammar, writePython
@@ -16,17 +14,10 @@ class ParseError(Exception):
1614
?Redo from start
1715
"""
1816

19-
@property
20-
def position(self):
21-
return self.args[0]
22-
23-
24-
@property
25-
def error(self):
26-
return self.args[1]
27-
2817
def __init__(self, input, position, message, trail=None):
2918
Exception.__init__(self, position, message)
19+
self.position = position
20+
self.error = message or []
3021
self.input = input
3122
self.trail = trail or []
3223

@@ -36,8 +27,17 @@ def __eq__(self, other):
3627
return (self.position, self.error) == (other.position, other.error)
3728

3829

30+
def mergeWith(self, other):
31+
"""
32+
Merges in another error's error and trail.
33+
"""
34+
self.error = list(set(self.error + other.error))
35+
self.args = (self.position, self.error)
36+
self.trail = other.trail or self.trail or []
37+
38+
3939
def formatReason(self):
40-
if self.error is None:
40+
if not self.error:
4141
return "Syntax error"
4242
if len(self.error) == 1:
4343
if self.error[0][0] == 'message':
@@ -129,19 +129,26 @@ def joinErrors(errors):
129129
"""
130130
Return the error from the branch that matched the most of the input.
131131
"""
132-
errors.sort(reverse=True, key=operator.itemgetter(0))
132+
if len(errors) == 1:
133+
return errors[0]
134+
135+
highestPos = -1
133136
results = set()
134-
pos = errors[0].position
135137
trail = None
138+
136139
for err in errors:
137-
if pos == err.position:
138-
e, trail = err.error, (err.trail or trail)
139-
if e is not None:
140-
for item in e:
141-
results.add(item)
140+
pos = err.position
141+
if pos < highestPos:
142+
continue
143+
elif pos > highestPos:
144+
highestPos = pos
145+
trail = err.trail or None
146+
results = set(err.error)
142147
else:
143-
break
144-
return ParseError(errors[0].input, pos, list(results) or None, trail)
148+
trail = err.trail or trail
149+
results.update(err.error)
150+
151+
return ParseError(errors[0].input, highestPos, list(results), trail)
145152

146153

147154
class character(str):
@@ -389,10 +396,12 @@ def __init__(self, input, globals=None, name='<string>', tree=False,
389396

390397
def considerError(self, error, typ=None):
391398
if error:
392-
if error[0] > self.currentError[0]:
399+
newPos = error.position
400+
curPos = self.currentError.position
401+
if newPos > curPos:
393402
self.currentError = error
394-
elif error[0] == self.currentError[0]:
395-
self.currentError = joinErrors([error, self.currentError])
403+
elif newPos == curPos:
404+
self.currentError.mergeWith(error)
396405

397406

398407
def _trace(self, src, span, inputPos):
@@ -590,7 +599,7 @@ def _not(self, fn):
590599
m = self.input
591600
try:
592601
fn()
593-
except ParseError, e:
602+
except ParseError:
594603
self.input = m
595604
return True, self.input.nullError()
596605
else:
@@ -606,9 +615,9 @@ def eatWhitespace(self):
606615
c, e = self.input.head()
607616
except EOFError, e:
608617
break
609-
t = self.input.tail()
618+
tl = self.input.tail()
610619
if c.isspace():
611-
self.input = t
620+
self.input = tl
612621
else:
613622
break
614623
return True, e
@@ -843,7 +852,7 @@ def parseGrammar(self, name):
843852
self.name = name
844853
res, err = self.apply("grammar")
845854
try:
846-
x = self.input.head()
855+
self.input.head()
847856
except EOFError:
848857
pass
849858
else:

0 commit comments

Comments
 (0)