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

如何在erlang中将中缀转换为后缀?,erlang,Erlang,我只是偶然发现,它很优雅 但它没有考虑到不同运营商的优先级 e、 g.*的优先级高于+ 所以1+2*(3+2)应该转换为1+2++ 考虑到优先级问题,如何在erlang中执行此操作?以下是一种方法,它滥用了erlang术语的内置解析器。您可以通过yecc或递归下降来编写自己的解析器,但为了简单起见,我将坚持使用Erlang解析器 -module(foo). -compile(export_all). 声明一个模块,导出其中的所有内容。如果你想用这个,这是一个糟糕的形式。而是尽量减少导出

我只是偶然发现,它很优雅

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

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

所以
1+2*(3+2)
应该转换为
1+2++


考虑到优先级问题,如何在erlang中执行此操作?

以下是一种方法,它滥用了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").

这只是格式化。

你可以从我的设计中得到启发。有所有手写词法分析器,解析器和“编译器”后缀代码


编辑:对不起,我看到练习3-8有明确的括号,所以它不能解决运算符优先级问题。您必须修改解析器来处理它。

正如我所暗示的,优先级由解析器处理。它实际上与“如何用RPN表示法格式化解析树”的问题是分开的,这正是上面所做的。您可以查找递归下降,这是对表达式所在的LL(1)语法执行此操作的一种方法。我需要有许多在erlang中不存在的附加运算符,因此我需要手动指定优先级,而不是erlang的默认设置。然后查看leex+yecc。它是为这种东西而建的。去拿一本关于解析的书,它会帮助你理解如何做。如果我要做一种新的编程语言,我只会使用leex/yecc工具链……转换为后缀并没有那么难,尽管也不容易。。