2016-05-12 12 views
-1

Ich habe einen einfachen Parser für einfache Abfragen, um Daten aus einem Datenspeicher zu holen. Die Operanden ich verwendet habe, sind <, < =,>,> =, ==,! = Der Parser arbeitet für jeden Operanden in Ordnung, außer für < Ich bin ein wenig überrascht, mit dem Verhalten, da die Regex für jeden Operanden ist fast gleich. Ich kann nicht finden, was ich falsch gemacht habe.RegEx Parse Fehler von Parsley Python

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: 
      return field 
     elif type(field) is Field: 
      elements = FieldSet(field,self.getter) 
      return 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() 
     return result 

    '''This functions will be returning 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 
     return result  


    def getResults(self,query): 
     return self.parse(query).expr().getSet() 
if __name__=="__main__": 
    pae = QueryParser("POP") 
    print pae.getResults("lame>10") 

Für jeden anderen Operanden ist der Ausgang so etwas wie diese

res lame<10 
set(['-&-lame<10']) 
set(['-&-lame<10']) 

Aber für '>' der Ausgang/Fehler wie:

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 getResults 
    return self.parse(query).expr().getSet() 
    File "D:\Nother\lookup_env\lib\site-packages\parsley.py", line 98, in invokeRule 
    raise err 
ometa.runtime.EOFError: 
lame>10 
^ 
Parse error at line 2, column 0: end of input. trail: [digit] 

Ich nehme an, es versucht, eine Ziffer zu finden, und es ist nicht in der Lage, aber eine ähnliche Regex wurde für andere Operanden geschrieben und führt nicht zu einem Fehler, der seltsam erscheint. Würde mich freuen, wenn sich jemand damit befassen und mir sagen könnte, wo ich falsch liege.

Antwort

0

Das Problem mit dieser RegEx war, wie ich den Wert regEx behandelt.

value = ws parens | neq | eq | lte | lt | gte |gt ws 

Hier Leerzeichen Ich habe hinzugefügt vor und nach den alle möglichen Optionen, also anstelle von Leerzeichen optional ist es erzwungen wurde. Also anstatt ws hier an Wert verwendet wird, habe ich ws, wo ich für die Suche im Wert Token wurde mit und geändert Wert

value = parens | neq | eq | lte | lt | gte |gt 

Das ist mein Problem gelöst.