私が何をしているかを理解するために、directx .xテキストファイルを解析するpythonパーサーを書いています。
私が抱えている問題は、ファイルのフォーマット方法を扱っています。私はそれをpythonで書いていますが、この種の解析を処理するための一般的なアルゴリズムを探しています。
.xファイルは、テンプレートを使用してデータを定義します。テンプレートのフォーマットは
template_name { [some_data] }
私の目標は、ファイルを1行ずつ解析することです。テンプレートに遭遇したときはいつでも、それに応じて処理します。
私の最初のアプローチは、行に開始または終了のブレースが含まれているかどうかをチェックすることでした。中括弧の場合は、テンプレート名を確認します。
ここでの問題は、開き括弧がテンプレート名と同じ行にある必要がないことです。それだけでなく
テンプレート名 { [some_data] }
そのため、「中かっこが存在する」という条件を使用すると、後者の形式を使用するファイルでは機能しません。
多くの言語でも中かっこが使用されています(ただし、スクリプト自体をいつ解析するかはわかりません)。テンプレート名を正確に取得する方法を知っている人がいるのではないかと思っていました(または他の言語では、関数名にしてください。ただし、検索するキーワードはありません)
Pythonを使用している場合は、 PyParsing を使用することを検討する必要があります。私はこれを何年もの間大成功で使用しています。
Pyparsingモジュールは、従来のLex/yaccアプローチや正規表現の使用と比較して、単純な文法を作成および実行するための代替アプローチです。 pyparsingモジュールは、クライアントコードがPython code ...で直接文法を構築するために使用するクラスのライブラリを提供します...
次に、pyparsingソリューションの外観を示します。
from pyparsing import *
LBRACE,RBRACE,LBRACK,RBRACK,SEMI = map(Suppress,'{}[];')
TEMPLATE = Keyword("template")
ident = Word(alphas, alphanums+"_")
uuid = Regex(r'<[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}>')
integer = Word(nums)
arrayDim = LBRACK + (integer|ident) + RBRACK
baseType = oneOf("Word DWORD FLOAT DOUBLE CHAR UCHAR BYTE STRING CSTRING UNICODE")
ARRAY = Keyword("array")
typeRef = baseType | ident
memberDefn = Group(ARRAY + typeRef("type") + ident("name") +
ZeroOrMore(arrayDim)("dims") + SEMI |
typeRef("type") + ident("name") + SEMI)
templateDefn = (TEMPLATE + ident("name") + LBRACE +
Optional(uuid)("uuid") +
ZeroOrMore(memberDefn)("members") +
RBRACE)
sample = """
some stuff...
template Mesh {
<3D82AB44-62DA-11cf-AB39-0020AF71E433>
DWORD nVertices;
array Vector vertices[nVertices];
DWORD nFaces;
array MeshFace faces[nFaces][4];
}
more stuff...
"""
for tplt in templateDefn.searchString(sample):
print tplt.dump()
for mbr in tplt.members:
print mbr.dump(indent=' ')
print tplt.name, tplt.uuid
プリント:
['template', 'Mesh', '<3D82AB44-62DA-11cf-AB39-0020AF71E433>', ['DWORD', 'nVertices'], ['array', 'Vector', 'vertices', 'nVertices'], ['DWORD', 'nFaces'], ['array', 'MeshFace', 'faces', 'nFaces', '4']]
- members: [['DWORD', 'nVertices'], ['array', 'Vector', 'vertices', 'nVertices'], ['DWORD', 'nFaces'], ['array', 'MeshFace', 'faces', 'nFaces', '4']]
- name: Mesh
- uuid: <3D82AB44-62DA-11cf-AB39-0020AF71E433>
['DWORD', 'nVertices']
- name: nVertices
- type: DWORD
['array', 'Vector', 'vertices', 'nVertices']
- dims: ['nVertices']
- name: vertices
- type: Vector
['DWORD', 'nFaces']
- name: nFaces
- type: DWORD
['array', 'MeshFace', 'faces', 'nFaces', '4']
- dims: ['nFaces', '4']
- name: faces
- type: MeshFace
Mesh <3D82AB44-62DA-11cf-AB39-0020AF71E433>
しないでくださいまだ別の悪いパーサーを書いてください。レクサー/パーサー(例: [〜#〜] ply [〜#〜] )を見て、適切に実行します。それはあなたにとって苦痛が少なく、ずっとユーザーにとって苦痛が少ないでしょう。