nothingness
nothingness

Reputation: 694

append if element in list

I'm trying to create a parser for program. For example, I entered (what I want)

"(2+3)-4" it will become something like this "(minus, (plus, num 2, num 3),num 4)"

What I've done so far..

"(2+3)-4" I then split it and it becomes list Z = ["(","2","+","3",")","-","4"] then I compared if "-" is a member of Z, if true I append the element "-" into a new list ["-"]

I'm not sure if the way I'm doing is correct, I'm new to Er-lang and struggling quite a lot. If anyone is able to offer me some insight, thanks.

Upvotes: 0

Views: 56

Answers (1)

Steve Vinoski
Steve Vinoski

Reputation: 20014

Consider the following, which returns a tuple-based representation of its input:

parse(Expr) ->
    Elems = re:split(Expr, "([-+)(])", [{return,list}]),
    parse(lists:filter(fun(E) -> E /= [] end, Elems), []).
parse([], [Result]) ->
    Result;
parse([], [V2,{op,Op},V1|Tacc]) ->
    parse([], [{Op,V1,V2}|Tacc]);
parse(["("|Tail], Acc) ->
    parse(Tail, [open|Acc]);
parse([")"|Tail], [Op,open|TAcc]) ->
    parse(Tail, [Op|TAcc]);
parse(["+"|Tail], Acc) ->
    parse(Tail, [{op,plus}|Acc]);
parse(["-"|Tail], Acc) ->
    parse(Tail, [{op,minus}|Acc]);
parse([V2|Tail], [{op,Op},V1|Tacc]) ->
    parse(Tail, [{Op,V1,{num,list_to_integer(V2)}}|Tacc]);
parse([Val|Tail], Acc) ->
    parse(Tail, [{num,list_to_integer(Val)}|Acc]).

The first function, parse/1, splits the expression along the + and - operators and parentheses, preserving these in the resulting list. It then filters that list to remove empty elements, and passes it with an empty accumulator to parse/2.

The parse/2 function has eight clauses, described below:

  • The first two handle the case when the parsed input list has been exhausted. The second of these handles the case where multiple elements in the accumulator need to be collapsed into a single tuple consisting of operator and operands.
  • The next two handle clauses parentheses. When we see an open parenthesis, we push an atom open into the accumulator. Upon seeing the matching close parenthesis, we expect to see an operation tuple and the atom open in the accumulator, and we replace them with just the tuple.
  • Clauses 5 and 6 handle + and - respectively. Each just pushes a {op,Operator} tuple into the accumulator, where Operator is either the atom plus or the atom minus.
  • The final two clauses handle values. The first one handles the case where the accumulator holds a value and an op tuple, which gets replaced with a full operation tuple consisting of the atom plus or minus followed by two num tuples each holding integer operands. The last clause just handles plain values.

Putting this in a module p, compiling it, and running it in an Erlang shell yields the following:

1> p:parse("2+3").
{plus,{num,2},{num,3}}
2> p:parse("(2+3)-4").
{minus,{plus,{num,2},{num,3}},{num,4}}

Upvotes: 2

Related Questions