|
19 | 19 |
|
20 | 20 | import sys |
21 | 21 | import string |
| 22 | +import operator |
| 23 | +import itertools |
| 24 | + |
22 | 25 | from pyparsing import * |
23 | 26 |
|
| 27 | +try: from functools import reduce |
| 28 | +except: pass |
| 29 | + |
24 | 30 | class Expression: |
25 | 31 | def __init__(self, contents): |
26 | 32 | self.contents = contents[0] |
@@ -56,12 +62,12 @@ def __repr__(self): |
56 | 62 | class Terminal: |
57 | 63 | def __init__(self, contents): |
58 | 64 | self.contents = contents[0] |
59 | | - def __repr__(self): |
60 | 65 | s = self.contents |
61 | | - is_keyword = len(s) >= 4 and s[0::len(s)-1] == '""' and \ |
| 66 | + self.is_keyword = len(s) >= 4 and s[0::len(s)-1] == '""' and \ |
62 | 67 | all(c in alphanums+"_" for c in s[1:-1]) |
63 | | - ty = "CaselessKeyword" if is_keyword else "CaselessLiteral" |
64 | | - return "%s(%s)" % (ty, s) |
| 68 | + def __repr__(self): |
| 69 | + ty = "CaselessKeyword" if self.is_keyword else "CaselessLiteral" |
| 70 | + return "%s(%s)" % (ty, self.contents) |
65 | 71 |
|
66 | 72 |
|
67 | 73 | LPAREN = Suppress("(") |
@@ -94,16 +100,16 @@ def __repr__(self): |
94 | 100 |
|
95 | 101 | express = grammar.parseFile(sys.argv[1]) |
96 | 102 |
|
97 | | -def find_keywords(expr, li = None): |
| 103 | +def find_bytype(expr, ty, li = None): |
98 | 104 | if li is None: li = [] |
99 | 105 | if isinstance(expr, Term): |
100 | 106 | expr = expr.contents |
101 | | - if isinstance(expr, Keyword): |
102 | | - li.append(repr(expr)) |
103 | | - return li |
| 107 | + if isinstance(expr, ty): |
| 108 | + li.append(expr) |
| 109 | + return set(li) |
104 | 110 | elif isinstance(expr, Expression): |
105 | 111 | for term in expr: |
106 | | - find_keywords(term, li) |
| 112 | + find_bytype(term, ty, li) |
107 | 113 | return set(li) |
108 | 114 |
|
109 | 115 | actions = { |
@@ -131,18 +137,22 @@ def find_keywords(expr, li = None): |
131 | 137 | to_combine = set(["simple_id"]) |
132 | 138 | to_ignore = set(["where_clause", "supertype_constraint", "unique_clause"]) |
133 | 139 | statements = [] |
| 140 | + |
| 141 | +terminals = reduce(lambda x,y: x | y, (find_bytype(e, Terminal) for id, e in express)) |
| 142 | +keywords = list(filter(operator.attrgetter('is_keyword'), terminals)) |
| 143 | +negated_keywords = map(lambda s: "~%s" % s, keywords) |
134 | 144 |
|
135 | 145 | while True: |
136 | 146 | emitted_in_loop = set() |
137 | 147 | for id, expr in express: |
138 | | - kws = find_keywords(expr) |
| 148 | + kws = map(repr, find_bytype(expr, Keyword)) |
139 | 149 | found = [k in emitted for k in kws] |
140 | 150 | if id in to_emit and all(found): |
141 | 151 | emitted_in_loop.add(id) |
142 | 152 | emitted.add(id) |
143 | 153 | stmt = "(%s)" % expr |
144 | 154 | if id in to_combine: |
145 | | - stmt = "originalTextFor(Combine%s)" % stmt |
| 155 | + stmt = " + ".join(itertools.chain(negated_keywords, ("originalTextFor(Combine%s)" % stmt,))) |
146 | 156 | if id in actions: |
147 | 157 | stmt = "%s.setParseAction(%s)" % (stmt, actions[id]) |
148 | 158 | statements.append("%s = %s" % (id, stmt)) |
|
0 commit comments