1

私はfunのための言語のようなjavascriptのためのコンパイラを書いています。別名私は車輪について学んでいるので、私は自分のために1つを作って、すべてを見つけようとしていますが、今は詰まってしまいました。メソッド呼び出しを後置記法に変換するには?

シンプルインミックス式を解析するとき、シャンティングヤードアルゴリズムは素晴らしいものです。私は接頭辞と接尾辞演算子に対してもこのアルゴリズムを拡張する方法を理解することができましたし、単純な関数を解析することもできました。例えば

2+3*a(3,5)+b(3,5)2 3 <G> 3 5 a() * + <G> 3 5 b() +

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

関数名がただ1つのトークンであれば、その直後にかっこが付いていれば関数記号としてマークすることができます。プロセス中に関数シンボルが出たら、演算子スタックにプッシュし、パラメータの変換が終わったらポップアウトします。

これまでのところこれが動作しています。

ただし、メンバー関数を持つオプションを追加すると、.演算子が使用されます。物事はもっとトリッキーです。例えば、a.b.c(12)+d.e.f(34)を変換したいのですが、a.b.cd.e.fが関数なので、関数であるとマークすることはできません。このような式でパーサを起動すると、結果はa 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)

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

答えて

0

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

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


--artem

+1

'.'は' + 'と同じように1つのトークンの演算子です。 – delnan

+0

@delnanが正しいです。通常の演算子のようにドットを扱う必要があります。 – mahdix

0

(私はこの質問にはまだ生きて見ました。私はそれのためのソリューションを自分自身を発見しました。)

まずI脅威つのトークンとして(...)[...]表現し、それらを展開します(再帰的に)。次に、関数呼び出しと配列添字を検出します。カッコで囲まれたトークンの前に中置演算子がない場合、それは関数呼び出しまたは配列添え字です。そこで特別な呼び出し関数またはアクセス演算子を挿入します。この変更で、それは魅力のように動作します。

関連する問題