I wrote a reverse polish notation tutorial for Dream In Code almost 2 years ago (wow that’s a long time ago!). The code only parsed for PI, E, numbers, the basic operators (plus, minus, multiply, divide), and the 3 basic trigonometric functions sine, cosine and tangent.

I’ve added more functions to it, and you can download the class here: ReversePolishNotation.cs

You can use the source code in a personal or commercial project. The disclaimer is that it’s given as is, and you’re ultimately responsible for what goes on in your project. Attribution to me (Vincent Tan) or a link to this blog is appreciated, but not necessary. Just do something awesome with it!

The new functions are

- Absolute function
- Arc sine (asin, inverse sine function)
- Arc cosine (acos, inverse cosine function)
- Arc tangent (atan, inverse tangent function)
- Hyperbolic sine (sinh)
- Hyperbolic cosine (cosh)
- Hyperbolic tangent (tanh)
- Square root function
- Sign function

All in all, not very much added. But I’m using regular expressions to parse the input, so the more functions I support, the more complex the regular expression becomes. For example, I have to tell “sin”, “asin” and “sinh” apart. It’s harder because “sin” is a subset of “asin” and “sinh”.

Don’t get it? What if the input is “sing 1”? The parser should output 2 tokens, “sing” and “1”. It shouldn’t output “sin”, “g” and “1” (or “sin” and “g 1”, or whatever weird case that shouldn’t happen).

Anyway, I haven’t been to Dream In Code for a while now… and someone’s commented that the regular expression for detecting the unary minus should be changed. This was the original code (broken up for legibility):

sBuffer = Regex.Replace(sBuffer, @"(?<number>(pi|e|(\d+(\.\d+)?)))\s+MINUS", "${number} -");

This was what that person suggested:

sBuffer = Regex.Replace(sBuffer, @"(?<number>(pi|e|(\d+(\.\d+)?)))\s+\)\s+MINUS\s+\(", "${number} ) - (");

If I understand it correctly, he (or she) wants to catch the situation where the input has something like this:

( 5 ) – ( 3 )

I checked, and my original parsing would indeed fail. I *do* think he overparsed (I made that word up) though. He made the assumption that the next number is also encapsulated in a round bracket. It doesn’t have to. My code will fail for this too:

( 5 ) – 3

The error was in the right round bracket, so the corrected code is

sBuffer = Regex.Replace(sBuffer, @"(?<number>(pi|e|(\d+(\.\d+)?)))\s+(?<bracket>[)]?)\s+MINUS", "${number} ${bracket} -");

Basically, I checked for the existence of the round bracket. Let me take it out for you to see it better:

(?<bracket>[)]?)\s+

Anyway, I’m putting the upgraded RPN code here because I’m going to shut down the site where I put it. I made a playground site called Ragnarok Code (now defunct). After months, I still only have the RPN code up.

Let me just say that writing articles is hard, and takes a non-trivial amount of time. So that site’s been stagnating, which ironically is the very thing I wanted my coding skills to *not* be. *sigh*

So have a play with an implementation of RPN while it’s still up.

P.S. I checked that person’s profile on Dream In Code. Seems like the only thing he did was comment on my tutorial. Wow, it must have bugged him really bad for him to register an account just so he could comment on my tutorial. After about 2 months, there’s no more activity from him. Maybe he got tired of waiting for a reply from me… oops…