Eth*_*ein 14 python parsing peg python-2.7 parsimonious
我一直试图找出我设计的语言的基本骨架,并且我正在尝试使用Parsimonious来为我解析.截至目前,我已经宣布了以下语法:
grammar = Grammar(
"""
program = expr*
expr = _ "{" lvalue (rvalue / expr)* "}" _
lvalue = _ ~"[a-z0-9\\-]+" _
rvalue = _ ~".+" _
_ = ~"[\\n\\s]*"
"""
)
Run Code Online (Sandbox Code Playgroud)
当我尝试输出简单输入字符串的结果AST时"{ do-something some-argument }":
Run Code Online (Sandbox Code Playgroud)print(grammar.parse("{ do-something some-argument }"))
Parsimonious决定拒绝它,然后给我这个有点神秘的错误:
Run Code Online (Sandbox Code Playgroud)Traceback (most recent call last): File "tests.py", line 13, in <module> print(grammar.parse("{ do-something some-argument }")) File "/usr/local/lib/python2.7/dist-packages/parsimonious/grammar.py", line 112, in parse return self.default_rule.parse(text, pos=pos) File "/usr/local/lib/python2.7/dist-packages/parsimonious/expressions.py", line 109, in parse raise IncompleteParseError(text, node.end, self) parsimonious.exceptions.IncompleteParseError: Rule 'program' matched in its entirety, but it didn't consume all the text. The non-matching portion of the text begins with '{ do-something some-' (line 1, column 1).
起初我认为这可能是与我的空白规则有关的问题_,但是在某些地方删除空白规则的尝试失败之后,我仍然遇到了同样的错误.
我试过在线搜索,但我发现这一切似乎与远程相关,这是一个问题,这对我没有任何帮助.
我的语法有问题吗?我没有以正确的方式解析输入吗?如果有人有可能的解决方案,我们将不胜感激.
我与Parsimonious的专家相距甚远,但我相信问题是~".+"贪婪地匹配输入字符串的整个剩余部分,没有任何东西可以与生产的其余部分相匹配.我最初通过将正则表达式更改为rvalueto来测试该想法~"[a-z0-9\\-]+",与您所使用的相同lvalue.现在它分析,和(赫然)由两个相同定义令牌之间的上下文区分lvalue和rvalue.
from parsimonious.grammar import Grammar
grammar = Grammar(
"""
program = expr*
expr = _ "{" lvalue (rvalue / expr)* "}" _
lvalue = _ ~"[a-z0-9\\-]+" _
rvalue = _ ~"[a-z0-9\\-]+" _
_ = ~"[\\n\\s]*"
"""
)
print(grammar.parse( "{ do-something some-argument }"))
Run Code Online (Sandbox Code Playgroud)
如果你rvalue想匹配任何非空白字符序列,你想要更像这样的东西:
rvalue = _ ~"[^\\s\\n]+" _
Run Code Online (Sandbox Code Playgroud)
但是哎呀!
{ foo bar }
Run Code Online (Sandbox Code Playgroud)
"}"是一个结束的大括号,但它也是一个或多个非空白字符的序列.难道"}"还是rvalue?语法说下一个标记可以是其中之一.其中一种解释是可解析的而另一种解释不是,但Parsimonious只是说它的菠菜和它的地狱.我不知道解析专家是否会认为这是解决歧义的合法方法(例如,这样的语法可能会导致两种可能的解释都解析的情况),或实现的实际可行性.在任何情况下,Parsimonious都没有打那个电话.
所以我们需要在大括号问题上击退寄宿生.我认为这个语法符合你的要求:
from parsimonious.grammar import Grammar
grammar = Grammar(
"""
program = expr*
expr = _ "{" lvalue (expr / rvalue)* "}" _
lvalue = _ ~"[a-z0-9\\-]+" _
rvalue = _ ~"[^{}\\n\\s]+" _
_ = ~"[\\n\\s]*"
"""
)
print(grammar.match( "{ do-something some-argument 23423 {foo bar} &^%$ }"))
Run Code Online (Sandbox Code Playgroud)
我也排除了开放的大括号,因为您希望这个字符串如何标记化?
{foo bar{baz poo}}
Run Code Online (Sandbox Code Playgroud)
我期待
"{" "foo" "bar" "{" "baz" "poo" "}" "}"
Run Code Online (Sandbox Code Playgroud)
......因为如果"poo}"预期作为记号化"poo" "}",并"{foo"有望作为记号化"{" "foo",那么治疗bar{baz的"bar{baz"或者"bar{" "baz"是错乱常理.
现在我记得我对yacc的痛恨让我对它有一种痴迷.