私はちょうどthis postに出くわしました、それは非常にエレガントです。erlangの後置に埋め込みコードを変換するには?
しかし、異なる演算子の優先順位を考慮していません。
+
よりも高い優先度を持つのが*
です。
ので1+2*(3+2)
を考慮に優先課題を取るErlangでそれを行うにはどのように1 2 3 2 + * +
に変換する必要がありますか?
私はちょうどthis postに出くわしました、それは非常にエレガントです。erlangの後置に埋め込みコードを変換するには?
しかし、異なる演算子の優先順位を考慮していません。
+
よりも高い優先度を持つのが*
です。
ので1+2*(3+2)
を考慮に優先課題を取るErlangでそれを行うにはどのように1 2 3 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").
これは単なる書式設定です。
あなたは私のErlang Programming Exercise 3-8 solutionからインスピレーションを得ることができます。手書きのレクサー、パーサ、そしてコンパイラの後ろに "コンパイラ"があります。
編集:申し訳ありませんが、演習3-8に明示的なブラケットが付いているので、オペレータの優先順位が解決されません。それを処理するにはパーサーを変更する必要があります。
優先度を扱うロジックが表示されません。 –
私が暗示したように、優先順位はパーサーによって処理されます。実際には、「RPN表記法で構文木をフォーマットするにはどうすればよいのですか」という質問とは別に、これは上記のことです。式があるLL(1)文法のための1つの方法である再帰的降下を調べることができます。 –
私はerlangには存在しない多くの演算子を追加する必要があるので、erlangのデフォルト設定ではなく、手動で優先順位を指定する必要があります。 –