3

いくつかのパーサーとレクサー生成ツール (Lex と Bison に似ていますが、C# 用) を使用して、後で評価できる抽象構文ツリーに文字列を解析するプログラムを生成しています。

私はエラー回復を行いたいと思っていました (つまり、生成された抽象文ツリーで、欠落しているトークンなどがあることを報告します)。生成された文法を構造化するために 2 つのアプローチを念頭に置いていましたが、どちらのアプローチが優れているか、より柔軟であるか、または競合が発生しないか疑問に思っていました (.y および .lex ファイルは、電卓の記述に基づいて生成されます)。

電卓の説明により、ユーザーは端末/正規表現と演算子の配置、および結合性を指定できます。次のようなものです:

grammar.AddTerminal("Plus", "\\+").
    AddNonTerminal(new NonTerminal("Add", Associativity.LeftToRight).
        AddTerminal("Expression").
        AddTerminal("Plus").
        AddTerminal("Expression"));

(優先順位は、TerminalNonTerminalが追加された順序で指定されます。"Add"は、リフレクションを介して発見されたメソッドの名前です。基本的には、抽象構文ツリーで演算子を呼び出すものを NonTerminal に伝えます。)


アプローチ 1 : (任意の式に対して空のルールを許可する)

S -> E
E -> E + T
E -> T
T -> T * P
T -> P
P -> (E)
P -> (E [error]
P -> a
P -> @ [error]

a端末です。 @空です。


アプローチ 2 : (開始ルールに空のルールのみを許可する)

S -> E
S -> @ [error]
E -> + [error]
E -> T + [error]
E -> + T [error]
E -> E + T
E -> T
T -> * [error]
T -> * P [error]
T -> P * [error]
T -> T * P
T -> P
P -> (E)
P -> (E [error]
P -> a

これは、各アプローチを使用した悪い入力の左端の導出を示す例です。


入力: (a +


アプローチ 1 :

S
E
T
P
(E
(E + T
(T + T
(P + T
(a + T
(a + P
(a +

アプローチ 2 :

S
E
T
P
(E
(T +
(P +
(a +

A -> A - Bアプローチ 2 のコーディングははるかに困難です (減算/単項負の演算子を検討してください。単純に減算を見て、最初にそれを取り出してAエラーを報告することはできません。A -> - Bこれは単項演算子に有効であるためです)。私は今朝、アプローチ 2 をコーディングしました。文法の問題があり、アプローチ 1 のように空のルールを使用すると、コードの観点から物事がはるかに単純になることがわかりましたが、私の主な関心事は、プログラマーが電卓の説明を次のように作成するときに、どのアプローチが文法の問題を最小限に抑えるかです。上で説明した。

4

1 に答える 1

4

この質問はしばらく前から出回っており、このトピックの初心者がよく訪れるトピックをカバーしています。学部でコンパイラのコースを受講したことがある人は、これが簡単な答えや単一の答えがない質問の 1 つであることを知っていることがよくあります。お気付きかもしれませんが、同じトピックについて 2 つの質問があり、どちらにも回答がありません。他の誰かが投稿した別の質問は、これが難しい理由を説明する文献へのポインタで回答されました。

それは50年以上にわたって存続している問題です。初期の会議論文、コースの教科書、博士論文、そして (今日の) など、時間をかけて文献を調べると、これが間違った質問SOであるという事実への言及が定期的に見られます。(または、問題への間違ったアプローチ)。

何年にもわたってコーステキストからサンプルを取っているだけです(私の本棚からランダムに選択しました):

Gries, D. (1970) Error Recovery and Correction - An Introduction to the Literature, In Compiler Construction, An advanced Course edit by Bauer, FL & Eickel, J., Springer Verlag, pp.627-638.
Gries, D. (1971) Compiler Construction for Digital Computers、Wiley、pp.320-326。
Aho, AV, Ullman, JD (1977)コンパイラ設計の原則、Addison Wesley、pp.397-405。
Bornat, R. (1979) 『Compilers and Writing Compilers』、Macmillan、pp.251-252。
Hanson, D. (1995)リターゲット可能なCコンパイラ: 設計と実装、Addison-Wesley、pp.140-146。
Grune, D., Bal, HE, Jacobs, CJH & Langendoen, KG (2000)最新のコンパイラ設計、Wiley、pp.175-184。
Aho, AV, Lam, MS, Sethi, R., Ullman, JD (2007) Compilers: Principles, Techniques, & Tools , Pearson, Addison-Wesley, pp.283-296.

これらはすべて(40年以上にわたって)、あなたの質問は間違ったツールを間違って使用したり、間違った方向に進んだりすることに関するものであることに同意しています. 「ここからは行けない」と言おうとしているのだと思います。どこかから始めるべきです。

さらに深く知りたい場合は、博士論文全体があります。

Charles, P. (1991) A Practical method for Constructing Efficient LALR(k) Parser with Automatic Error Recovery、ニューヨーク大学

うまくいけば、将来この質問に再びアクセスする人のために、回答のプレースホルダーがあります.


コメントから、CPPG から派生した MPPG を使用していることに注意してください。誰もがこれらを使用しているわけではないため、これらのツールへのリンクをいくつか示します。

Managed Babel Systems Essentials
Garden Points パーサー ジェネレーター
Irony .NET コンパイラ コンストラクション キット
初めての Visual Studio 言語サービスの作成

于 2015-04-21T16:08:21.307 に答える