Dead-simple grammar that can read natural numbers [parsimonious]

It should be fairly clear what's going on in this grammar: numbers are
any string of text that contains 1 or more digits.

The Calculator class might not be obvious. Parsimonious defines a
NodeVisitor class that's used for walking the AST returned by
Grammar.parse. For each rule in your grammar, you define a method called
visit_<that_rule>. So for our simple grammar with just a rule called
`number`, we define a `visit_number` method on our AST walker. It gets a
"node", which is an object containing the text that the rule matched,
and a list of visited_children, which in this case is empty. We'll see
visited_children play a larger part later.
Parse decimal numbers [parsimonious]

Numbers are now a series of digits, possibly with a . in the middle of
them. This parser doesn't accept inputs like "15." or ".15", which are
arguably valid input. Personally I figure it won't kill the user to type
a 0 once in a while.

generic_visit might need some explanation. parsimonious's NodeVisitors
call generic_visit when the group they're matching doesn't have a
particular name. Rules like the `number` rule, which consists of several
parts, are implicitly transformed into a named rule and several
anonymous rules that're visited by generic_visit. We don't care about
the lower-level matches, just the outermost number, so generic_visit
doesn't need any functionality. However, the default implentation in
NodeVisitor raises a NotImplementedError, so we have to override it with
an empty method.
Add support for negative numbers [parsimonious]

This is a fairly simple change building on the two we already did:
numbers can now have an optional - in front of them, indicating
negation. So far, the extensions we've made to our grammar rules haven't
required any changes in the Calculator--they're all reflected in
Python's `float` method.
Now the parser can add two numbers [parsimonious]

The "plus" rule returns a function that takes two numbers and adds them
together. If you're not familiar with higher-order functions you might
be surprised to see a `return lambda...`, but in fact it fits quite
nicely with what we're doing. In the language we're defining, `+` is a
function of two numbers, so our interpreter transforms the literal
string '+' into the very function it's meant to represent.

The "addition" rule finally makes use of that visited_children argument
we've been ignoring for so long. Looking up at the grammar, we see that
an addition is a number, a plus, and another number. Since the
addition rule refers to other rules, its visited_children is a list of
the return values of the visit methods for the referred-to rules. In
this case, it's a float returned by visit_number, a function returned by
visit_plus, and another float from visit_number. We grab the function
from the middle of the list and call it on the left and right numbers.

visit_expression also uses its visited_children argument, but in this
case it doesn't do much with it. The `expression` rule simply expresses
that you can have either a number or an addition at the topmost level,
so by the time we visit its node, all the work's already been done. We
just keep returning the value calculated in the lower-level rules.

We could simplify our grammar somewhat:
    expression = (number plus number) / number
    plus       = "+"
    number     = "-"? ~"[0-9]+" ("." ~"[0-9]+")?
But this would result in a significantly-more-complicated implementation
in visit_expression.
Allow chaining additions [parsimonious]

Now we have some recursion in our grammar! The `expression` refers to
the `addition` rule, which in turn refers back to the `expression` rule.
Anchoring the `addition` rule with the non-recursing `number` rule on
the left ensures our recursion has a terminus. If we instead define the
`addition` rule as `expression plus expression`, parsimonious runs into
Python's recursion depth limit when trying to parse the input text.
Support various operators [parsimonious]

Note how visit_operation, other than being renamed, is no different from
visit_addition. This is a consequence of making visit_operator (nee
visit_plus) a higher-order function. See, functional programming is
great!

Also take note of the "operators are right-associative" test. This is a
consequence of the decision to define the `operation` rule as `number
operator expression`: The right-hand side of the operator is an
expression, and its evaluated result is what's available to the
operator. It is somewhat harder in Parsimonious to write a
left-associative language.

In the majority of cases, the particular flavor of parser generator you
use isn't too important. This is a case where it matters: parsimonious
generates PEG parsers, for which left-associativity is possible, but
harder, to define. Some parser generators generate LL or LR parsers; the
second letter indicates which "derivation" of the language the parser
uses. An LL parser will tend to generate left-associative languages. An
LR parser will tend to generate right-associative languages. For various
reasons, LR parsers are much more common than LL; thus most programming
languages (including Python) are right-associative.