An interpreter is a program that reads and executes code. It is a way to execute code without compiling it. It is a great way to execute code on the fly. It is used in many places like scripting languages, command line tools, etc.
Parts of an Interpreter ( Simplified )
A minimal interpreter can be represented in 3 parts:
- lexer: It reads the code and converts it into tokens.
- parser: It reads the tokens and converts it into an abstract syntax tree (AST).
- evaluator: It reads the AST and executes the code.
Note: There can be more parts like optimizer, IR generator etc. for advanced interpreters.
Representation of code
Let’s take a simple python code to understand the parts of an interpreter.
def add_numbers(a, b):
return a + b
Tokens
Tokens are the smallest unit of a program. It can be a keyword, identifier, operator, etc.
Tokens of the above python code:
def
: keywordadd_numbers
: identifier(
: open parenthesisa
: identifier,
: commab
: identifier)
: close parenthesis:
: colonreturn
: keyworda
: identifier+
: operatorb
: identifierEOF
: end of file
Tokens are the input to the parser to generate the AST.
Abstract Syntax Tree (AST)
It is a tree representation of the code. It is a way to represent the code in a structured way. It is a great way to understand the code and execute it.
AST of the above python code:
FunctionDef
├─ name: "add_numbers"
├─ args: Arguments
│ ├─ arg: "a"
│ └─ arg: "b"
└─ body
└─ Return
└─ BinOp
├─ left: Name "a"
├─ op: Add
└─ right: Name "b"
AST is the input to the evaluator to execute the code.
Evaluator
Evaluator reads the AST and walks through the tree to execute each part of the code.
REPL
REPL stands for Read-Eval-Print-Loop. It is a way to interact with the interpreter. It reads the code, block by block, and executes it.