Skip to content

Commit c9249e8

Browse files
committed
В REPL добавлен вывод функций, переменных и всего исходника
1 parent e326cb7 commit c9249e8

File tree

2 files changed

+143
-44
lines changed

2 files changed

+143
-44
lines changed

src/main/java/com/annimon/ownlang/Main.java

Lines changed: 3 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.annimon.ownlang;
22

3-
import com.annimon.ownlang.exceptions.LexerException;
43
import com.annimon.ownlang.exceptions.StoppedException;
54
import com.annimon.ownlang.parser.Beautifier;
65
import com.annimon.ownlang.parser.Lexer;
@@ -11,18 +10,18 @@
1110
import com.annimon.ownlang.parser.Token;
1211
import com.annimon.ownlang.parser.ast.Statement;
1312
import com.annimon.ownlang.parser.visitors.FunctionAdder;
13+
import com.annimon.ownlang.utils.Repl;
1414
import com.annimon.ownlang.utils.TimeMeasurement;
1515
import java.io.IOException;
1616
import java.util.List;
17-
import java.util.Scanner;
1817
import java.util.concurrent.TimeUnit;
1918

2019
/**
2120
* @author aNNiMON
2221
*/
2322
public final class Main {
2423

25-
private static final String VERSION = "1.2.0";
24+
public static final String VERSION = "1.2.0";
2625

2726
private static String[] ownlangArgs = new String[0];
2827

@@ -97,7 +96,7 @@ public static void main(String[] args) throws IOException {
9796

9897
case "-r":
9998
case "--repl":
100-
repl();
99+
Repl.main(new String[0]);
101100
return;
102101

103102
case "-l":
@@ -192,46 +191,6 @@ private static void run(String input, Options options) {
192191
}
193192
}
194193
}
195-
196-
private static void repl() {
197-
final StringBuilder buffer = new StringBuilder();
198-
final Scanner scanner = new Scanner(System.in);
199-
System.out.println("Welcome to OwnLang " + VERSION + " REPL\n"
200-
+ "Type in expressions to have them evaluated.\n"
201-
+ "Type :reset to clear buffer.\n"
202-
+ "Type :exit to exit REPL.");
203-
while (true) {
204-
System.out.print((buffer.length() == 0) ? "\n> " : " ");
205-
206-
if (!scanner.hasNextLine()) break;
207-
208-
final String line = scanner.nextLine();
209-
if (":exit".equalsIgnoreCase(line)) break;
210-
if (":reset".equalsIgnoreCase(line)) {
211-
buffer.setLength(0);
212-
continue;
213-
}
214-
215-
buffer.append(line).append(System.lineSeparator());
216-
try {
217-
final List<Token> tokens = Lexer.tokenize(buffer.toString());
218-
final Parser parser = new Parser(tokens);
219-
final Statement program = parser.parse();
220-
if (parser.getParseErrors().hasErrors()) {
221-
continue;
222-
}
223-
program.execute();
224-
} catch (LexerException lex) {
225-
continue;
226-
} catch (StoppedException ex) {
227-
// skip
228-
} catch (Exception ex) {
229-
Console.handleException(Thread.currentThread(), ex);
230-
}
231-
buffer.setLength(0);
232-
}
233-
scanner.close();
234-
}
235194

