Skip to content

Commit 980a4d3

Browse files
committed
Add better option display
1 parent 9e541d4 commit 980a4d3

9 files changed

Lines changed: 147 additions & 42 deletions

File tree

.idea/workspace.xml

Lines changed: 39 additions & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main/java/ko/carbonel/compiler/config/Config.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public class Config {
3838
private static final String OPERATION = "OPERATION";
3939
private static final String OP_PARSE = "PARSE";
4040
private static final String OP_LEX = "LEX";
41+
private static final String ALL_OPTIONS = "ALL_OPTIONS";
4142
private static final Config instance = new Config();
4243
private final Map<String, Boolean> flags = new HashMap<>();
4344
private final Map<String, String> params = new HashMap<>();
@@ -114,6 +115,10 @@ public boolean doSyntaxDebug() {
114115
return flags.get(SYNTAX_DEBUG);
115116
}
116117

118+
public boolean allOptions() {
119+
return flags.get(ALL_OPTIONS);
120+
}
121+
117122
public Language.Values getLang() {
118123
return Arrays.stream(Language.Values.values())
119124
.filter(it -> Objects.equals(it.getName(), params.get(LANG)))
@@ -159,6 +164,7 @@ private void initDefaultConfigs() {
159164
flags.put(TABLE_ALIGN_LEFT, false);
160165
flags.put(FORCE_ASCII, false);
161166
flags.put(SYNTAX_DEBUG, false);
167+
flags.put(ALL_OPTIONS, false);
162168
params.put(LANG, Language.Values.TEACHER.getName());
163169
params.put(SORT_FUN, START_AWARE_SORT);
164170
params.put(INPUT_FILE, "");

src/main/java/ko/carbonel/compiler/exception/parser/UnexpectedTokenError.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public UnexpectedTokenError(FileLocation start, FileLocation end, Token peek, St
2121

2222
private static String buildMessage(Token peek, String from, Set<TokenType> options) {
2323
return "Unexpected " + Utils.getTokenDescription(peek) + (Config.get().doSyntaxDebug() ? " while matching " + from : "") + ".\n" +
24-
"Valid options are " + Config.get().getActiveLang().translate(options);
24+
"Valid options: " + Config.get().getActiveLang().translate(options);
2525
}
2626

2727
public UnexpectedTokenError(FileLocation location, Token peek, String from, Set<TokenType> options) {

src/main/java/ko/carbonel/compiler/representation/TokenTypeGroup.java

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,29 @@
22

33
import ko.carbonel.Pair;
44

5-
import java.util.Arrays;
6-
import java.util.HashSet;
7-
import java.util.List;
8-
import java.util.Set;
5+
import java.util.*;
6+
import java.util.stream.Collectors;
97

108
import static ko.carbonel.compiler.representation.TokenType.*;
119

1210
public enum TokenTypeGroup {
1311
LITERAL(INT_DATA, STR_DATA, CHR_DATA, TRUE, FALSE, NULL),
14-
OPERATOR(PLUS, MINUS, TIMES, DIVIDE, MOD, EQ, NEQ, GT, LT, LEQ, GEQ, AND, OR, NOT),
15-
TYPE(STR, BOOL, INT, CHR, ARRAY, VOID),
16-
CONTROL(IF, ELSE, WHILE);
12+
UNARY_OPERATOR(PLUS, MINUS, NOT),
13+
BINARY_NUMERIC_OPERATOR(PLUS, MINUS, TIMES, DIVIDE, MOD, EQ, NEQ, GT, LT, LEQ, GEQ),
14+
BINARY_LOGICAL_OPERATOR(AND, OR),
15+
PRIMITIVE(STR, BOOL, INT, CHR),
16+
CONTROL(IF, ELSE, WHILE, RETURN, SEMI_COLON);
1717

1818
public static Pair<Set<TokenTypeGroup>, Set<TokenType>> getGroups(Set<TokenType> t) {
19-
Set<TokenTypeGroup> groups = new HashSet<>();
20-
Set<TokenType> types = new HashSet<>();
21-
t.forEach(type -> {
22-
TokenTypeGroup group = getGroup(type);
23-
if (group != null) groups.add(group);
24-
else types.add(type);
25-
});
26-
return new Pair<>(groups, types);
19+
Map<TokenTypeGroup, Long> groupCount = t.stream().map(TokenTypeGroup::getGroup).filter(Objects::nonNull)
20+
.collect(Collectors.groupingBy(group -> group, Collectors.counting()));
21+
Set<TokenTypeGroup> completeGroups = groupCount.entrySet().stream() // Get groups that have all types
22+
.filter(entry -> entry.getValue() == entry.getKey().types.size())
23+
.map(Map.Entry::getKey)
24+
.collect(Collectors.toSet());
25+
// Add all remaining token types to types
26+
Set<TokenType> types = t.stream().filter(type -> !completeGroups.contains(TokenTypeGroup.getGroup(type))).collect(Collectors.toSet());
27+
return new Pair<>(completeGroups, types);
2728
}
2829

2930
public Set<TokenType> types() {

src/main/java/ko/carbonel/compiler/runner/Runner.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ protected static void init(String[] args) {
2222

2323
public void start() {
2424
inputFileName = Config.get().getParam(Config.INPUT_FILE);
25+
if (!inputFileName.endsWith(".rs")) {
26+
System.out.println(TermFont.commented("WARNING: ") + "Input file does not end with .rs");
27+
}
2528
outputStream = Config.get().getOutputStream();
2629
}
2730

src/main/java/ko/carbonel/compiler/runner/language/ENLanguage.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,10 @@ public String description() {
6363
public String translate(TokenTypeGroup t) {
6464
return switch (t) {
6565
case LITERAL -> "Literal";
66-
case OPERATOR -> "Operator";
67-
case TYPE -> "Type";
66+
case UNARY_OPERATOR -> "Unary Operator";
67+
case BINARY_NUMERIC_OPERATOR -> "Binary Numeric Operator";
68+
case BINARY_LOGICAL_OPERATOR -> "Binary Boolean Operator";
69+
case PRIMITIVE -> "Primitive";
6870
case CONTROL -> "Control statement";
6971
};
7072
}

src/main/java/ko/carbonel/compiler/runner/language/Language.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package ko.carbonel.compiler.runner.language;
22

33
import ko.carbonel.Pair;
4+
import ko.carbonel.compiler.config.Config;
45
import ko.carbonel.compiler.representation.TokenType;
56
import ko.carbonel.compiler.representation.TokenTypeGroup;
67

8+
import java.util.List;
79
import java.util.Set;
810
import java.util.stream.Collectors;
911
import java.util.stream.Stream;
@@ -22,13 +24,22 @@ public interface Language {
2224
String translate(TokenType t);
2325
String translate(TokenTypeGroup t);
2426
default String translate(Set<TokenType> t) {
27+
if (Config.get().allOptions()) {
28+
return t.stream().map(TokenType::name)
29+
.collect(Collectors.joining(", "));
30+
}
2531
Pair<Set<TokenTypeGroup>, Set<TokenType>> grouping = TokenTypeGroup.getGroups(t);
26-
return Stream.concat(
32+
return naturalJoin(grouping);
33+
}
34+
private String naturalJoin(Pair<Set<TokenTypeGroup>, Set<TokenType>> grouping) {
35+
List<String> list = Stream.concat(
2736
grouping.l().stream().map(this::translate),
2837
grouping.r().stream().map(this::translate)
29-
).collect(Collectors.joining(", "));
38+
).toList();
39+
if (list.size() == 1)
40+
return list.get(0);
41+
return String.join(", ", list.subList(0, list.size() - 1)) + " or " + list.get(list.size() - 1);
3042
}
31-
3243
enum Values {
3344
TEACHER("teacher"), ENGLISH("en");
3445
final String name;

src/main/java/ko/carbonel/compiler/runner/language/TeacherLanguage.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,10 @@ public String description() {
6363
public String translate(TokenTypeGroup t) {
6464
return switch (t) {
6565
case LITERAL -> "Literal";
66-
case OPERATOR -> "Operador";
67-
case TYPE -> "Tipo";
66+
case UNARY_OPERATOR -> "Operador unario";
67+
case BINARY_NUMERIC_OPERATOR -> a() ? "Operador binario numerico" : "Operador binario numérico";
68+
case BINARY_LOGICAL_OPERATOR -> "Operador binario booleano";
69+
case PRIMITIVE -> "Tipo";
6870
case CONTROL -> "Sentencia de control";
6971
};
7072
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package ko.carbonel.compiler.representation;
2+
3+
import ko.carbonel.Pair;
4+
import org.junit.jupiter.api.Assertions;
5+
import org.junit.jupiter.api.DisplayName;
6+
import org.junit.jupiter.params.ParameterizedTest;
7+
import org.junit.jupiter.params.provider.Arguments;
8+
import org.junit.jupiter.params.provider.MethodSource;
9+
10+
import java.util.Set;
11+
import java.util.stream.Stream;
12+
13+
import static ko.carbonel.compiler.representation.TokenType.*;
14+
import static ko.carbonel.compiler.representation.TokenTypeGroup.*;
15+
16+
class TokenTypeGroupTest {
17+
@DisplayName("Test Token Types are Grouped Correctly")
18+
@ParameterizedTest(name = "{index}: {0} {1} {2}")
19+
@MethodSource("getTestArguments")
20+
public void test(Set<TokenType> in, Set<TokenTypeGroup> groups, Set<TokenType> remainder) {
21+
Pair<Set<TokenTypeGroup>, Set<TokenType>> result = getGroups(in);
22+
Assertions.assertEquals(groups, result.l());
23+
Assertions.assertEquals(remainder, result.r());
24+
}
25+
26+
public static Stream<Arguments> getTestArguments() {
27+
return Stream.of(
28+
Arguments.of(
29+
Set.of(INT_DATA),
30+
Set.of(),
31+
Set.of(INT_DATA)
32+
),
33+
Arguments.of(
34+
Set.of(INT_DATA, CHR_DATA),
35+
Set.of(),
36+
Set.of(INT_DATA, CHR_DATA)
37+
),
38+
Arguments.of(
39+
Set.of(INT_DATA, CHR_DATA, STR_DATA, NULL, TRUE, FALSE),
40+
Set.of(LITERAL),
41+
Set.of()
42+
),
43+
Arguments.of(
44+
Set.of(INT_DATA, CHR_DATA, STR_DATA, NULL, TRUE, FALSE, INT),
45+
Set.of(LITERAL),
46+
Set.of(INT)
47+
),
48+
Arguments.of(
49+
Set.of(INT_DATA, CHR_DATA, STR_DATA, NULL, TRUE, FALSE, INT, PLUS),
50+
Set.of(LITERAL),
51+
Set.of(INT, PLUS)
52+
),
53+
Arguments.of(
54+
Set.of(INT_DATA, CHR_DATA, STR_DATA, NULL, TRUE, FALSE, INT, PLUS, MINUS, NOT),
55+
Set.of(LITERAL, UNARY_OPERATOR),
56+
Set.of(INT)
57+
)
58+
);
59+
}
60+
}

0 commit comments

Comments
 (0)