Revised Interpreter
Learning Objectives
- You know how to use the lexer and parser in an interpreter.
- You know of type promotion in Dart.
Now that we have the lexer and parser in place, we can revise the interpreter that we initially hacked together to use the lexer and parser. Now, instead of storing the program lines as strings, we store them as statements — i.e., as the result from the parser. Then, when iterating over the program lines, we can evaluate the statements in the correct order and with the correct context.
The revised interpreter looks as follows.
import "lexer.dart";
import "parser.dart";
import "statements.dart";
class Interpreter {
Map<int, Statement> programLines = {};
Map<String, num> variables = {};
List<String> interpret(String code) {
final lexer = Lexer(code);
final parser = Parser(lexer.tokenize());
programLines = parser.parse();
List<int> lineNumbers = programLines.keys.toList()..sort();
List<String> outputLines = [];
for (var lineNumber in lineNumbers) {
Statement statement = programLines[lineNumber]!;
if (statement is PrintStatement) {
String output = statement.execute(variables);
outputLines.add(output);
} else {
statement.execute(variables);
}
}
return outputLines;
}
}
One of the perhaps surprising changes is checking for the type of the statement when executing them. This is done in order to handle possible return values from the statement — in our case, the PrintStatement
returns the string that is printed.
As you notice, we do not need to explicitly cast the statement to the correct type when checking the type of the statement. This is because Dart automatically promotes the type of the variable to the correct type when checking the type of the variable.
As we already implemented tests to the program when hacking things together, we can use the existing tests to see if the interpreter works as expected. Running the command dart test test/basic_interpreter_test.dart
shows that all tests pass.
00:00 +6: All tests passed!
Yay! We have a working interpreter that can interpret the BASIC code we have written so far. Next, we will add GOTO
and IF
statements to the interpreter.