#!/usr/bin/env python def eval_expression(elements, name, operator, arg, ui): # print "Evaluating %s.%s(%r)" % (name,operator,arg) ## Try and find the element with the specified name: element = None for e in elements: if e.name == name: element = e break if not element: raise RuntimeError("Column %s not known" % name) ## Use the element to parse: return element.parse(name, operator, arg, context='code', ui=ui) def logical_operator_parse(left, operator, right): if operator=="and": return lambda row: left(row) and right(row) elif operator=="or": return lambda row: left(row) or right(row) raise RuntimeError("operator %s not supported" % operator) # Begin -- grammar generated by Yapps import sys, re from yapps import runtime class CodeParserScanner(runtime.Scanner): patterns = [ ("'\\\\)'", re.compile('\\)')), ("'\\\\('", re.compile('\\(')), ('[ \r\t\n]+', re.compile('[ \r\t\n]+')), ('END', re.compile('$')), ('STR', re.compile('"([^\\\\"]+|\\\\.)*"')), ('STR2', re.compile("'([^\\\\']+|\\\\.)*'")), ('WORD', re.compile('[-:+*/!@$%^&=\\<\\>.a-zA-Z0-9_]+')), ('LOGICAL_OPERATOR', re.compile('(and|or|AND|OR)')), ] def __init__(self, str,*args,**kw): runtime.Scanner.__init__(self,None,{'[ \r\t\n]+':None,},str,*args,**kw) class CodeParser(runtime.Parser): Context = runtime.Context def goal(self, types, ui, _parent=None): _context = self.Context(_parent, self._scanner, 'goal', [types, ui]) clause = self.clause(types, ui, _context) END = self._scan('END', context=_context) return clause def clause(self, types, ui, _parent=None): _context = self.Context(_parent, self._scanner, 'clause', [types, ui]) expr = self.expr(types, ui, _context) result = expr while self._peek('LOGICAL_OPERATOR', 'END', "'\\\\)'", context=_context) == 'LOGICAL_OPERATOR': LOGICAL_OPERATOR = self._scan('LOGICAL_OPERATOR', context=_context) logical_operator = LOGICAL_OPERATOR expr = self.expr(types, ui, _context) result = logical_operator_parse(result, logical_operator, expr) return result def term(self, _parent=None): _context = self.Context(_parent, self._scanner, 'term', []) _token = self._peek('STR', 'STR2', 'WORD', context=_context) if _token == 'STR': STR = self._scan('STR', context=_context) return eval(STR) elif _token == 'STR2': STR2 = self._scan('STR2', context=_context) return eval(STR2) else: # == 'WORD' WORD = self._scan('WORD', context=_context) return WORD def expr(self, types, ui, _parent=None): _context = self.Context(_parent, self._scanner, 'expr', [types, ui]) _token = self._peek('STR', 'STR2', 'WORD', "'\\\\('", context=_context) if _token != "'\\\\('": term = self.term(_context) column = term WORD = self._scan('WORD', context=_context) operator = WORD term = self.term(_context) return eval_expression(types, column,operator,term, ui) else: # == "'\\\\('" self._scan("'\\\\('", context=_context) clause = self.clause(types, ui, _context) self._scan("'\\\\)'", context=_context) return clause def parse(rule, text): P = CodeParser(CodeParserScanner(text)) return runtime.wrap_error_reporter(P, rule) # End -- grammar generated by Yapps def parse_eval(text, types, ui): """ This return a parse tree from the expression in text using the table objects in types. A parse tree is essentially a function which may be called with: function(row) where row is a dict containing all the column in the row. The function returns True if the filter expression applies to the row or False otherwise. Note that once the filter is parsed there is no need to re-parse it for each row, just reuse the function over and over. This is very fast. """ P = CodeParser(CodeParserScanner(text)) try: return P.goal(types, ui) except runtime.SyntaxError, e: raise RuntimeError("\n%s\n%s^\n%s" % (text, '-' * e.pos[2], e.msg)) if __name__=='__main__': import pyflag.TableObj as TableObj types = [ TableObj.TimestampType(name='Timestamp'), TableObj.IPType(name='IP Address')] test = 'Timestamp < "2006-10-01 \\\"10:10:00\\\"" or (Timestamp before \'2006-11-01 "10:10:00"\' and "IP Address" netmask "10.10.10.0/24") or "IP Address" = 192.168.1.1' print "Will test %s" % test print parse_eval(test,types)