2016-11-19 129 views
0

我想解析一些非常简单的PyParsing,这是多行,但我挣扎明白为什么它不工作。我想解析的字符串如下。多行PyParsing示例

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

我知道,开始和结束标记之间每行包含一个或多个正/负号,可以是intfloat类型。我也希望用户可以选择在%符号后添加额外的元数据。

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

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

我知道一个线可以由% Name包含随后分号一个或多个Float,以及任选。

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

我预计很多行,所以我可以定义行的语法如下。

Lines = OneOrMore(Group(Line)) 

我用Group如保罗在this answer建议,使检索成为可能。

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) 

然而,这并不在一个结构化的方式分号后返回的部分,我必须分析它再分开。这是推荐的方法吗?

+0

添加“Name.setDebug()”和“Float.setDebug()”,看看该输出是否有用。 – PaulMcG

+0

这个输出似乎表明'OneOrMore(Name)'比行尾更进一步。推荐的方法是确保OneOrMore(Name)在行尾停止。我尝试了OneOrMore(Name)+ NL,但这也没有奏效,我无法理解为什么。 – kdheepak

+0

首先,是“2”的有效名称吗?其次,语法结尾是否有意义?如果是这样,那么您应该使用ParserElement.setDefaultWhitespaceChars(请参阅https://pythonhosted.org/pyparsing/pyparsing.ParserElement-class.html#setDefaultWhitespaceChars中的文档内联示例)将它们从可忽略的空白集中移除。最后,你可能想要收紧Float和Name的定义。就像你现在拥有它们一样,Float将匹配诸如“......”,“---”和“1.1”之类的字符串。1“,名称将匹配”12345“和”221B“ – PaulMcG

回答

1

从默认空白字符中删除新行是解决此问题所需的。正如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)