How to write a math expression parser (in JavaScript)

Is2PidGuy
4 min readJan 28, 2019

--

Here goes my first post.

It’s not that difficult to write a math expression parser. I’ll share how to develop such program step by step starting with the most basic expression parser. For simplicity, let us assume expression does not contain any whitespace characters.

Step one — parsing plus separated expression

We need to be able to parse 123 + 58 + 38

Let’s say we would like to parse the expression. Assuming there are no spaces in between the operators and the operands, we first split the expression string by “+” string. Thus we obtain the array [“123”, “58”, “38”]. Then, we accumulate all the integers and return the result. Easy !!

Simple expression parser — parse “123 + 58 + 38”

Step two — adding multiplication support

We need to be able to parse 12 * 5+ 5 * 32 + 3

Since * binds tightly than + operator. We first split by +. We obtain the array [“12*5”,“5*32”,“3”]. Thus, we obtain expressions comprising of only * operator and its operands. For each expression in the array, we execute function that will multiply all those values using new function called parseMultiplicationSeparatedExpression. Since the problem is the same as initial problem we started, except the operator is * instead of +, we can write the function easily.

Step three — adding subtraction support

We need to be able to parse 12 * 5 - 5 * 32 + 3.

Okay, this part is also easy. The generic pattern is, first split by the lowest priority operator, then by the next high priority operator and so on.

For our above expression, we can split by either plus or minus operator first, since both have the same precedence / priority. So we obtain

[“12*5–5*32”, “3”], after splitting by plus. In the next step, we split by minus and finally by * operator. We need functions that are able to parse each resultant strings. So, please see the code below.

Okay, this will sum up the ideas necessary for simple parser. We starting with operator with lowest priority and go up in ascending order of priority. We split strings according to the binding with the operator we are looking at. Each step will call parser function for simplified expression obtained containing one less operator. At the last step, we accumulate the result using proper accumulator function and initial value.

Step four — adding parenthesis support

We need to be able to parse 12 * 5–(5 * (32 + 4)) + 3.

This may seem a little complicated at first. But we can use what we have done earlier and extend the solution to be able to parse the above expression.

Previously we just use the javascript string split function to split by operator. Now, it won’t work because expression can contain + operator inside parentheses and it would split that too.

Say our expression is this, 12 * 5–(5 * (32 + 4)) + 3

After splitting by ‘+’ operator, we want [“12*5-(5*(32 + 4))”, “3”].

That is, our new split function will have to make the expression inside parentheses atomic. Let’s visualize it,

The above expression will look like this for our split function, 12 * 5– a + 3,

where, a = (5 * (32 + 4))

So how to design such split function that will work with parentheses also?

For that, we have to be able to know if at any position, we are surrounded by parentheses. For example, in 12 * 5–(5 * (32 + 4)) + 3, 12 is not surrounded by parentheses, but 32 is. For that, we use a simple counter. We loop from left to right, if we encounter (, we increase counter, if we encounter ), we decrease the counter. So effectively, we’ll know if we are inside parentheses if the braces count is 0.

Our split function will look as below:

The above function takes expression and operator as argument. It will work same as str.split(‘+’) except it will consider parentheses also. Every time we encounter operator supplied in argument and if braces count is 0, we split at that position as shown in line 12 of above code.

After the design of split function, rest will look easy. For the above expression,

12 * 5–(5 * (32 + 4)) + 3

Split by + = [“12*5-(5*32+4))”, “3”]

now take the first string, split by minus = [“12*5”, “(5*32+4)”]

“12*5” will be reduced to 60.

(5*32+4) after splitting by ‘*’ will give (5*32+4). Thus, we obtain an expression inside braces. We remove the braces and obtain the expression 5*32+4, then we call our function parsePlusSeperatedExpression. This is a recursive call, since we previously started with the same function.

This is the full expression parser.

Each expression inside parentheses is a sub task that will be solved by the main function parsePlusSeparatedExpression. Essentially a recursive call.

This recursive call is done at the bottom. This can be visualized with the tree below.

So, I hope it is easy to understand. Thank you for reading.

Here is my youtube video for part one,

https://www.youtube.com/watch?v=6YyvyvBAZr8&pbjreload=10

--

--