多行 PyParsing 示例

Multiline PyParsing example

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

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

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

所以我首先定义浮点数和名称的基本语法。

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

我知道一行可以包含一个或多个 Float 后跟一个分号,并且可以选择 % Name.

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

我希望有很多行,所以我可以如下定义行的语法。

Lines = OneOrMore(Group(Line))

我按照 Paul 在 中的建议使用 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)

但是,这并不是 return 分号后的结构化部分,我必须再次单独解析它。这是推荐的方法吗?

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

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)