pyPEG2 给出错误的结果

pyPEG2 giving wrong result

我已经使用 pyPEG2 创建语法来解析如下语句:

A loves B but B hates A, A hates B and A loves D while B loves C

下面是我的代码:

import pypeg2 as pp


class Person(str):
    grammar = pp.word

class Action(pp.Keyword):
    grammar = pp.Enum(pp.K('loves'), pp.K('hates'))

class Separator(pp.Keyword):
    grammar = pp.Enum(pp.K(','), pp.K('\n'), pp.K('but'), pp.K('and'), pp.K('while'))

relation = Person, Action, Person

class Relations(pp.Namespace):
    grammar = relation, pp.maybe_some(Separator, relation)

然而,当我尝试执行以下操作时:

>>> love = pp.parse('A loves B but B hates A , B loves C, Relations)

我得到:

Traceback (most recent call last):
  File "<pyshell#64>", line 1, in <module>
    love = pp.parse('A loves B but B hates A , B loves C', Relations)
  File "/home/michael/.local/lib/python3.5/site-packages/pypeg2/__init__.py", line 669, in parse
    raise parser.last_error
  File "<string>", line 1
    es B but B hates A , B loves C
                       ^
SyntaxError: expecting Separator
>>> 

如果我更改此声明:

>>> love = pp.parse('A loves B but B hates A and B loves C', Relations)

没有错误,但由于某些原因错过了最后一个块:

>>> pp.compose(love)
'A loves B but B hates A'

那么我哪里做错了,文档描述得很清楚,但无法真正找到我在那里做错了什么。

希望有人可以帮助解决这个问题。提前致谢!!!

这里有两个问题。

分隔符的语法使用关键字 class。这匹配默认的正则表达式 "\w" - 单词类型字符。 (https://fdik.org/pyPEG/grammar_elements.html#keyword)

您需要导入 re,并为此定义您自己的正则表达式 class。此正则表达式应该是您希望允许进入关键字的其他字符,或者至少是一个词类型。

import re

class Separator(pp.Keyword):
    grammar = pp.Enum(pp.K(','), pp.K('\n'), pp.K('but'), pp.K('and'), pp.K('while'))
    regex = re.compile('[,]|\w+')

这应该有效。

注意 - 我也不确定将换行符作为分隔符是否有效 - 您可能需要深入了解 pypeg2 中单个语法中的多行解析。

另一方面,我认为这与为 Relations 类型使用命名空间有关。

>>> love
Relations([(Symbol('#2024226558144'), 'A'), (Symbol('loves'), 
  Action('loves')), (Symbol('#2024226558384'), 'B'), (Symbol('but'),
  Separator('but')), (Symbol('#2024226558624'), 'B'), (Symbol('hates'),
  Action('hates')), (Symbol('#2024226558864'), 'A'), (Symbol('and'), 
  Separator('and')), (Symbol('#2024226559104'), 'B'),
  (Symbol('#2024226559344'), 'C'), ])

如果将其设为类型列表,则更有意义 - 因为命名空间应该只有命名的东西,并且不确定对一个命名空间项目有多个定义意味着什么。

class Relations(pp.Namespace):
  grammar = relation, pp.maybe_some(Separator, relation)

>>> love = pp.parse('A loves B but B hates A and B loves C', Relations)
>>> love
['A', Action('loves'), 'B', Separator('but'), 'B', Action('hates'), 'A', Separator('and'), 'B', Action('loves'), 'C']
>>> pp.compose(love)
'A loves B but B hates A and B loves C'