1

私は楽しみのために言語のような JavaScript のコンパイラを書いています。別名、私はホイールについて学んでいるので、自分用にホイールを作成し、すべてを見つけようとしていますが、今は行き詰まっています.

単純な中置式を構文解析する場合、分路アルゴリズムが優れていることはわかっています。前置演算子と後置演算子についてもこのアルゴリズムを拡張する方法を理解することができ、単純な関数を解析することもできました。

例:2+3*a(3,5)+b(3,5)に変わります2 3 <G> 3 5 a () * + <G> 3 5 b () +

(<G>はスタックにプッシュされるガード トークンであり、戻りアドレスなどを格納します。()必要な量の引数をポップアウトし、戻り時に結果をプッシュするスタックの一番上にある関数を呼び出す call コマンドです。)

関数名が 1 つのトークンにすぎない場合は、その直後に括弧を付ければ関数シンボルとして簡単にマークできます。プロセス中に関数シンボルに遭遇した場合は、それをオペレーター スタックにプッシュし、パラメーターの変換が終了したときにポップアウトします。

これはこれまでのところ機能しています。

しかし、メンバー関数を持つオプションを追加すると、.演算子. 物事はよりトリッキーになります。たとえば、とは関数a.b.c(12)+d.e.f(34)であるため、 I can't mark c と f を関数に変換したいとします。このような式でパーサーを開始すると、結果はどちらが明らかに間違っているかになります。私はそれが正しいように見えることを望みます。しかし、括弧をいくつか追加すると、事態をより複雑にすることができます。または、もう一度呼び出す関数を返す関数を作成します。a.b.cd.e.fa b . <G> 12 c () . d e . <G> 34 f () .<G> 12 a b . c . () <G> 34 d e . f. ()(a.b.c)()f(a,b)(c,d)

これらのトリッキーな状況を処理する簡単な方法はありますか?

4

2 に答える 2

0

あなたのアプローチの問題は、オブジェクトとそのメンバーを で区切られた 2 つの別個のトークンとして扱うことです.。従来のシャント ヤード アルゴリズムは、OOP について何も知らず、関数呼び出しに単一のトークンに依存しています。したがって、問題を解決する最初の方法は、オブジェクト メンバーの呼び出しに 1 つのトークンを使用することです。つまり、全体a.b.cが 1 つのトークンでなければなりません。

問題の別の解決策として、自動パーサー ジェネレーターを参照することもできます。ターゲット言語 (JavaScript) の完全な文法を一連の正式な規則として定義し、パーサーを自動的に生成することができます。人気のあるツールのリストには、さまざまなプログラミング言語でパーサーを生成するツールが含まれています: ANTLR、Bison + Lex、Lemon + Ragel


--アルテム

于 2011-01-14T13:55:08.530 に答える
0

(この質問はまだ生きているのを見ました。私は自分で解決策を見つけました。)

(...)最初にand[...]式を 1 つのトークンとして脅し、必要に応じて (再帰的に) 展開します。次に、関数呼び出しと配列添字を検出します。括弧で囲まれたトークンの前に中置演算子がない場合、それは関数呼び出しまたは配列添字であるため、特別な関数呼び出しまたはアクセス演算子をそこに挿入します。この変更により、魅力的に機能します。

于 2011-03-05T12:06:46.457 に答える