I have made a simple parser for simple queries, to fetch data from a datastore. The operands I have used are <,<=,>,>=,==,!= The Parser works fine for every operand except for < I am a bit surprised with the behavior since the regex for each operand are almost identical. I am unable to find what i might have done wrong.
Code:
import parsleyfrom FieldSet import FieldSet
from Field import Fieldclass QueryParser(object):def __init__(self,getter):self.__defineParser()self.getter = getterdef __defineParser(self):self.parseField = parsley.makeGrammar("""neq = <letterOrDigit*>:field ws '!=' ws <letterOrDigit*>:value ->Field(field,value,'!=')eq = <letterOrDigit*>:field ws '==' ws <letterOrDigit*>:value ->Field(field,value,'==')lte = <letterOrDigit*>:field ws '<=' ws <digit*'.'?digit*>:value ->Field(field,value,'<=')gte = <letterOrDigit*>:field ws '>=' ws <digit*'.'?digit*>:value ->Field(field,value,'>=')lt = <letterOrDigit*>:field ws '<' ws <digit*'.'?digit*>:value ->Field(field,value,'<')gt = <letterOrDigit*>:field ws '>' ws <digit*'.'?digit*>:value ->Field(field,value,'>')fieldCondition = ws (neq | eq | lte | lt | gte |gt):evalTuple ws -> evalTuple""",{'Field':Field}) self.parse = parsley.makeGrammar("""neq = <letterOrDigit* ws '!=' ws letterOrDigit*>:s ->str(s)eq = <letterOrDigit* ws '==' ws letterOrDigit*>:s ->str(s)lte = <letterOrDigit* ws '<=' ws digit*'.'?digit*>:s->str(s)gte = <letterOrDigit* ws '>=' ws digit*'.'?digit*>:s ->str(s)lt = <letterOrDigit* ws '<' ws digit*'.'?digit*>:s->str(s)gt = <letterOrDigit* ws '>' ws digit*'.'?digit*>:s ->str(s)parens = ws '(' ws expr:e ws ')' ws -> evalue = ws parens | neq | eq | lte | lt | gte |gt wsws = ' '*and = 'AND' ws expr3:n -> ('AND', n)or = 'OR' ws expr3:n -> ('OR', n)not = 'NOT' ws value:n -> ('NOT', n)checknot = ws (value|not)andor = ws (and | or)expr = expr3:left andor*:right -> performOperations(left, right)expr3 = ws checknot:right -> getVal(right)""", {"performOperations": self.performOperations,'getVal':self.getVal})def processQuery(self,field):if type(field) is FieldSet:return fieldelif type(field) is Field:elements = FieldSet(field,self.getter)return elementselse:raise Exception("Invalid Input")def performOperations(self,start, pairs):result = startif type(result) is Field:result = self.processQuery(start)for op, value in pairs:if op == 'AND':secondField = self.processQuery(value)result.union(secondField)elif op == 'OR':secondField = self.processQuery(value)result.intersection(secondField)print type(result)print result.getSet() return result'''This functions will be returning sets'''def getVal(self,field):if type(field) is tuple:_op,value = fieldresult = self.parseField(value).fieldCondition()result.negate()elif type(field) is FieldSet:result = fieldelse:result = self.parseField(field).fieldCondition()print "res",resultreturn result def getResults(self,query):return self.parse(query).expr().getSet()
if __name__=="__main__":pae = QueryParser("POP")print pae.getResults("lame>10")
For Every other Operand the output is something like this
res lame<10
set(['-&-lame<10'])
set(['-&-lame<10'])
But for '>' the output/error is as:
Traceback (most recent call last):File "D:\Nother\engine\parser\QueryParser.py", line 107, in <module>print pae.getResults("lame>10")File "D:\Nother\engine\parser\QueryParser.py", line 104, in getResultsreturn self.parse(query).expr().getSet()File "D:\Nother\lookup_env\lib\site-packages\parsley.py", line 98, in invokeRuleraise err
ometa.runtime.EOFError:
lame>10
^
Parse error at line 2, column 0: end of input. trail: [digit]
I suppose its trying to find some digit and its not able to.But similar regex has been written for other operands and it does not result in an error, which seems to be weird. Would appreciate if anyone could look into this and tell me where I am wrong.