我只是碰到了this post,它很優雅。如何將infix轉換爲erlang中的postfix?
但它沒有考慮到不同運營商的優先級。
例如*
的優先級高於+
。
所以1+2*(3+2)
應轉換爲1 2 3 2 + * +
怎麼做二郎考慮的優先問題考慮在內?
我只是碰到了this post,它很優雅。如何將infix轉換爲erlang中的postfix?
但它沒有考慮到不同運營商的優先級。
例如*
的優先級高於+
。
所以1+2*(3+2)
應轉換爲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編寫解析器?」答案是雙重的:要麼使用leex + yecc,要麼使用基於解析器組合器和/或遞歸下降的解析器。尤其對於語法來說這很簡單。
p(Str) ->
Tree = parse(Str),
rpn(Tree),
io:format("~n").
這只是格式。
你可以從我的靈感Erlang Programming Exercise 3-8 solution。所有的手寫詞法分析器,解析器和「編譯器」都是後綴代碼。
編輯:對不起,我看練習3-8有明確的包圍,所以它不解決運算符的優先級。你將不得不修改解析器來處理它。
我看不到處理優先級的邏輯.. –
正如我所暗示的,優先級是由解析器處理的。它與「如何在RPN表示法中格式化分析樹」這個問題是分開的,這就是上面所說的。您可以查看遞歸下降,這是您的表達式爲LL(1)語法的一種方法。 –
我需要有很多額外的運算符,這些運算符在erlang中不存在,所以我需要手動指定優先級,而不是erlang的默認設置。 –