В REPL добавлен вывод функций, переменных и всего исходника

This commit is contained in:
Victor 2016-08-01 19:45:14 +03:00
parent e326cb7d5d
commit c9249e8577
2 changed files with 143 additions and 44 deletions

View File

@ -1,6 +1,5 @@
package com.annimon.ownlang;
import com.annimon.ownlang.exceptions.LexerException;
import com.annimon.ownlang.exceptions.StoppedException;
import com.annimon.ownlang.parser.Beautifier;
import com.annimon.ownlang.parser.Lexer;
@ -11,10 +10,10 @@ import com.annimon.ownlang.parser.SourceLoader;
import com.annimon.ownlang.parser.Token;
import com.annimon.ownlang.parser.ast.Statement;
import com.annimon.ownlang.parser.visitors.FunctionAdder;
import com.annimon.ownlang.utils.Repl;
import com.annimon.ownlang.utils.TimeMeasurement;
import java.io.IOException;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.TimeUnit;
/**
@ -22,7 +21,7 @@ import java.util.concurrent.TimeUnit;
*/
public final class Main {
private static final String VERSION = "1.2.0";
public static final String VERSION = "1.2.0";
private static String[] ownlangArgs = new String[0];
@ -97,7 +96,7 @@ public final class Main {
case "-r":
case "--repl":
repl();
Repl.main(new String[0]);
return;
case "-l":
@ -193,46 +192,6 @@ public final class Main {
}
}
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 (StoppedException ex) {
// skip
} catch (Exception ex) {
Console.handleException(Thread.currentThread(), ex);
}
buffer.setLength(0);
}
scanner.close();
}
private static class Options {
boolean showTokens, showAst, showMeasurements;
boolean lintMode;

View File

@ -0,0 +1,140 @@
package com.annimon.ownlang.utils;
import com.annimon.ownlang.Console;
import com.annimon.ownlang.Main;
import com.annimon.ownlang.exceptions.LexerException;
import com.annimon.ownlang.exceptions.StoppedException;
import com.annimon.ownlang.lib.Functions;
import com.annimon.ownlang.lib.UserDefinedFunction;
import com.annimon.ownlang.lib.Variables;
import com.annimon.ownlang.parser.Lexer;
import com.annimon.ownlang.parser.Parser;
import com.annimon.ownlang.parser.Token;
import com.annimon.ownlang.parser.ast.BlockStatement;
import com.annimon.ownlang.parser.ast.Statement;
import com.annimon.ownlang.parser.visitors.PrintVisitor;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Scanner;
import java.util.stream.Collectors;
public final class Repl {
private static final String
HELP = ":help",
VARS = ":vars",
FUNCS = ":funcs",
SOURCE = ":source",
RESET = ":reset",
EXIT = ":exit";
public static void main(String[] args) {
System.out.println("Welcome to OwnLang " + Main.VERSION + " REPL");
printHelp(false);
final BlockStatement history = new BlockStatement();
final StringBuilder buffer = new StringBuilder();
final Scanner scanner = new Scanner(System.in);
while (true) {
System.out.print((buffer.length() == 0) ? "\n> " : " ");
if (!scanner.hasNextLine()) break;
final String line = scanner.nextLine();
if (EXIT.equalsIgnoreCase(line)) break;
switch (line.toLowerCase(Locale.ENGLISH)) {
case RESET:
buffer.setLength(0);
continue;
case HELP:
printHelp(true);
continue;
case VARS:
printVariables();
continue;
case FUNCS:
printFunctions();
continue;
case SOURCE:
System.out.println(history.accept(new PrintVisitor(), new StringBuilder()));
continue;
}
buffer.append(line).append(System.lineSeparator());
Statement program = null;
try {
final List<Token> tokens = Lexer.tokenize(buffer.toString());
final Parser parser = new Parser(tokens);
program = parser.parse();
if (parser.getParseErrors().hasErrors()) {
continue;
}
program.execute();
} catch (LexerException lex) {
continue;
} catch (StoppedException ex) {
// skip
} catch (Exception ex) {
Console.handleException(Thread.currentThread(), ex);
}
if (program != null) {
history.add(program);
}
buffer.setLength(0);
}
scanner.close();
}
private static void printHelp(boolean full) {
System.out.println("Type in expressions to have them evaluated.");
final List<String> commands = new ArrayList<>();
if (full) {
commands.add(VARS + " - listing variables");
commands.add(FUNCS + " - listing functions");
commands.add(SOURCE + " - listing source");
}
commands.add(HELP + " - show help");
commands.add(RESET + " - clear buffer");
commands.add(EXIT + " - exit REPL");
int maxLength = commands.stream()
.mapToInt(String::length)
.max().getAsInt();
final int maxCols = 2;
final int size = commands.size();
for (int i = 0; i < size; i += maxCols) {
// Pad to max length and print in tab-separatex maxCols columns
System.out.println(commands
.subList(i, Math.min(size, i + maxCols))
.stream()
.map(str -> String.format("%-" + maxLength + "s", str))
.collect(Collectors.joining("\t", " ", ""))
);
}
}
private static void printVariables() {
Variables.variables().entrySet().stream()
.sorted(Map.Entry.comparingByKey())
.forEach(e -> System.out.printf("\t%s = %s%n",
e.getKey(), e.getValue().toString()));
}
private static void printFunctions() {
System.out.println("User functions:");
Functions.getFunctions().entrySet().stream()
.filter(p -> p.getValue() instanceof UserDefinedFunction)
.sorted(Map.Entry.comparingByKey())
.forEach(e -> System.out.printf("\t%s%s%n",
e.getKey(), ((UserDefinedFunction)e.getValue()).arguments));
System.out.println("Library functions:");
Functions.getFunctions().entrySet().stream()
.filter(p -> !(p.getValue() instanceof UserDefinedFunction))
.sorted(Map.Entry.comparingByKey())
.forEach(e -> System.out.printf("\t%s%n", e.getKey()));
}
}