我刚遇到this post,它非常优雅。
但它没有考虑到不同运营商的优先级。
e.g。 *
的优先级高于+
。
因此1+2*(3+2)
应转换为1 2 3 2 + * +
如何在erlang中考虑优先级问题?
答案 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有明确的包围,因此无法解决操作员优先级问题。您必须修改解析器才能处理它。