So far we have implemented the interpreter, but the script was written directly in the program source. This article allows you to read and execute a script from a text file.
This article is a continuation of "Supporting static method calls".
Read the script from a file and make sure you want to run it.
For example, there is a text file that describes the script below. This script is a program that outputs Fibonacci numbers from 0 to 6. Run this script and aim to output the Fibonacci number.
fibo.txt
function fibonacci(n) {
if (n == 0) {
return 0
} else if (n == 1) {
return 1
} else {
return fibonacci(n - 2) + fibonacci(n - 1)
}
}
var i = 0
while (i <= 6) {
var n = fibonacci(i)
println("f(" + i.toString() + ") -> " + n.toString())
i = i + 1
}
Get the file name from the command line argument and read the file contents. Introduce a class that processes the read contents in the order of lexical analysis (Lexer), parser (Parser), and interpreter (Interpreter). Introduce a driver class that performs such processing.
Move on to implementation. Let's take a look at the installed driver classes in order.
Driver.java
An implementation of Driver.java.
The constructor for the Driver class. Instantiate and prepare lexical analysis (Lexer), parser (Parser), and interpreter (Interpreter) for later processing.
Driver.java
public class Driver {
Lexer lexer;
Parser parser;
Interpreter interpreter;
public Driver() {
lexer = new Lexer();
parser = new Parser();
interpreter = new Interpreter();
}
This is the ʻexecute () method that executes the script. The ʻexecute ()
method executes the following operations in order.
The variables
field variable holds the value of the post-execution interpreter global variable that results in the execution.
The ʻexception` field variable holds the exception thrown during execution.
Driver.java
public Map<String, Interpreter.Variable> variables;
public Exception exception;
public int execute(String[] args) {
try {
validateArguments(args);
String path = args[0];
String text = readText(path);
variables = run(text);
return 0;
} catch (Exception e) {
exception = e;
System.err.println(e.getMessage());
return -1;
}
}
The validateArguments ()
method that validates command line arguments.
One command line argument is specified to verify that it is a file.
If the verification result is incorrect, an exception is thrown.
Driver.java
public static final String ARGS_NULL = "Arguments were null.";
public static final String NO_ARGS = "No Arguments.";
public static final String FILE_NOT_FOUND = "File not found.: ";
public static final String PATH_NOT_FILE = "The path was not a file.: ";
public void validateArguments(String[] args) throws Exception {
if (args == null) {
throw new Exception(ARGS_NULL);
}
if (args.length != 1) {
throw new Exception(NO_ARGS);
}
String path = args[0];
File f = new File(path);
if (!f.exists()) {
throw new FileNotFoundException(FILE_NOT_FOUND + path);
}
if (!f.isFile()) {
throw new Exception(PATH_NOT_FILE + path);
}
}
A readText
method that reads and returns the file contents.
It is assumed that the character code of the file contents is UTF-8.
Driver.java
public String readText(String path) throws IOException {
return new String(Files.readAllBytes(Paths.get(path)), StandardCharsets.UTF_8);
}
A run ()
method that executes a script of the file contents.
Lexical analysis (Lexer), parser (Parser), and interpreter (Interpreter) are processed in this order.
Driver.java
public Map<String, Interpreter.Variable> run(String text) throws Exception {
exception = null;
variables = null;
List<Token> tokens = lexer.init(text).tokenize();
List<Token> blk = parser.init(tokens).block();
return interpreter.init(blk).run();
}
The main ()
method, which is the starting point at runtime.
Instantiate the Driver class and execute the script with the ʻexecute ()` method.
Driver.java
public static void main(String[] args) {
Driver driver = new Driver();
int status = driver.execute(args);
System.exit(status);
}
}
That's all for the implementation.
It looks like the script file fibo.txt was executed with the built Driver.class. It is assumed that Driver.class and fibo.txt are in the same directory.
$ java Driver fibo.txt
f(0) -> 0
f(1) -> 1
f(2) -> 1
f(3) -> 2
f(4) -> 3
f(5) -> 5
f(6) -> 8
Thank you very much.
The full source is available here.
Calc https://github.com/quwahara/Calc/tree/article-21-driver/Calc/src/main/java
Recommended Posts