2016-11-19 124 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)