Translating an EBNF grammar to pyparsing give error

故事扮演 提交于 2020-06-17 07:07:11

问题


I am making a parser to convert a simple DSL into elasticsearch query. some of the possible queries are:

response:success
response:success AND extension:php OR extension:css
response:sucess AND (extension:php OR extension:css)
time >= 2020-01-09
time >= 2020-01-09 AND response:success OR os:windows
NOT reponse:success
response:success AND NOT os:windows

I have written the following EBNF grammar for this :

<expr> ::= <or>
<or> ::= <and> (" OR " <and>)*
<and> ::= <unary> ((" AND ") <unary>)*
<unary> ::= " NOT " <unary> | <equality>
<equality> ::=  (<word> ":" <word>) | <comparison>
<comparison> ::= "(" <expr> ")" | (<word> (" > " | " >= " | " < " | " <= ") <word>)+
<word> ::= ("a" | "b" | "c" | "d" | "e" | "f" | "g"
                      | "h" | "i" | "j" | "k" | "l" | "m" | "n"
                      | "o" | "p" | "q" | "r" | "s" | "t" | "u"
                      | "v" | "w" | "x" | "y" | "z")+

The precdence of operators in the DSL is: () > NOT > AND > OR aslo exact mathing i.e ':' has higher precedence than comparison operators.

I believe the above grammar capture the idea of my DSL. I am having a difficult time translating it to pyparsing, this is what i have now:

from pyparsing import *

AND = Keyword('AND') | Keyword('and')
OR  = Keyword('OR')  | Keyword('or')
NOT = Keyword('NOT') | Keyword('not')

word = Word(printables, excludeChars=':')

expr = Forward()

expr << Or
Comparison = Literal('(') + expr + Literal(')')  + OneOrMore(word + ( Literal('>') | Literal('>=') | Literal('<') | Literal('<=')) + word)
Equality = (word + Literal(':') + word) | Comparison
Unary = Forward()
Unary << (NOT + Unary) | Equality
And = Unary + ZeroOrMore(AND + Unary)
Or = And + ZeroOrMore(OR + And)

The error i get is :

Traceback (most recent call last):
  File "qql.py", line 54, in <module>
    expr << Or
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pyparsing.py", line 5006, in __lshift__
    self.mayIndexError = self.expr.mayIndexError
AttributeError: type object 'Or' has no attribute 'mayIndexError'

I think its becuase i am unable to understand Forward() correctly.

Questions: how can i correctly translate the above grammar to pyparsing?

**EDIT **: when i changed the pyparsing code to:

AND = Keyword('AND')
OR  = Keyword('OR')
NOT = Keyword('NOT')
word = Word(printables, excludeChars=':')

expr = Forward()
Comparison = Literal('(') + expr + Literal(')')  + OneOrMore(word + ( Literal('>') | Literal('>=') | Literal('<') | Literal('<=')) + word)
Equality = (word + Literal(':') + word) | Comparison
Unary = Forward()
Unary << ((NOT + Unary) | Equality)
And = Unary + ZeroOrMore(AND) + Unary
Or = And + ZeroOrMore(OR + And)
expr << Or


Q = """response : 200        \
    AND extesnion: php       \
    OR  extension: css       \
    """
print(expr.parseString(Q))

I get this output:

['response', ':', '200', 'AND', 'extesnion', ':', 'php']

why OR expression is not parsed?

来源:https://stackoverflow.com/questions/61934552/translating-an-ebnf-grammar-to-pyparsing-give-error

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!