236195
private static class Options {
237196
boolean showTokens, showAst, showMeasurements;
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
package com.annimon.ownlang.utils;
2+
3+
import com.annimon.ownlang.Console;
4+
import com.annimon.ownlang.Main;
5+
import com.annimon.ownlang.exceptions.LexerException;
6+
import com.annimon.ownlang.exceptions.StoppedException;
7+
import com.annimon.ownlang.lib.Functions;
8+
import com.annimon.ownlang.lib.UserDefinedFunction;
9+
import com.annimon.ownlang.lib.Variables;
10+
import com.annimon.ownlang.parser.Lexer;
11+
import com.annimon.ownlang.parser.Parser;
12+
import com.annimon.ownlang.parser.Token;
13+
import com.annimon.ownlang.parser.ast.BlockStatement;
14+
import com.annimon.ownlang.parser.ast.Statement;
15+
import com.annimon.ownlang.parser.visitors.PrintVisitor;
16+
import java.util.ArrayList;
17+
import java.util.List;
18+
import java.util.Locale;
19+
import java.util.Map;
20+
import java.util.Scanner;
21+
import java.util.stream.Collectors;
22+
23+
public final class Repl {
24+
25+
private static final String
26+
HELP = ":help",
27+
VARS = ":vars",
28+
FUNCS = ":funcs",
29+
SOURCE = ":source",
30+
RESET = ":reset",
31+
EXIT = ":exit";
32+
33+
public static void main(String[] args) {
34+
System.out.println("Welcome to OwnLang " + Main.VERSION + " REPL");
35+
printHelp(false);
36+
37+
final BlockStatement history = new BlockStatement();
38+
final StringBuilder buffer = new StringBuilder();
39+
final Scanner scanner = new Scanner(System.in);
40+
while (true) {
41+
System.out.print((buffer.length() == 0) ? "\n> " : " ");
42+
43+
if (!scanner.hasNextLine()) break;
44+
45+
final String line = scanner.nextLine();
46+
if (EXIT.equalsIgnoreCase(line)) break;
47+
switch (line.toLowerCase(Locale.ENGLISH)) {
48+
case RESET:
49+
buffer.setLength(0);
50+
continue;
51+
case HELP:
52+
printHelp(true);
53+
continue;
54+
case VARS:
55+
printVariables();
56+
continue;
57+
case FUNCS:
58+
printFunctions();
59+
continue;
60+
case SOURCE:
61+
System.out.println(history.accept(new PrintVisitor(), new StringBuilder()));
62+
continue;
63+
}
64+
65+
buffer.append(line).append(System.lineSeparator());
66+
Statement program = null;
67+
try {
68+
final List<Token> tokens = Lexer.tokenize(buffer.toString());
69+
final Parser parser = new Parser(tokens);
70+
program = parser.parse();
71+
if (parser.getParseErrors().hasErrors()) {
72+
continue;
73+
}
74+
program.execute();
75+
} catch (LexerException lex) {
76+
continue;
77+
} catch (StoppedException ex) {
78+
// skip
79+
} catch (Exception ex) {
80+
Console.handleException(Thread.currentThread(), ex);
81+
}
82+
if (program != null) {
83+
history.add(program);
84+
}
85+
buffer.setLength(0);
86+
}
87+
scanner.close();
88+
}
89+
90+
private static void printHelp(boolean full) {
91+
System.out.println("Type in expressions to have them evaluated.");
92+
final List<String> commands = new ArrayList<>();
93+
if (full) {
94+
commands.add(VARS + " - listing variables");
95+
commands.add(FUNCS + " - listing functions");
96+
commands.add(SOURCE + " - listing source");
97+
}
98+
commands.add(HELP + " - show help");
99+
commands.add(RESET + " - clear buffer");
100+
commands.add(EXIT + " - exit REPL");
101+
102+
int maxLength = commands.stream()
103+
.mapToInt(String::length)
104+
.max().getAsInt();
105+
106+
final int maxCols = 2;
107+
final int size = commands.size();
108+
for (int i = 0; i < size; i += maxCols) {
109+
// Pad to max length and print in tab-separatex maxCols columns
110+
System.out.println(commands
111+
.subList(i, Math.min(size, i + maxCols))
112+
.stream()
113+
.map(str -> String.format("%-" + maxLength + "s", str))
114+
.collect(Collectors.joining("\t", " ", ""))
115+
);
116+
}
117+
}
118+
119+
private static void printVariables() {
120+
Variables.variables().entrySet().stream()
121+
.sorted(Map.Entry.comparingByKey())
122+
.forEach(e -> System.out.printf("\t%s = %s%n",
123+
e.getKey(), e.getValue().toString()));
124+
}
125+
126+
private static void printFunctions() {
127+
System.out.println("User functions:");
128+
Functions.getFunctions().entrySet().stream()
129+
.filter(p -> p.getValue() instanceof UserDefinedFunction)
130+
.sorted(Map.Entry.comparingByKey())
131+
.forEach(e -> System.out.printf("\t%s%s%n",
132+
e.getKey(), ((UserDefinedFunction)e.getValue()).arguments));
133+
134+
System.out.println("Library functions:");
135+
Functions.getFunctions().entrySet().stream()
136+
.filter(p -> !(p.getValue() instanceof UserDefinedFunction))
137+
.sorted(Map.Entry.comparingByKey())
138+
.forEach(e -> System.out.printf("\t%s%n", e.getKey()));
139+
}
140+
}

0 commit comments

Comments
 (0)