多行PyParsing示例

时间:2016-11-19 19:26:30

标签: python pyparsing

我试图在PyParsing中解析一些非常简单的东西,但是我很难理解为什么它不起作用。我要解析的字符串如下。

string = '''START
    1   10; %   Name1
    2   20; %   Name2
END'''

我知道START和END令牌之间的每一行都包含一个或多个可能为intfloat类型的正/负数。我还希望用户可以选择在%符号后添加其他元数据。

所以我首先定义Floats和Names的基本语法。

Float = Word(nums + '.' + '-')
Name = Word(alphanums)

我知道一行可以包含一个或多个Float后跟分号,也可以包含% Name

Line = OneOrMore(Float)('data') + Suppress(Literal(';')) + Suppress(Optional(Literal('%'))) + Optional(OneOrMore(Name)('name')) + Suppress(LineEnd())

我期待很多行,所以我可以按如下方式定义Lines的语法。

Lines = OneOrMore(Group(Line))

我按照this answer中的建议使用Group来使检索成为可能。

grammar = Suppress(Keyword('START')) + Lines + Suppress(Keyword('END'))

grammar.parseString(string)

然而,这会引发错误,说明以下

ParseException: Expected end of line (at char 62), (line:3, col:19)

以下完整代码,以便于复制和粘贴。

string = '''START
    1   10; %   Name1
    2   20; %   Name2
END'''

from pyparsing import Word, Keyword, nums, OneOrMore, Optional, Suppress, Literal, alphanums, LineEnd, LineStart, Group

Float = Word(nums + '.' + '-')
Name = Word(alphanums)
Line = OneOrMore(Float)('data') + Suppress(Literal(';')) + Suppress(Optional(Literal('%'))) + Optional(OneOrMore(Name)('name')) + Suppress(LineEnd())
Lines = OneOrMore(Group(Line))

grammar = Suppress(Keyword('START')) + Lines + Suppress(Keyword('END'))
grammar.parseString(string)

编辑:

我已经尝试了以下无效。

string = '''START
    1   10; %   Name1
    2   20; %   Name2
END'''

from pyparsing import Word, Keyword, nums, OneOrMore, Optional, Suppress, Literal, alphanums, LineEnd, LineStart, Group

Float = Word(nums + '.' + '-')
Name = Word(alphanums)
NL = Suppress(LineEnd())
Line = OneOrMore(Float)('data') + Suppress(Literal(';')) + Optional(~NL +
                                                            Suppress(Literal('%'))
                                                            + OneOrMore(Name)('name') + NL ) | NL
Lines = OneOrMore(Group(Line))

grammar = Suppress(Keyword('START')) + Lines + Suppress(Keyword('END'))
grammar.parseString(string)

唯一可行的方法是使用restOfLine

Line = OneOrMore(Float)('data') + Suppress(Literal(';')) + Optional(restOfLine)

但是,这不会以结构化的方式返回分号后面的部分,我必须再次单独解析它。这是推荐的方法吗?

1 个答案:

答案 0 :(得分:2)

从默认的空白字符中删除新行是解决此问题所需的。正如保罗在评论中所说,可以做出其他改进,以确保它更严格地解析浮点数和名称。

string = '''START
    1   10; %   Name1
    2   20; %   Name2
END'''

from pyparsing import Word, Keyword, nums, OneOrMore, Optional, Suppress, Literal, alphanums, LineEnd, LineStart, Group, ParserElement

ParserElement.setDefaultWhitespaceChars(" \t")

Float = Word(nums + '.' + '-')
Name = Word(alphanums)
NL = Suppress(LineEnd())
Line = OneOrMore(Float)('data') + Suppress(Literal(';')) + Optional(~NL +
                                                            Suppress(Literal('%'))
                                                            + OneOrMore(Name)('name') + NL ) | NL
Lines = OneOrMore(Group(Line))

grammar = Suppress(Keyword('START')) + Lines + Suppress(Keyword('END'))
grammar.parseString(string)