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

发布于 2024-12-02 08:26:15 字数 332 浏览 0 评论 0原文

我刚刚看到这篇文章,相当优雅。

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

例如,* 的优先级高于+

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

考虑到优先级问题,如何在 erlang 中做到这一点?

I just came across this post,it's quite elegant.

But it's not taking into account the priority of different operators.

e.g. * has higher priority than +.

So 1+2*(3+2) should be converted to 1 2 3 2 + * +

How to do it in erlang taking the priority issue into account?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

驱逐舰岛风号 2024-12-09 08:26:15

这是一种滥用 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").

这只是格式化。

Here is a way to do it which abuses the built-in parser for Erlang terms. You could write your own parser via yecc or recursive descent, but for the simplicity, I'll stick with the Erlang-parser.

  -module(foo).
  -compile(export_all).

Declare a module, export everything from it. This is bad form if you want to use this. Rather minimize the export to p/1.

 parse(Str) ->    
     {ok, Tokens, _} = erl_scan:string(Str ++ "."),
     {ok, [E]} = erl_parse:parse_exprs(Tokens),
     E.

This function abuses the Erlang parser so we can get a parse tree of Erlang tokens.

 rpn({op, _, What, LS, RS}) ->
     rpn(LS),
     rpn(RS),
     io:format(" ~s ", [atom_to_list(What)]);
 rpn({integer, _, N}) ->
     io:format(" ~B ", [N]).

RPN output is to do a post-order tree-walk traversal. So we basically walk the Left hand and right hand side of the tree and then output ourselves as a node. The order of "parenthesis" is stored abstractly in the tree itself. The priority is handled by the Erlang parser. You could easily do this via a recursive descent parser if you want. But that is a different question to the point of "How do I write parsers in Erlang?" The answer is twofold: Either you use leex+yecc or you use a parser based upon parser combinators and/or recursive descent. Especially for a grammar this simple.

 p(Str) ->
      Tree = parse(Str),
      rpn(Tree),
      io:format("~n").

This is just formatting.

不语却知心 2024-12-09 08:26:15

您可以从我的 Erlang 编程练习 3-8 解决方案。有所有手写的词法分析器、解析器和后缀代码的“编译器”。

编辑:抱歉,我发现练习 3-8 有明确的括号,因此它无法解决运算符优先级问题。您必须修改解析器才能处理它。

You can get inspired by mine Erlang Programming Exercise 3-8 solution. There is all handwritten lexer, parser and "compiler" to postfix code.

Edit: Sorry, I see Exercise 3-8 has explicit bracketing so it doesn't solve operator priority. You would have to modify parser to handle it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文