I spun a new math expression parser off of my generic parser and it is elite. It supports all possible math constants and functions and I was even able to include modulus support. It's barely 80 lines after removing comments and unnecessary whitespace (other than new line).
My method this time was way smarter. First I removed all whitespace. Then I found every + and - symbol that was a polarity operator and replaced it with a POS or NEG token. Finally, I sequesters all parenthetical groups. Doing all that turns the expression into a script. As an example
-ceil(1.5)+-6
would become
NEG:ceil$ROUND1+NEG:6
If there is any confusion regarding $ROUND1... Lib[$ROUND1] would equal 1.5 from the example above but it can be any valid math expression.
From there it's simple
1) split expression on operators [+-/*%] to array
2) iterate array splitting each index on : and $
3) determine polarity or null
4) determine lib name or null
5) if lib name determine func or null
6) if lib name compile(lib[name])
7) if lib name... if func apply func
8] if not lib name apply numeric or constant
9) regardless of lib name apply polarity (if any)
10) loop operator stack inside operator priority loop applying match operators to left side value stack index.
11) slice last used operator from operator stack
12) slice right side value from value stack
The end result is the first (and now only) value of the value stack is the numeric result of the expression...cake.
I do 99% of this in one procedural loop.
Next step is to tie the math parser and object parser together so objects can contain math expressions. I will also need to upgrade my reference system a little so references can be injected into expressions.
My method this time was way smarter. First I removed all whitespace. Then I found every + and - symbol that was a polarity operator and replaced it with a POS or NEG token. Finally, I sequesters all parenthetical groups. Doing all that turns the expression into a script. As an example
-ceil(1.5)+-6
would become
NEG:ceil$ROUND1+NEG:6
If there is any confusion regarding $ROUND1... Lib[$ROUND1] would equal 1.5 from the example above but it can be any valid math expression.
From there it's simple
1) split expression on operators [+-/*%] to array
2) iterate array splitting each index on : and $
3) determine polarity or null
4) determine lib name or null
5) if lib name determine func or null
6) if lib name compile(lib[name])
7) if lib name... if func apply func
8] if not lib name apply numeric or constant
9) regardless of lib name apply polarity (if any)
10) loop operator stack inside operator priority loop applying match operators to left side value stack index.
11) slice last used operator from operator stack
12) slice right side value from value stack
The end result is the first (and now only) value of the value stack is the numeric result of the expression...cake.
I do 99% of this in one procedural loop.
Next step is to tie the math parser and object parser together so objects can contain math expressions. I will also need to upgrade my reference system a little so references can be injected into expressions.
Comment