如何在erlang中将中缀转换为后缀?

时间:2011-08-30 11:18:15

标签: erlang

我刚遇到this post,它非常优雅。

但它没有考虑到不同运营商的优先级。

e.g。 *的优先级高于+

因此1+2*(3+2)应转换为1 2 3 2 + * +

如何在erlang中考虑优先级问题?

2 个答案:

答案 0 :(得分: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").

这只是格式化。

答案 1 :(得分:0)

你可以从我的Erlang Programming Exercise 3-8 solution获得灵感。有所有手写的词法分析器,解析器和“编译器”到后缀代码。

编辑抱歉,我看到练习3-8有明确的包围,因此无法解决操作员优先级问题。您必须修改解析器才能处理它。