33
44// Implementation of the Scanner for KAY
55
6- // This code DOES NOT implement a scanner for KAY yet. You have to complete
7- // the code and also make sure it implements a scanner for KAY - not something
8- // else, not more and not less
9-
106import java .io .BufferedReader ;
117import java .io .FileNotFoundException ;
128import java .io .FileReader ;
139import java .io .IOException ;
1410
1511public class TokenStream {
1612
17- // READ THE COMPLETE FILE FIRST
18- // You will need to adapt it to KAY, NOT JAY
19-
2013 // Instance variables
2114 private boolean isEof = false ; // is end of file
2215 private char nextChar = ' ' ; // next character in input stream
@@ -34,16 +27,14 @@ public TokenStream(String fileName) {
3427 input = new BufferedReader (new FileReader (fileName ));
3528 } catch (FileNotFoundException e ) {
3629 System .out .println ("File not found: " + fileName );
37- // System.exit(1); // Removed to allow ScannerDemo to continue
38- // running after the input file is not found.
3930 isEof = true ;
4031 }
4132 }
4233
4334 public Token nextToken () { // Main function of the scanner
44- // Return next token with its type and value.
35+ // Return next token type and value.
4536 Token t = new Token ();
46- t .setType ("Other" ); // For now it is Other. You will update it in the code
37+ t .setType ("Other" ); // For now it is Other
4738 t .setValue ("" );
4839
4940 // First check for whitespaces and bypass them
@@ -52,12 +43,14 @@ public Token nextToken() { // Main function of the scanner
5243 // Then check for a comment, and bypass it
5344 // but remember that / may also be a division operator.
5445 while (nextChar == '/' ) {
55- // The use of while (instead of if) prevents the 2nd line to be printed when
56- // there are two comment lines in a row.
5746 nextChar = readChar ();
5847 if (nextChar == '/' ) { // If / is followed by another /
5948 // skip rest of line - it's a comment.
60- // TODO TO BE COMPLETED
49+ // look for <cr>, <lf>, <ff>
50+ while (!isEof && !isEndOfLine (nextChar )) {
51+ nextChar = readChar ();
52+ }
53+ skipWhiteSpace ();
6154 } else {
6255 // A slash followed by anything else must be an operator.
6356 t .setValue ("/" );
@@ -72,17 +65,49 @@ public Token nextToken() { // Main function of the scanner
7265 t .setType ("Operator" );
7366 t .setValue (t .getValue () + nextChar );
7467 switch (nextChar ) {
75- // TODO TO BE COMPLETED OR CHANGED WHERE NEEDED TO IMPLEMENT KAY
7668 case '<' :
77- // <=
69+ // <= or <>
70+ nextChar = readChar ();
71+ if (nextChar == '=' || nextChar == '>' ) {
72+ t .setValue (t .getValue () + nextChar );
73+ nextChar = readChar ();
74+ }
75+ return t ;
7876 case '>' :
7977 // >=
78+ nextChar = readChar ();
79+ if (nextChar == '=' ) {
80+ t .setValue (t .getValue () + nextChar );
81+ nextChar = readChar ();
82+ }
83+ return t ;
8084 case '=' :
8185 // ==
86+ nextChar = readChar ();
87+ if (nextChar == '=' ) {
88+ t .setValue (t .getValue () + nextChar );
89+ nextChar = readChar ();
90+ }
91+ return t ;
8292 case '!' :
8393 // !=
8494 nextChar = readChar ();
95+ if (nextChar == '=' ) {
96+ t .setValue (t .getValue () + nextChar );
97+ nextChar = readChar ();
98+ }
8599 return t ;
100+ case ':' :
101+ // := (assignment operator in KAY)
102+ nextChar = readChar ();
103+ if (nextChar == '=' ) {
104+ t .setValue (t .getValue () + nextChar );
105+ nextChar = readChar ();
106+ return t ;
107+ } else {
108+ t .setType ("Other" );
109+ return t ;
110+ }
86111 case '|' :
87112 // Look for ||
88113 nextChar = readChar ();
@@ -94,6 +119,7 @@ public Token nextToken() { // Main function of the scanner
94119 t .setType ("Other" );
95120 }
96121 return t ;
122+
97123 case '&' :
98124 // Look for &&
99125 nextChar = readChar ();
@@ -104,9 +130,9 @@ public Token nextToken() { // Main function of the scanner
104130 } else {
105131 t .setType ("Other" );
106132 }
107-
108133 return t ;
109- default : // all other operators
134+
135+ default : // all other operators: +, -, *, /
110136 nextChar = readChar ();
111137 return t ;
112138 }
@@ -115,22 +141,24 @@ public Token nextToken() { // Main function of the scanner
115141 // Then check for a separator
116142 if (isSeparator (nextChar )) {
117143 t .setType ("Separator" );
118- // TODO TO BE COMPLETED
144+ t .setValue (t .getValue () + nextChar );
145+ nextChar = readChar ();
119146 return t ;
120147 }
121148
122- // Then check for an identifier, keyword, or literal (True or False) .
149+ // Then check for an identifier, keyword, or literal.
123150 if (isLetter (nextChar )) {
124151 // Set to an identifier
125152 t .setType ("Identifier" );
126153 while ((isLetter (nextChar ) || isDigit (nextChar ))) {
127154 t .setValue (t .getValue () + nextChar );
128155 nextChar = readChar ();
129156 }
130- // Now see if this is a keyword
157+ // now see if this is a keyword
131158 if (isKeyword (t .getValue ())) {
132159 t .setType ("Keyword" );
133160 } else if (t .getValue ().equals ("True" ) || t .getValue ().equals ("False" )) {
161+ // In KAY, True and False are uppercased literals
134162 t .setType ("Literal" );
135163 }
136164 if (isEndOfToken (nextChar )) { // If token is valid, returns.
@@ -187,30 +215,12 @@ private char readChar() {
187215 }
188216
189217 private boolean isKeyword (String s ) {
190- // TODO TO BE COMPLETED
191- return false ;
218+ // Keywords in KAY: main, if, else, while, integer, bool
219+ // Note: void is NOT a keyword in KAY
220+ return s .equals ("main" ) || s .equals ("if" ) || s .equals ("else" ) ||
221+ s .equals ("while" ) || s .equals ("integer" ) || s .equals ("bool" );
192222 }
193223
194- private boolean isSeparator (char c ) {
195- // TODO TO BE COMPLETED
196- return false ;
197- }
198-
199- private boolean isOperator (char c ) {
200- // Checks for characters that start operators
201- // TODO TO BE COMPLETED
202- return false ;
203- }
204-
205- private boolean isLetter (char c ) {
206- return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' );
207- }
208-
209- private boolean isDigit (char c ) {
210- // TODO TO BE COMPLETED
211- return false ;
212- }
213-
214224 private boolean isWhiteSpace (char c ) {
215225 return (c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\f' );
216226 }
@@ -219,7 +229,7 @@ private boolean isEndOfLine(char c) {
219229 return (c == '\r' || c == '\n' || c == '\f' );
220230 }
221231
222- private boolean isEndOfToken (char c ) { // Is the value a seperate token?
232+ private boolean isEndOfToken (char c ) { // Is the value a separate token?
223233 return (isWhiteSpace (nextChar ) || isOperator (nextChar ) || isSeparator (nextChar ) || isEof );
224234 }
225235
@@ -230,7 +240,34 @@ private void skipWhiteSpace() {
230240 }
231241 }
232242
243+ private boolean isSeparator (char c ) {
244+ // Separators in KAY: { } ; ( )
245+ return (c == '{' || c == '}' || c == ';' || c == '(' || c == ')' );
246+ }
247+
248+ private boolean isOperator (char c ) {
249+ // Checks for characters that start operators
250+ // Operators in KAY: + - * / < <= > >= == != && || ! :=
251+ return (c == '+' || c == '-' || c == '*' || c == '/' ||
252+ c == '<' || c == '>' || c == '=' || c == '!' ||
253+ c == '&' || c == '|' || c == ':' );
254+ }
255+
256+ private boolean isLetter (char c ) {
257+ return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' );
258+ }
259+
260+ private boolean isDigit (char c ) {
261+ return (c >= '0' && c <= '9' );
262+ }
263+
264+ public boolean isEndofFile () {
265+ return isEof ;
266+ }
267+ }
268+
233269 public boolean isEndofFile () {
234270 return isEof ;
235271 }
236- }
272+
273+ }
0 commit comments