-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathTokenScanner.java
More file actions
150 lines (134 loc) · 4.16 KB
/
TokenScanner.java
File metadata and controls
150 lines (134 loc) · 4.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
class TokenScanner {
private final String source;
private final List<Token> tokens = new ArrayList<>();
private static final Map<String, TokenType> keywords;
private static int left_parentheses = 0;
private static int right_parentheses = 0;
// Define a hashmap that saves the compiler's keywords
static {
keywords = new HashMap<>();
keywords.put("AND", TokenType.AND);
keywords.put("NOT", TokenType.NOT);
keywords.put("OR", TokenType.OR);
keywords.put("IMPLIES", TokenType.IMPLIES);
keywords.put("EQUIVALENT", TokenType.EQUIVALENT);
keywords.put("TRUE", TokenType.TRUE);
keywords.put("FALSE", TokenType.FALSE);
}
private int start = 0;
private int current = 0;
private int line = 1;
// Constructor that takes the source expression
TokenScanner(String source) {
this.source = source;
}
// Loops through the source string
List<Token> scanTokens() {
// Group the whole expression as (P (NOT P)) to handle errors
tokens.add(new Token(TokenType.LEFT_PAREN, "(", line));
while (!isAtEnd()) {
start = current;
scanToken();
}
tokens.add(new Token(TokenType.RIGHT_PAREN, ")", line));
// adds and EOF token at the end to indicate that end of tokens
tokens.add(new Token(TokenType.EOF, "", line));
if (left_parentheses != right_parentheses) {
Main.reportError(line, "Scanner", source + " has unbalanced parentheses.");
}
return tokens;
}
private void scanToken() {
char c = advance();
switch (c) {
case '(': addToken(TokenType.LEFT_PAREN); left_parentheses++; break;
case ')': addToken(TokenType.RIGHT_PAREN); right_parentheses++; break;
case 'P':
addToken(TokenType.LEFT_PAREN);
addToken(TokenType.IDENTIFIERS);
addToken(TokenType.RIGHT_PAREN);
break;
case 'Q':
addToken(TokenType.LEFT_PAREN);
addToken(TokenType.IDENTIFIERS);
addToken(TokenType.RIGHT_PAREN);
break;
case 'S':
addToken(TokenType.LEFT_PAREN);
addToken(TokenType.IDENTIFIERS);
addToken(TokenType.RIGHT_PAREN);
break;
case '/':
if (match('/')) {
while (peek() != '\n' && !isAtEnd()) advance();
} else {
Main.reportError(line, "Scanner", source + " has an invalid token.");
break;
}
break;
case ' ':
case '\t': break;
default:
if (isAlpha(c)) {
checkKeywork();
}
else {
Main.reportError(line, "Scanner", source + " has an invalid token.");
break;
}
break;
}
}
// May change this to accomodate all placeholders for statements
private void checkKeywork() {
while (isAlpha(peek())) advance();
String text = source.substring(start, current);
TokenType type = keywords.get(text);
if (type == null){
Main.reportError(line, "Scanner", source + " has an invalid token.");
}
if(type == TokenType.TRUE){
addToken(TokenType.LEFT_PAREN);
addToken(type);
addToken(TokenType.RIGHT_PAREN);
} else if(type == TokenType.FALSE){
addToken(TokenType.LEFT_PAREN);
addToken(type);
addToken(TokenType.RIGHT_PAREN);
} else {
addToken(type);
}
}
private boolean isAlpha(char c) {
return (c >= 'A' && c <= 'Z');
}
// matches the next character for a token
private boolean match(char expected) {
if (isAtEnd()) return false;
if (source.charAt(current) != expected) return false;
current++;
return true;
}
// checks for the current character
private char peek() {
if (isAtEnd()) return '\0';
return source.charAt(current);
}
// returns if current is at the end
private boolean isAtEnd() {
return current >= source.length();
}
// moves the current while returns the character
private char advance() {
return source.charAt(current++);
}
// adds token
private void addToken(TokenType type) {
String text = source.substring(start, current);
tokens.add(new Token(type, text, line));
}
}