Working off of Peter Norvig's (How to Write a (Lisp) Interpreter (in Python)) tutorial, I appropriated it to illustrate how to build toy implementation of a concatenative language. If you're unfamiliar with concatenative languages, the concatenative.org wiki is a good place to start. The canonical example is the Joy language, and a very impressive recent development is the Factor language, which we will be making a minimalistic implementation of.
Like in lis.py, language elements are represented by their Python counterparts. Quotations are Python lists, strings are words, and everything else is coerced into a number. Since this implementation won't be using strings, the grammar is very simple: any sequence of non-whitespace characters is treated as a word. Whitespace is significant in the sense that it delimits words.
Since our evaluator will actually work on Python data types, we can define our evaluator first, and leave the tokenizing and parsing for a little later. Forgive the wall of code, but here is the interpreter in its entirety.
Above contains the definition of a very simple standard set of words, and the evaluate method. The evaluate method does most of the work, taking a Python list as input and treating it like an abstract syntax tree. To see it in action, not much work needs to be done:
>>> r = Runtime()
>>> r.evaluate([[1, 2, '+'], 'call'])
The above will execute, first pushing the quotation to the stack, then having the call word evaluate it, leaving 3 on the stack. Running it through Python is fine,
Now, the tokenizer and parser. The tokenizer is simple: according to our grammar it is legal to split by whitespace, so that's what it does. The parser takes the tokens and builds a Python list in the same structure as the Factor code. For example, the input [ some-word ] call will be returned as [['some-word'], 'call'].