pyPEG2给出了错误的结果

时间:2017-07-27 21:09:30

标签: python python-3.x parsing pypeg

我用pyPEG2创建了语法,用于解析如下语句:

  

A爱B但是B讨厌A,A讨厌B而A喜欢D而B喜欢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'

所以我做错了什么,文档描述得很好,但是我真的找不到我在那里做的错误。

希望有人可以帮忙解决这个问题。在此先感谢!!!

1 个答案:

答案 0 :(得分:1)

这里有两个问题。

您对Separator的语法使用Keyword类。这与“\ w”的默认正则表达式匹配 - 单词类型字符。 (https://fdik.org/pyPEG/grammar_elements.html#keyword

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

public static void main(String[] args) throws ParseException {
    String input = "Tue Dec 20 00:00:00 IST 2005";
    SimpleDateFormat inFormat = new SimpleDateFormat("EEE MMM d H:m:s zzz y");
    Date d = inFormat.parse(input);
    System.out.println("d = " + d);
    SimpleDateFormat outFormat = new SimpleDateFormat("y-MM-d");//(2005-12-20
    System.out.println("" + outFormat.format(d));
}

这应该有用。

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

对于另一部分,我认为这与使用Relation类型的命名空间有关。

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+')

如果你创建它的类型列表,它会更有意义 - 因为命名空间应该只有命名的东西,并且不确定对于命名空间项目有多个定义意味着什么。

>>> 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'), ])