5

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?

Community
  • 1
  • 1
Je Rog
  • 5,675
  • 8
  • 39
  • 47

2 Answers2

2

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.

I GIVE CRAP ANSWERS
  • 18,739
  • 3
  • 42
  • 47
  • 1
    As I hinted, the priority is handled by a parser. It is really separate from the question of "How do I format a parse tree in RPN notation", which is what the above does. You can look up recursive descent which is one way to do it for an LL(1) grammar which your expressions are. – I GIVE CRAP ANSWERS Aug 30 '11 at 12:54
  • I need to have a lot of additional operators that doesn't exist in erlang, so I need to specify the priority manually, not the default settings of erlang. – Je Rog Aug 30 '11 at 12:58
  • Look at leex+yecc then. It is built for this kind of stuff. Go grab a book on parsing as well as it will help you understand how to do it. – I GIVE CRAP ANSWERS Aug 30 '11 at 13:12
  • I'll only use the leex/yecc toolchain if I'm gonna making a new programing language...Converting to postfix is not as hard as that though not easy as well.. – Je Rog Aug 30 '11 at 13:33
0

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.

Hynek -Pichi- Vychodil
  • 26,174
  • 5
  • 52
  • 73