# fun with GTK#

Recently I’ve resumed work on a GTK# project I started three years ago: SnazzyCalculator, hosted on Github. I originally started the project out of curiosity about GTK#, and it’s been fun to develop – I know no one needs another calculator tool. I do intend to develop it into what I’ve been calling a wordulator: type in something like “one plus one equals” and it’ll respond “two”. Feel free to laugh, Jon keeps teasing me about it certainly. :P Anyway, what’s been really fun since I’ve resumed development is getting the parser and equation solver to work. I found this awesome tutorial by Eric White on writing a recursive descent parser in C#, and that gave me the bulk of my parser code. I did discover two bugs in his code that I fixed; I’ll share my fixes with you.

`ParserException`

from white space generation

In his `Expression.Produce`

, he has the following:

1 2 3 4 |
return new Expression( Enumerable.Repeat(new WhiteSpace(), whiteSpaceBefore), n, Enumerable.Repeat(new WhiteSpace(), whiteSpaceAfter)); |

This caused a `ParserException`

for me because of the checks in the `Symbol(params Object[] symbols)`

constructor. Basically, `Enumerable.Repeat`

returned an `Enumerable/<CreateRepeatIterator>`

instead of either a `Symbol`

or `IEnumerable<Symbol>`

like the `Symbol`

constructor expected, so `Symbol`

wigged out and threw a `ParserException`

. I ended up adding the following to my `WhiteSpace`

class:

1 2 3 4 5 6 7 8 9 |
public static IEnumerable<Symbol> CreateWhiteSpace(int amount) { List<Symbol> ws = new List<Symbol>(); for (int i=0; i<amount; i++) { ws.Add(new WhiteSpace()); } return (IEnumerable<Symbol>)ws; } |

Then in `Expression.Produce`

, instead of Eric’s code, I had:

1 2 |
return new Expression(WhiteSpace.CreateWhiteSpace(whiteSpaceBefore), n, WhiteSpace.CreateWhiteSpace(whiteSpaceAfter)); |

## Mismatched parentheses

Parsing an expression like `(1+2)\*(2+3)`

resulted in an exception because of the order in which his `NospaceExpression.Produce`

method constructs new `NospaceExpression`

instances. His code was looking for an opening parenthesis and a closing parenthesis first; then, if that didn’t match, checking for an `Expression`

followed by an `InfixOperator`

followed by another `Expression`

. That resulted in it extracting `1+2)\*(2+3`

, i.e. ditching the first and last parentheses, and trying to treat that as an `Expression`

, which it isn’t. I just moved the following chunk of code down a bit, so it came after `return new NospaceExpression(e1, io, e2);`

:

1 2 3 4 5 6 7 8 9 |
if (symbols.First() is OpenParenthesis && symbols.Last() is CloseParenthesis) { Expression e = Expression.Produce(symbols.Skip(1).SkipLast(1)); if (e != null) { return new NospaceExpression(new OpenParenthesis(), e, new CloseParenthesis()); } } |

This results in first trying to find an expression, then some operator that works on two expressions, then a final expression. And since an `Expression`

consists of another `NospaceExpression`

, which can then consist of parentheses surrounding another `Expression`

, you wind up with `(1+2)`

being seen as its own `Expression`

, then `\*`

as an `InfixOperator`

, then finally `(2+3)`

as the last `Expression`

.

After I got the parser working as expected, I had to make it actually do something with its parse – that is, solve the equation. I did that by adding a `Solve`

method to several classes that returned a `double`

representing its value. That was easiest for the `DecimalDigit`

class, since it just returns its own numeric value. I worked up from there, determining what the symbols could be in each class, so I could determine how to take those symbols and produce some `double`

result. A fun part was adding the following method to `InfixOperator`

that returns a function that knows how to solve an equation involving two terms, depending on which operator the `InfixOperator`

contains:

1 2 3 4 5 6 7 8 9 |
public Func<double, double, double> GetSolver() { Symbol sym = ConstituentSymbols[0]; if (sym is Plus) { return (ad1, ad2) => ad1 + ad2; } if (sym is Minus) { return (t1, t2) => t1 - t2; } if (sym is Asterisk) { return (f1, f2) => f1 * f2; } if (sym is ForwardSlash) { return (dividend, divisor) => { if (0 == divisor) { throw new DivideByZeroException(); } return dividend / divisor; }; } if (sym is Caret) { return (t1, t2) => Math.Pow(t1, t2); } return (t1, t2) => { throw new ParserException("Don't know how to solve " + "expression with InfixOperator " + sym.GetType().ToString()); }; } |

So now my SnazzyCalculator calculates, and it seems to do so correctly, following PEMDAS. It correctly reports “ERROR” when you give it a crap equation like `*1.32.34))`

, or you divide by zero. The next step is to write some tests for it, to ensure I don’t accidentally break the parser or solver while tinkering with other bits. I’ve been fiddling with the GUI, and while it looks all right, I don’t like how I’m styling it. I’m applying the fonts and colors programmatically, instead of in the gui.stetic XML file where all the widgets are laid out. It seems like I ought to be able to describe the appearance of each button in the XML somewhere, but I haven’t found any example showing how.