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 parsley
from FieldSet import FieldSet
from Field import Field
class QueryParser(object):
def __init__(self,getter):
self.__defineParser()
self.getter = getter
def __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 -> e
value = ws parens | neq | eq | lte | lt | gte |gt ws
ws = ' '*
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:
retu field
elif type(field) is Field:
elements = FieldSet(field,self.getter)
retu elements
else:
raise Exception("Invalid Input")
def performOperations(self,start, pairs):
result = start
if 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()
retu result
'''This functions will be retuing sets'''
def getVal(self,field):
if type(field) is tuple:
_op,value = field
result = self.parseField(value).fieldCondition()
result.negate()
elif type(field) is FieldSet:
result = field
else:
result = self.parseField(field).fieldCondition()
print "res",result
retu result
def getResults(self,query):
retu 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:NotherengineparserQueryParser.py", line 107, in <module>
print pae.getResults("lame>10")
File "D:NotherengineparserQueryParser.py", line 104, in getResults
retu self.parse(query).expr().getSet()
File "D:Notherlookup_envlibsite-packagesparsley.py", line 98, in invokeRule
raise 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.
