-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTokenStream.java
More file actions
218 lines (196 loc) · 5.29 KB
/
Copy pathTokenStream.java
File metadata and controls
218 lines (196 loc) · 5.29 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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
package cop5555sp15;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
/**
* This class holds the tokenize input. It is initialized with the input
* (several constructors provide different options for providing the input) and
* passed to a Scanner which fills in the tokens. The nextToken method is used
* by the parser to retrieve the Tokens.
*
* @author Beverly Sanders
*
*/
public class TokenStream {
char[] inputChars; // input
public final ArrayList<Token> tokens = new ArrayList<Token>(); // holds tokens after scan
/* provide input in char array */
public TokenStream(char[] inputChars) {
this.inputChars = inputChars;
}
/* provide input via a Reader */
public TokenStream(Reader r) {
this.inputChars = getChars(r);
}
/* provide input via a String */
public TokenStream(String inputString) {
int length = inputString.length();
inputChars = new char[length];
inputString.getChars(0, length, inputChars, 0);
}
// reads all the characters in the given reader into a char array.
private char[] getChars(Reader r) {
StringBuilder sb = new StringBuilder();
try {
int ch = r.read();
while (ch != -1) {
sb.append((char) ch);
ch = r.read();
}
} catch (IOException e) {
throw new RuntimeException("IOException");
}
char[] chars = new char[sb.length()];
sb.getChars(0, sb.length(), chars, 0);
return chars;
}
private int pos = 0;
/** returns the next token and increments the position */
public Token nextToken() {
return tokens.get(pos++);
}
/** resets the position in the token stream */
public void reset() {
pos = 0;
}
public String toString() {
StringBuilder sb = new StringBuilder();
for (Token t : tokens) {
sb.append(t.toString());
sb.append('\n');
}
return sb.toString();
}
public static enum Kind {
IDENT,
/* reserved words */
KW_INT, KW_STRING, KW_BOOLEAN, KW_IMPORT, KW_CLASS, KW_DEF, KW_WHILE, KW_IF, KW_ELSE, KW_RETURN, KW_PRINT,
KW_SIZE, KW_KEY, KW_VALUE,
/* boolean literals */
BL_TRUE, BL_FALSE,
/* null literal */
NL_NULL,
/* separators */
DOT, // .
RANGE, // ..
SEMICOLON, // ;
COMMA, // ,
LPAREN, // (
RPAREN, // )
LSQUARE, // [
RSQUARE, // ]
LCURLY, // {
RCURLY, // }
COLON, // :
QUESTION, // ?
ASSIGN, // =
BAR, // |
AND, // &
EQUAL, // ==
NOTEQUAL, // !=
LT, // <
GT, // >
LE, // <=
GE, // >=
PLUS, // +
MINUS, // -
TIMES, // *
DIV, // /
MOD, // %
NOT, // !
LSHIFT, // <<
RSHIFT, // >>
ARROW, // ->
AT, // @
INT_LIT, STRING_LIT,
/* end of file */
EOF,
/* error tokens */
ILLEGAL_CHAR, //a character that cannot appear in that context
UNTERMINATED_STRING, //end of input is reached before the closing "
UNTERMINATED_COMMENT //end of input is reached before the closing */
}
/*
* This is a non-static inner class. Each instance is linked to a instance
* of StreamToken and can access that instance's variables.
*
* Example of token creation where stream is an instance of TokenStream:
* Token t = stream.new Token(SEMI, beg, end, line);
*/
public class Token {
public final Kind kind;
public final int beg;
public final int end;
public final int lineNumber;
public Token(Kind kind, int beg, int end, int lineNumber) {
this.kind = kind;
this.beg = beg;
this.end = end;
this.lineNumber = lineNumber;
}
/* this should only be applied to Tokens with kind==INT_LIT */
public int getIntVal() {
assert kind == Kind.INT_LIT : "attempted to get value of non-number token";
return Integer.valueOf(getText());
}
/* this should only be applied to Tokens with kind==BOOLEAN_LIT */
public boolean getBooleanVal() {
assert (kind == Kind.BL_TRUE || kind == Kind.BL_FALSE) : "attempted to get boolean value of non-boolean token";
return kind == Kind.BL_TRUE;
}
public int getLineNumber() {
return lineNumber;
}
/**This method handles the escape characters in String literals. The
* getText method returns the string from the token's characters. This means that
* the Scanner can ignore escape characters.
*
* @return
*/
public String getText() {
if (inputChars.length < end) {
assert kind == Kind.EOF && beg == inputChars.length;
return "";
}
if (kind == Kind.STRING_LIT) {
StringBuilder sb = new StringBuilder();
for (int i = beg+1; i < end-1; ++i) {
char ch = inputChars[i];
if (ch == '\\') {
char nextChar = inputChars[i+1];
if (nextChar == '"') {
sb.append('"');
i++;
} else if (nextChar == 'n') {
sb.append('\n');
i++;
} else if (nextChar == 'r') {
sb.append('\r');
i++;
} else if (nextChar == '\\') {
sb.append('\\');
i++;
}
} else {
sb.append(ch);
}
}
return sb.toString();
}
return String.valueOf(inputChars, beg, end - beg);
}
public String toString() {
return (new StringBuilder("<").append(kind).append(",")
.append(getText()).append(",").append(beg).append(",")
.append(end).append(",").append(lineNumber).append(">"))
.toString();
}
public boolean equals(Object o) {
if (!(o instanceof Token))
return false;
Token other = (Token) o;
return kind == other.kind && beg == other.beg && end == other.end
&& lineNumber == other.lineNumber;
}
}
}