separating out the top-level interpreter from the lexer