1) トークナイザー、つまり文字ストリームを解析し、それを識別子のリスト、OpeningBrace、ClosingBrace、EqualSign、および SemiColon に変換する関数を作成します。コメントとスペースは破棄されます。正規表現を使用して実行できます。
2) 簡単なパーサーを書きます。最初の Identifier と OpeningBrace をスキップします。
パーサーは、識別子の後に EqualSign または OpeningBrace のいずれか、または ClosingBrace が続くことを想定しています。
2.1) EqualSign の場合、識別子とセミコロンが続く必要があります。2.2) OpeningBrace の場合、パーサーを再帰的に呼び出します。2.3) ClosingBrace の場合、再帰呼び出しから戻ります。
2.1 の処理で、任意の方法で dict に目的のデータを入力します。囲んでいるブロックの名前を識別子の前に付けることができます。
{"Main.SubSection.VariableName1": VariableValue1}
これは、トークナイザーの後に呼び出されるパーサーのプロトタイプ コードです。文字が識別子を表す文字列をスキャンします。セパレータは={} です。最後のトークンは$でなければなりません。
def Parse(String, Prefix= "", Nest= 0):
global Cursor
if Nest == 0:
Cursor= 0
# Scan the input string
while String[Cursor + 0].isalpha():
# Identifier, starts an Assignment or a Block (Id |)
if String[Cursor + 1] == "=":
# Assignment, lookup (Id= | Id;)
if String[Cursor + 2].isalpha():
if String[Cursor + 3] == ";":
# Accept the assignment (Id=Id; |)
print Nest * " " + Prefix + String[Cursor] + "=" + String[Cursor + 2] + ";"
Cursor+= 4
elif String[Cursor + 1] == "{":
# Block, lookup (Id{ | )
print Nest * " " + String[Cursor] + "{"
Cursor+= 2
# Recurse
Parse(String, Prefix + String[Cursor - 2] + "::", Nest + 4)
else:
# Unexpected token
break
if String[Cursor + 0] == "}":
# Block complete, (Id{...} |)
print (Nest - 4) * " " + "}"
Cursor+= 1
return
if Nest == 0 and String[Cursor + 0] == "$":
# Done
return
print "Syntax error at", String[Cursor:], ":("
Parse("C{D=E;X{Y=Z;}F=G;}H=I;A=B;$")
実行すると、次のように出力されます。
C{
C::D=E;
X{
C::X::Y=Z;
}
C::F=G;
}
H=I;
A=B;
ネスティングを検出したことを証明します。print ステートメントを任意の処理に置き換えます。