2011-08-30 49 views

回答

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"). 

這只是格式。

+0

我看不到處理優先級的邏輯.. –

+1

正如我所暗示的,優先級是由解析器處理的。它與「如何在RPN表示法中格式化分析樹」這個問題是分開的,這就是上面所說的。您可以查看遞歸下降,這是您的表達式爲LL(1)語法的一種方法。 –

+0

我需要有很多額外的運算符,這些運算符在erlang中不存在,所以我需要手動指定優先級,而不是erlang的默認設置。 –

0

你可以從我的靈感Erlang Programming Exercise 3-8 solution。所有的手寫詞法分析器,解析器和「編譯器」都是後綴代碼。

編輯:對不起,我看練習3-8有明確的包圍,所以它不解決運算符的優先級。你將不得不修改解析器來處理它。

相關問題