2011-01-26 7 views
14

私は、形式の式を解析するためにpyparsingを使い、[[['gimme', ['some', ['nested', ['lists']]]]]]の形式のpythonリストを取得したいと思います。今、私の文法は次のようになります。pyparsingを使用して複数のオープナー/クローザータイプを持つネストされた式を解析するにはどうすればよいですか?

nestedParens = nestedExpr( '('、 ')')
nestedBrackets = nestedExpr( '['、 ']')
nestedCurlies = nestedExpr( '{'、「} ')
enclosed = nestedParens | nestedBrackets | nestedCurlies

現在、enclosed.searchString(expr)は、[[['gimme', ['some', '{nested', '[lists]}']]]]の形式のリストを返します。これは正方形か中括弧を認識していないので、私が望むものではありませんが、理由はわかりません。

答えて

26

はここで動的に正しい閉じ括弧文字に一致するように自己修正の文法を使用していますpyparsingソリューションです必要な場合は

import re 
import ast 

def parse(s): 
    s = re.sub("[\{\(\[]", '[', s) 
    s = re.sub("[\}\)\]]", ']', s) 
    answer = '' 
    for i,char in enumerate(s): 
     if char == '[': 
      answer += char + "'" 
     elif char == '[': 
      answer += "'" + char + "'" 
     elif char == ']': 
      answer += char 
     else: 
      answer += char 
      if s[i+1] in '[]': 
       answer += "', " 
    ast.literal_eval("s=%s" %answer) 
    return s 

コメント。

from pyparsing import * 

data = '(gimme [some {nested, nested [lists]}])' 

opening = oneOf("({ [") 
nonBracePrintables = ''.join(c for c in printables if c not in '(){}[]') 
closingFor = dict(zip("({[",")}]")) 
closing = Forward() 
# initialize closing with an expression 
closing << NoMatch() 
closingStack = [] 
def pushClosing(t): 
    closingStack.append(closing.expr) 
    closing << Literal(closingFor[t[0]]) 
def popClosing(): 
    closing << closingStack.pop() 
opening.setParseAction(pushClosing) 
closing.setParseAction(popClosing) 

matchedNesting = nestedExpr(opening, closing, Word(alphas) | Word(nonBracePrintables)) 

print matchedNesting.parseString(data).asList() 

プリント:更新

[['gimme', ['some', ['nested', ',', 'nested', ['lists']]]]] 

私は実際に実験として年前にそれを上に書かれていたので、私は上記の溶液を掲載。私はちょうどオリジナルの投稿を詳しく見て、それはoperatorPrecedenceメソッドで作成された再帰型定義を考えさせてくれました。元のアプローチを使用してこのソリューションを再作成しました。

from pyparsing import * 

enclosed = Forward() 
nestedParens = nestedExpr('(', ')', content=enclosed) 
nestedBrackets = nestedExpr('[', ']', content=enclosed) 
nestedCurlies = nestedExpr('{', '}', content=enclosed) 
enclosed << (Word(alphas) | ',' | nestedParens | nestedBrackets | nestedCurlies) 


data = '(gimme [some {nested, nested [lists]}])' 

print enclosed.parseString(data).asList() 

を与える:(徹底的にテストしていない、しかし右入力データと左再帰の問題がある可能性があります)

[['gimme', ['some', ['nested', ',', 'nested', ['lists']]]]] 
+0

Paul、有益な回答をありがとうございました。そして、私の新しいお気に入りのPythonライブラリを作成し、オープンソース化してくれてありがとう! pyparsingは私が取り組んでいるプロジェクトのサイズ、複雑さ、保守性を劇的に減らすのに役立っています。 – Derek

+0

賛辞をお寄せいただきありがとうございます。 – PaulMcG

-3

これはあなたのためのトリックを行う必要があります。私はあなたの例でそれをテストした:あなたはもっと

+1

謝罪を明確に十分なされていないために、私が言及して出力されますネストしたPythonリスト。これは、pyparsingでネストされた式を解析する一般的な結果です。あなたのソリューションは、単に印刷されたPythonリストのような文字列を返します。あなたの助けをありがとう! – Derek

+0

@Derek:文字列を返さない。私はリストを返すよ。 answerという名前の変数は文字列です(yes)。だからこそ、exec = "%s"%answerという行があります。これにより、sという新しい変数が作成されます。これはリストです。これが私のコードが答えを返してくれない理由です。返される値の型をチェックすると、リストであることがわかります。文字列ではなく、 – inspectorG4dget

+3

を返していますが、この文脈でどのような構文解析が誤解されていると思います。文字列を解析するときは、通常、構文解析時に一致したトークン/グループにアクセスし、その上で何らかのアクションを実行できます。あなたのプログラムは単にPythonコードを動的に生成し、それを実行して文字列をネストされたリストに変換します。それは何も解析せず、元の質問で言及されたようにpyparsingを使用しません。言い換えれば、任意のpythonコードを実行するので、引用符付きの入力では失敗します。 – Derek

関連する問題