honeytrap.devexercisesinterpreter.javaSettings
Description

28. Interpreter

ReadBehaviouralNothing to write

Giving every rule of a grammar its own class, each able to evaluate itself

This one is for reading. Every file is locked, and Run is the only button.

One class per rule of the grammar, each knowing how to work out its own value. Num is the base case and does nothing. Add and Multiply ask their children and combine the answers. Variable asks the Context. Compose them and you have a tree that mirrors the source it came from and needs no separate evaluator to walk it — eval() on the root is the whole interpreter.

Notice what the Context buys. In Tests.java the same tree is evaluated twice, against x = 5 and then x = 10, and nothing is rebuilt in between — because a Variable holds a name and not a value, and the bindings arrive as an argument rather than being baked into the node. Parse once, evaluate as often as you like.

This one is a demo for a reason you can check by opening the repository. The pattern’s textbook example is a small language evaluated by a tree of nodes, and that is exactly what this site’s Java subset is: src/java/parser.ts builds the tree, src/java/interpreter.ts evaluates it, and the code that ran the tests you are reading is the same shape as the code you are reading. The demo is the toy; the thing running it is the pattern at the size where it earns its keep.

Which is also why there is nothing to grade. The change you would ask for is “add a rule”, and that is one new class implementing Expr — Open/Closed and Visitor already grade adding a case without editing the tree, and they do it more sharply. What makes Interpreter itself is scale: a grammar large enough that one class per rule is the cheapest arrangement, plus the parser that builds the tree, and neither of those fits in a single file you write in a browser.

Run runs Tests.java exactly as it is written. There is nothing to edit and nothing to submit.

  • Ctrl/⌘ + Enter runs the tests