2011-08-30 3 views
5

私はちょうどthis postに出くわしました、それは非常にエレガントです。erlangの後置に埋め込みコードを変換するには?

しかし、異なる演算子の優先順位を考慮していません。

+よりも高い優先度を持つのが*です。

ので1+2*(3+2)を考慮に優先課題を取るErlangでそれを行うにはどのように1 2 3 2 + * +

に変換する必要がありますか?

答えて

2

Erlangの用語の組み込みパーサーを乱用する方法があります。 yeccや再帰的な降下で独自のパーサーを書くこともできますが、簡単にするために、私はErlangパーサーに固執します。

-module(foo). 
    -compile(export_all). 

モジュールを宣言し、モジュールからすべてをエクスポートします。あなたがこれを使いたい場合、これは悪い形式です。むしろ、輸出をp/1に最小限に抑えてください。

parse(Str) ->  
    {ok, Tokens, _} = erl_scan:string(Str ++ "."), 
    {ok, [E]} = erl_parse:parse_exprs(Tokens), 
    E. 

この関数はErlangパーサーを乱用し、Erlangトークンの解析ツリーを取得できます。

rpn({op, _, What, LS, RS}) -> 
    rpn(LS), 
    rpn(RS), 
    io:format(" ~s ", [atom_to_list(What)]); 
rpn({integer, _, N}) -> 
    io:format(" ~B ", [N]). 

RPN出力後のオーダーツリーウォークトラバーサルを行うことです。だから、基本的にツリーの左手と右手を歩いて、ノードとして自分自身を出力します。 「括弧」の順序は、ツリー自体に抽象的に格納されます。優先度はErlangパーサによって処理されます。必要に応じて、再帰的な降下構文解析ツールを使って簡単にこれを行うことができます。しかし、それは「Erlangでパーザを書くにはどうすればいいですか?」という点とは異なる質問です。答えは2つあります:leex + yeccを使うか、パーサーコンビネータや再帰的降下に基づいてパーサーを使うかのどちらかです。特に文法の場合、これは単純です。

p(Str) -> 
     Tree = parse(Str), 
     rpn(Tree), 
     io:format("~n"). 

これは単なる書式設定です。

+0

優先度を扱うロジックが表示されません。 –

+1

私が暗示したように、優先順位はパーサーによって処理されます。実際には、「RPN表記法で構文木をフォーマットするにはどうすればよいのですか」という質問とは別に、これは上記のことです。式があるLL(1)文法のための1つの方法である再帰的降下を調べることができます。 –

+0

私はerlangには存在しない多くの演算子を追加する必要があるので、erlangのデフォルト設定ではなく、手動で優先順位を指定する必要があります。 –

0

あなたは私のErlang Programming Exercise 3-8 solutionからインスピレーションを得ることができます。手書きのレクサー、パーサ、そしてコンパイラの後ろに "コンパイラ"があります。

編集:申し訳ありませんが、演習3-8に明示的なブラケットが付いているので、オペレータの優先順位が解決されません。それを処理するにはパーサーを変更する必要があります。

関連する問題