Now the parser can add numbers together [ply]

This is not quite the design recommended by the ply documentation, but I
think it's a nice clean design. The tokenizer returns the values
associated with each token, and the parser consumes those values. In
this case, the value associated with '+' happens to be a function of two
numbers, so that's what we'll return.

If you've already read the parsimonious version of this parser, you'll
notice that PLY allows `expression: expression plus expression` whereas
parsimonious would've gone into an infinite loop on that grammar. This
is a distinction between the LALR grammars used by PLY and the PEG
grammars used by parsimonious.

Note that this uncovered a bug in my decimal-numbers regex. Oops! I
blame PLY for being so regex-oriented. It's definitely not my fault for
making a classic regex mistake. Nope.
Add various operators [ply]

Now you can see what I meant about a nice clean design from returning
functions in the tokenizer. Each operator token returns the associated
function, and the parser just calls it. In a more classic yacc
implementation, the operator tokens would just return their string
representations, and you'd have a big if-elsif-elsif-elsif block where
you look up the behavior associated with the strings.

You may notice that the number rule changed here. Previously a unary '-'
was considered part of the numeric token, whereas now it's a separate
operator. It turns out that with two different ways to interpret the '-'
token, you end up with an ambiguous grammar and the behavior is
unpredictable. Having the unary '-' pass an explicit 0 to the binary
subtraction function is either an elegant workaround or a kludgy hack,
depending on your viewpoint.