2

参考までに、ここに私のコードがあります:http://hpaste.org/86949

次の式を解析しようとしています: if (a[1].b[2].c.d[999].e[1+1].f > 3) { }. 再生中のメソッドvarExprは、変数メンバー チェーンを解析する です。

環境

私が解析している言語では、ドットはメンバー変数へのアクセスを指定できます。メンバー変数は別のオブジェクトになる可能性があるため、チェーンを生成できa.b.cます(a.b).c。ドットが関数構成であると想定しないでください。

実装

ロジックは次のようになります。

  • 最初に、before <- many voccすべてのインスタンスvarname .とそれらのオプションの配列式を収集し、単一の識別子のみを残します

  • this <- vtrm残りの識別子と配列式を収集します -- ドットで始まらない唯一の識別子

問題

私は2つの問題を抱えています:

まず、最初の用語 [私には判断できない理由で] は、パーサーがそれを受け入れるために常に角かっこで囲む必要があるようです。つまり、(a[1]).b[2].c...次の用語ではこれは必要ありません。

次に、many vocc解析が停止しません。常に別の識別子と別のドットが必要であり、最後の をキャッチするために式を終了できませんvtrm

問題や頭痛の解決に役立つヒントや解決策を探しています。ありがとう。

4

1 に答える 1

4

実行するvarExprと、入力の次のビットが または と一致するかどうかがチェックされvoccますvtrm

varExpr = do before <- many vocc  -- Zero or more occurrences
             this <- vtrm
             return undefined

問題は、 で一致する入力がvtrmの最初のステップでも一致することですvoccvarExpr実行すると、実行されvocc、実行されvobj、実行されますvtrm

vocc = vobj <* symbol "."
vobj = choice [try vtrm, try $ parens vtrm]

入力を消費せずに失敗すると、解析がmany vocc終了します。voccこれは、vtrmとの両方parens vtrmが失敗した場合に発生します。ただし、many vocc終了後、次に実行するパーサーはvtrm— そしてこのパーサーは確実に失敗します!

vocc入力に ​​a が見つからない場合は、入力を消費せずに失敗します"."。そのためには、 を使用する必要がありますtry

vocc = try $ vobj <* symbol "."

または、vobjvtrm本当に同じ構文にする必要がある場合は、 varExpr を として定義できますvobj `sepBy1` symbol "."

于 2013-05-01T02:08:29.007 に答える