162 return (op, x[1], ta) |
162 return (op, x[1], ta) |
163 raise error.ProgrammingError('invalid operator %r' % op) |
163 raise error.ProgrammingError('invalid operator %r' % op) |
164 |
164 |
165 def analyze(x): |
165 def analyze(x): |
166 """Transform raw parsed tree to evaluatable tree which can be fed to |
166 """Transform raw parsed tree to evaluatable tree which can be fed to |
167 getmatch() |
167 optimize() or getmatch() |
168 |
168 |
169 All pseudo operations should be mapped to real operations or functions |
169 All pseudo operations should be mapped to real operations or functions |
170 defined in methods or symbols table respectively. |
170 defined in methods or symbols table respectively. |
171 """ |
171 """ |
172 return _analyze(x) |
172 return _analyze(x) |
173 |
173 |
|
174 def _optimize(x): |
|
175 if x is None: |
|
176 return 0, x |
|
177 |
|
178 op = x[0] |
|
179 if op in {'string', 'symbol'}: |
|
180 return 0.5, x |
|
181 if op == 'kindpat': |
|
182 w, t = _optimize(x[2]) |
|
183 return w, (op, x[1], t) |
|
184 if op == 'not': |
|
185 w, t = _optimize(x[1]) |
|
186 return w, (op, t) |
|
187 if op in {'and', 'minus'}: |
|
188 wa, ta = _optimize(x[1]) |
|
189 wb, tb = _optimize(x[2]) |
|
190 return max(wa, wb), (op, ta, tb) |
|
191 if op == 'or': |
|
192 ws, ts = zip(*(_optimize(y) for y in x[1:])) |
|
193 return max(ws), (op,) + ts |
|
194 if op == 'list': |
|
195 ws, ts = zip(*(_optimize(y) for y in x[1:])) |
|
196 return sum(ws), (op,) + ts |
|
197 if op == 'func': |
|
198 f = getsymbol(x[1]) |
|
199 w = getattr(symbols.get(f), '_weight', 1) |
|
200 wa, ta = _optimize(x[2]) |
|
201 return w + wa, (op, x[1], ta) |
|
202 raise error.ProgrammingError('invalid operator %r' % op) |
|
203 |
|
204 def optimize(x): |
|
205 """Reorder/rewrite evaluatable tree for optimization |
|
206 |
|
207 All pseudo operations should be transformed beforehand. |
|
208 """ |
|
209 _w, t = _optimize(x) |
|
210 return t |
|
211 |
174 def prettyformat(tree): |
212 def prettyformat(tree): |
175 return parser.prettyformat(tree, ('string', 'symbol')) |
213 return parser.prettyformat(tree, ('string', 'symbol')) |