Reputation: 694
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
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:
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.+
and -
respectively. Each just pushes a {op,Operator}
tuple into the accumulator, where Operator
is either the atom plus
or the atom minus
.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