using System; using System.IO; using System.Text; /// /// The Scanner for the Z# Compiler. /// public class Scanner { const char EOF = '\u0080'; // return this for end of file const char CR = '\r'; const char LF = '\n'; // Alphbetically sorted list of the keywords. static readonly string[] keywords = { "class", "const", "else", "if", "new", "read", "return", "void", "while", "write" }; // Token codes in the same order as the keywords. static readonly int[] kwCodes = { Token.CLASS, Token.CONST, Token.ELSE, Token.IF, Token.NEW, Token.READ, Token.RETURN, Token.VOID, Token.WHILE, Token.WRITE }; static TextReader input; static char ch; // lookahead character (= next (unprocessed) character in input stream) static int line, col; // line and column number of ch in input stream // Initializes the scanner. public static void Init (TextReader r) { input = r; line = 1; col = 0; // read 1st char into ch, increment col to 1 NextCh(); } // Reads next character from input stream into ch. // Keeps pos, line and col in sync with reading position. static void NextCh () { // TODO } // Returns next token. // To be used by parser. public static Token Next () { // TODO return null; } // end Next() // Error handling for the scanner. // Prints error message to System.Console. static void Error (string msg) { Errors.Error(msg, line, col); } // Reads a name into the Token t. static void ReadName (Token t) { StringBuilder sb = new StringBuilder(); do { sb.Append(ch); NextCh(); } while (IsLetter(ch) || IsDigit(ch) || ch == '_'); t.str = sb.ToString(); t.kind = KeywordKind(t.str); } // Reads a number into the Token t. static void ReadNumber (Token t) { StringBuilder sb = new StringBuilder(); do { sb.Append(ch); NextCh(); } while (IsDigit(ch)); t.str = sb.ToString(); t.kind = Token.NUMBER; try { t.val = Convert.ToInt32(t.str); } catch (OverflowException) { Error("Number to big: " + t.str); } } // Skips nested multi-line comments. static void SkipComment () { // TODO } // if str is a keyword, returns specific keyword token code, // otherwise returns ident token code. static int KeywordKind (string str) { int idx = Array.BinarySearch(keywords, str); return (idx < 0) ? Token.IDENT : kwCodes[idx]; } static bool IsPrintableChar (char c) { return ' ' <= c && c <= '~'; } static bool IsLetter (char c) { return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'); } static bool IsDigit (char c) { return '0' <= c && c <= '9'; } }