2015-05-18 17:07:40 +03:00
|
|
|
package com.annimon.ownlang;
|
|
|
|
|
2016-03-04 20:21:31 +02:00
|
|
|
import com.annimon.ownlang.exceptions.LexerException;
|
2015-05-18 17:07:40 +03:00
|
|
|
import com.annimon.ownlang.parser.Lexer;
|
|
|
|
import com.annimon.ownlang.parser.Parser;
|
2016-02-19 12:20:20 +02:00
|
|
|
import com.annimon.ownlang.parser.SourceLoader;
|
2015-05-18 17:07:40 +03:00
|
|
|
import com.annimon.ownlang.parser.Token;
|
2015-05-20 14:59:16 +03:00
|
|
|
import com.annimon.ownlang.parser.ast.Statement;
|
2015-06-29 20:50:59 +03:00
|
|
|
import com.annimon.ownlang.parser.visitors.AssignValidator;
|
|
|
|
import com.annimon.ownlang.parser.visitors.FunctionAdder;
|
2015-05-25 23:20:10 +03:00
|
|
|
import java.io.IOException;
|
2015-05-18 17:07:40 +03:00
|
|
|
import java.util.List;
|
2016-03-04 20:21:31 +02:00
|
|
|
import java.util.Scanner;
|
2016-02-19 11:42:29 +02:00
|
|
|
import java.util.concurrent.TimeUnit;
|
2015-05-18 17:07:40 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @author aNNiMON
|
|
|
|
*/
|
|
|
|
public final class Main {
|
2016-03-04 20:21:31 +02:00
|
|
|
|
|
|
|
private static final String VERSION = "1.1.0";
|
2015-05-18 17:07:40 +03:00
|
|
|
|
2015-05-25 23:20:10 +03:00
|
|
|
public static void main(String[] args) throws IOException {
|
2016-01-19 18:25:19 +02:00
|
|
|
if (args.length == 0) {
|
2016-02-25 23:10:51 +02:00
|
|
|
try {
|
|
|
|
run(SourceLoader.readSource("program.own"), true, true, true);
|
|
|
|
} catch (IOException ioe) {
|
2016-03-04 20:21:31 +02:00
|
|
|
System.out.println("OwnLang version " + VERSION + "\n\n" +
|
2016-02-25 23:10:51 +02:00
|
|
|
"Usage: ownlang [options]\n" +
|
|
|
|
" options:\n" +
|
|
|
|
" -f, --file [input] Run program file. Required.\n" +
|
2016-03-04 20:21:31 +02:00
|
|
|
" -r, --repl Enter to a REPL mode\n" +
|
2016-02-25 23:10:51 +02:00
|
|
|
" -a, --showast Show AST of program\n" +
|
|
|
|
" -t, --showtokens Show lexical tokens\n" +
|
|
|
|
" -m, --showtime Show elapsed time of parsing and execution");
|
|
|
|
}
|
2016-01-19 18:25:19 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-02-19 11:42:29 +02:00
|
|
|
boolean showTokens = false, showAst = false, showMeasurements = false;
|
2016-01-19 18:25:19 +02:00
|
|
|
String input = null;
|
|
|
|
for (int i = 0; i < args.length; i++) {
|
|
|
|
switch (args[i]) {
|
|
|
|
case "-a":
|
|
|
|
case "--showast":
|
|
|
|
showAst = true;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case "-t":
|
|
|
|
case "--showtokens":
|
|
|
|
showTokens = true;
|
|
|
|
break;
|
|
|
|
|
2016-02-19 11:42:29 +02:00
|
|
|
case "-m":
|
|
|
|
case "--showtime":
|
|
|
|
showMeasurements = true;
|
|
|
|
break;
|
|
|
|
|
2016-03-04 20:21:31 +02:00
|
|
|
case "-r":
|
|
|
|
case "--repl":
|
|
|
|
repl();
|
|
|
|
return;
|
|
|
|
|
2016-01-19 18:25:19 +02:00
|
|
|
case "-f":
|
|
|
|
case "--file":
|
|
|
|
if (i + 1 < args.length) {
|
2016-02-19 12:20:20 +02:00
|
|
|
input = SourceLoader.readSource(args[i + 1]);
|
2016-01-19 18:25:19 +02:00
|
|
|
i++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
input = args[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (input == null) {
|
|
|
|
throw new IllegalArgumentException("Empty input");
|
|
|
|
}
|
2016-02-19 11:42:29 +02:00
|
|
|
run(input, showTokens, showAst, showMeasurements);
|
2016-01-19 18:25:19 +02:00
|
|
|
}
|
|
|
|
|
2016-02-19 11:42:29 +02:00
|
|
|
private static void run(String input, boolean showTokens, boolean showAst, boolean showMeasurements) {
|
|
|
|
final TimeMeasurement measurement = new TimeMeasurement();
|
|
|
|
measurement.start("Tokenize time");
|
2016-02-19 16:56:05 +02:00
|
|
|
final List<Token> tokens = Lexer.tokenize(input);
|
2016-02-19 11:42:29 +02:00
|
|
|
measurement.stop("Tokenize time");
|
2016-01-19 18:25:19 +02:00
|
|
|
if (showTokens) {
|
|
|
|
for (int i = 0; i < tokens.size(); i++) {
|
|
|
|
System.out.println(i + " " + tokens.get(i));
|
|
|
|
}
|
2015-05-18 17:07:40 +03:00
|
|
|
}
|
|
|
|
|
2016-02-19 11:42:29 +02:00
|
|
|
measurement.start("Parse time");
|
2016-02-14 21:03:28 +02:00
|
|
|
final Parser parser = new Parser(tokens);
|
|
|
|
final Statement program = parser.parse();
|
2016-02-19 11:42:29 +02:00
|
|
|
measurement.stop("Parse time");
|
2016-01-19 18:25:19 +02:00
|
|
|
if (showAst) {
|
|
|
|
System.out.println(program.toString());
|
|
|
|
}
|
2016-02-14 21:03:28 +02:00
|
|
|
if (parser.getParseErrors().hasErrors()) {
|
|
|
|
System.out.println(parser.getParseErrors());
|
|
|
|
return;
|
|
|
|
}
|
2015-06-29 20:50:59 +03:00
|
|
|
program.accept(new FunctionAdder());
|
|
|
|
program.accept(new AssignValidator());
|
2016-01-24 19:38:19 +02:00
|
|
|
try {
|
2016-02-19 11:42:29 +02:00
|
|
|
measurement.start("Execution time");
|
2016-01-24 19:38:19 +02:00
|
|
|
program.execute();
|
|
|
|
} catch (Exception ex) {
|
2016-02-19 17:26:35 +02:00
|
|
|
Console.handleException(Thread.currentThread(), ex);
|
2016-02-19 11:42:29 +02:00
|
|
|
} finally {
|
|
|
|
if (showMeasurements) {
|
|
|
|
measurement.stop("Execution time");
|
2016-02-19 13:27:54 +02:00
|
|
|
System.out.println("======================");
|
2016-02-19 11:42:29 +02:00
|
|
|
System.out.println(measurement.summary(TimeUnit.MILLISECONDS, true));
|
|
|
|
}
|
2016-01-24 19:38:19 +02:00
|
|
|
}
|
|
|
|
}
|
2016-03-04 20:21:31 +02:00
|
|
|
|
|
|
|
private static void repl() {
|
|
|
|
final StringBuilder buffer = new StringBuilder();
|
|
|
|
final Scanner scanner = new Scanner(System.in);
|
|
|
|
System.out.println("Welcome to OwnLang " + VERSION + " REPL\n"
|
|
|
|
+ "Type in expressions to have them evaluated.\n"
|
|
|
|
+ "Type :reset to clear buffer.\n"
|
|
|
|
+ "Type :exit to exit REPL.");
|
|
|
|
while (true) {
|
|
|
|
System.out.print((buffer.length() == 0) ? "\n> " : " ");
|
|
|
|
|
|
|
|
if (!scanner.hasNextLine()) break;
|
|
|
|
|
|
|
|
final String line = scanner.nextLine();
|
|
|
|
if (":exit".equalsIgnoreCase(line)) break;
|
|
|
|
if (":reset".equalsIgnoreCase(line)) {
|
|
|
|
buffer.setLength(0);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
buffer.append(line).append(System.lineSeparator());
|
|
|
|
try {
|
|
|
|
final List<Token> tokens = Lexer.tokenize(buffer.toString());
|
|
|
|
final Parser parser = new Parser(tokens);
|
|
|
|
final Statement program = parser.parse();
|
|
|
|
if (parser.getParseErrors().hasErrors()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
program.execute();
|
|
|
|
} catch (LexerException lex) {
|
|
|
|
continue;
|
|
|
|
} catch (Exception ex) {
|
|
|
|
Console.handleException(Thread.currentThread(), ex);
|
|
|
|
}
|
|
|
|
buffer.setLength(0);
|
|
|
|
}
|
|
|
|
scanner.close();
|
|
|
|
}
|
2015-05-18 17:07:40 +03:00
|
|
|
}
|