2016-11-19 10 views
0

PyParsingで本当に単純なものを複数行で解析しようとしていますが、なぜ動作しないのか分かりません。解析したい文字列は以下の通りです。複数行のPyParsingの例

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

私は、STARTとENDトークン間のすべての行がintまたはfloatタイプすることができる1つまたはそれ以上の正/負の数値が含まれていることを知っています。私はまた、ユーザが%符号の後に追加のメタデータを任意に追加することを期待しています。

フロートと名前の基本的な文法を定義することから始めます。

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

Iは、ラインがセミコロンに続く一つ以上Floatを含み、任意に% Nameによってできることを知っています。

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

多くの行が必要なので、次のように行の文法を定義できます。ポールにより示唆されるように、私は可能取り出すにするためにthis answerGroupを使用

Lines = OneOrMore(Group(Line)) 

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のdocsのサンプルインラインを参照)を使用して、無視できる空白のセットからそれらを削除する必要があります。最後に、フロートと名前の定義を強化することができます。今のところ、「...」、「---」、「1.1」などの文字列と一致します。1 "、Nameは" 12345 "と" 221B "に一致します – PaulMcG

答えて

1

これを解決するには、デフォルトの空白文字から新しい行を削除する必要があります。ポールが彼のコメントで示唆したように、浮動小数点数と名前をより厳密に解析するために、他の改善がなされる可能性があります。

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) 
関連する問題