-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathScanner.java
More file actions
165 lines (159 loc) · 6.34 KB
/
Scanner.java
File metadata and controls
165 lines (159 loc) · 6.34 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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
import java.util.*;
import java.io.*;
class Scanner {
private Queue<Core> tokenQueue;
private BufferedReader reader;
private Queue<String> idQueue;
private Queue<Integer> constQueue;
// Initialize the scanner and linkedlists for Token, ID, and CONST Queues
Scanner(String filename) {
try{
reader = new BufferedReader(new FileReader(filename));
tokenQueue = new LinkedList<>();
idQueue = new LinkedList<>();
constQueue = new LinkedList<>();
tokenize();
reader.close();
}catch (IOException e){
System.out.println("Error: File not found");
}
}
//Tokenizes all the input at once, and adds them to the TokenQueue via addToken
private void tokenize(){
StringBuilder s = new StringBuilder();
int c;
try{
while((c = reader.read()) != -1){
char ch = (char) c;
//Checks if the current char is a whitespace, ends the stringbuilding sequence and adds the token
if (Character.isWhitespace(ch)){
if(s.length() > 0){
addToken(s.toString());
s = new StringBuilder();
}
//Checks if the current char is a nonletter or digit character and adds it to the TokenQueue if it is
} else if(ch == '+' || ch == '-' || ch == '*' || ch == '/' ||ch == ':'|| ch == '=' || ch == '<' || ch == ';' || ch == '.' || ch == ',' || ch == '(' || ch == ')' || ch == '[' || ch == ']'){
if(s.length() > 0){
addToken(s.toString());
s = new StringBuilder();
}
//Checks if the current nonletter or digit character is specifically a colon. If it is, it checks if the very next character is an equal,
if(ch == ':'){
if(reader.ready()){
reader.mark(2);
c = reader.read();
char specialEqual = (char) c;
if(specialEqual == '='){
reader.reset();
reader.skip(1);
s.append(ch);
s.append(specialEqual);
addToken(s.toString());
s = new StringBuilder();
}else{
addToken(Character.toString(ch));
reader.reset();
}
}else{
addToken(Character.toString(ch));
}
}else{
addToken(Character.toString(ch));
}
} else {
s.append(ch);
}
}
if(s.length()>0){
addToken(s.toString());
}
}catch (IOException e){
System.out.println("Error: Tokenizer failed!");
}
}
//Uses a switch case to match each str, with it's ENUM in the Core class. If the str doesn't match, returns an Error
private Core mapStringToCore(String str){
switch (str) {
case "procedure": return Core.PROCEDURE;
case "begin": return Core.BEGIN;
case "is": return Core.IS;
case "end": return Core.END;
case "if": return Core.IF;
case "else": return Core.ELSE;
case "in": return Core.IN;
case "integer": return Core.INTEGER;
case "return": return Core.RETURN;
case "do": return Core.DO;
case "new": return Core.NEW;
case "not": return Core.NOT;
case "and": return Core.AND;
case "or": return Core.OR;
case "out": return Core.OUT;
case "array": return Core.ARRAY;
case "then": return Core.THEN;
case "while": return Core.WHILE;
case "+": return Core.ADD;
case "-": return Core.SUBTRACT;
case "*": return Core.MULTIPLY;
case "/": return Core.DIVIDE;
case ":=": return Core.ASSIGN;
case "=": return Core.EQUAL;
case "<": return Core.LESS;
case ":": return Core.COLON;
case ";": return Core.SEMICOLON;
case ".": return Core.PERIOD;
case ",": return Core.COMMA;
case "(": return Core.LPAREN;
case ")": return Core.RPAREN;
case "[": return Core.LBRACE;
case "]": return Core.RBRACE;
default:
if (str.matches("[0-9]+")){
int val = Integer.parseInt(str);
if (val >= 0 && val <= 100003){
return Core.CONST;
}else{
System.out.println("Error: CONST " + str + " is not a valid number, or is not in the range of 0 to 100003");
return Core.ERROR;
}
} else if(str.matches("[a-zA-Z][a-zA-Z0-9]*")){
return Core.ID;
} else {
System.out.println("Error: Token "+ str + " is not valid!");
return Core.ERROR;
}
}
}
//After matching str with Core ENUM via mapStringToCore, adds it to the TokenQueue, and then if the token was an ID or CONST, adds it to their respective queues as well.
private void addToken(String str){
Core token = mapStringToCore(str);
tokenQueue.add(token);
if (token == Core.ID){
idQueue.add(str);
}else if(token == Core.CONST){
constQueue.add(Integer.parseInt(str));
}
}
// Advance to the next token
public void nextToken() {
if (!tokenQueue.isEmpty()){
tokenQueue.poll();
}
}
// Return the current token
public Core currentToken() {
if(!tokenQueue.isEmpty()){
return tokenQueue.peek();
}else{
return Core.EOS;
}
}
// Return the identifier string
public String getId() {
return idQueue.poll();
}
// Return the constant value
public int getConst() {
return constQueue.poll();
}
}