public static void RunUnitTests()
        {
            Lexer lex = new Lexer("42  * 3.14158");

            Check(lex.Dequeue(), Token.Type.Number, "42");
            CheckLineNum(lex.lineNum, 1);
            Check(lex.Dequeue(), Token.Type.OpTimes);
            Check(lex.Dequeue(), Token.Type.Number, "3.14158");
            UnitTest.ErrorIf(!lex.AtEnd, "AtEnd not set when it should be");
            CheckLineNum(lex.lineNum, 1);

            lex = new Lexer("6*(.1-foo) end if // and a comment!");
            Check(lex.Dequeue(), Token.Type.Number, "6");
            CheckLineNum(lex.lineNum, 1);
            Check(lex.Dequeue(), Token.Type.OpTimes);
            Check(lex.Dequeue(), Token.Type.LParen);
            Check(lex.Dequeue(), Token.Type.Number, ".1");
            Check(lex.Dequeue(), Token.Type.OpMinus);
            Check(lex.Peek(), Token.Type.Identifier, "foo");
            Check(lex.Peek(), Token.Type.Identifier, "foo");
            Check(lex.Dequeue(), Token.Type.Identifier, "foo");
            Check(lex.Dequeue(), Token.Type.RParen);
            Check(lex.Dequeue(), Token.Type.Keyword, "end if");
            Check(lex.Dequeue(), Token.Type.EOL);
            UnitTest.ErrorIf(!lex.AtEnd, "AtEnd not set when it should be");
            CheckLineNum(lex.lineNum, 1);

            lex = new Lexer("\"foo\" \"isn't \"\"real\"\"\" \"now \"\"\"\" double!\"");
            Check(lex.Dequeue(), Token.Type.String, "foo");
            Check(lex.Dequeue(), Token.Type.String, "isn't \"real\"");
            Check(lex.Dequeue(), Token.Type.String, "now \"\" double!");
            UnitTest.ErrorIf(!lex.AtEnd, "AtEnd not set when it should be");

            lex = new Lexer("foo\nbar\rbaz\r\nbamf");
            Check(lex.Dequeue(), Token.Type.Identifier, "foo");
            CheckLineNum(lex.lineNum, 1);
            Check(lex.Dequeue(), Token.Type.EOL);
            Check(lex.Dequeue(), Token.Type.Identifier, "bar");
            CheckLineNum(lex.lineNum, 2);
            Check(lex.Dequeue(), Token.Type.EOL);
            Check(lex.Dequeue(), Token.Type.Identifier, "baz");
            CheckLineNum(lex.lineNum, 3);
            Check(lex.Dequeue(), Token.Type.EOL);
            Check(lex.Dequeue(), Token.Type.Identifier, "bamf");
            CheckLineNum(lex.lineNum, 4);
            Check(lex.Dequeue(), Token.Type.EOL);
            UnitTest.ErrorIf(!lex.AtEnd, "AtEnd not set when it should be");

            Check(LastToken("x=42 // foo"), Token.Type.Number, "42");
            Check(LastToken("x = [1, 2, // foo"), Token.Type.Comma);
            Check(LastToken("x = [1, 2 // foo"), Token.Type.Number, "2");
            Check(LastToken("x = [1, 2 // foo // and \"more\" foo"), Token.Type.Number, "2");
            Check(LastToken("x = [\"foo\", \"//bar\"]"), Token.Type.RSquare);
            Check(LastToken("print 1 // line 1\nprint 2"), Token.Type.Number, "2");
            Check(LastToken("print \"Hi\"\"Quote\" // foo bar"), Token.Type.String, "Hi\"Quote");
        }
        public static void Check(Token tok, Token.Type type, string text = null, int lineNum = 0)
        {
            UnitTest.ErrorIfNull(tok);
            if (tok == null)
            {
                return;
            }
            UnitTest.ErrorIf(tok.type != type, "Token type: expected "
                             + type + ", but got " + tok.type);

            UnitTest.ErrorIf(text != null && tok.text != text,
                             "Token text: expected " + text + ", but got " + tok.text);
        }
        public static void RunUnitTests()
        {
            Lexer lex = new Lexer("42  * 3.14158");

            Check(lex.Dequeue(), Token.Type.Number, "42");
            CheckLineNum(lex.lineNum, 1);
            Check(lex.Dequeue(), Token.Type.OpTimes);
            Check(lex.Dequeue(), Token.Type.Number, "3.14158");
            UnitTest.ErrorIf(!lex.AtEnd, "AtEnd not set when it should be");
            CheckLineNum(lex.lineNum, 1);

            lex = new Lexer("6*(.1-foo) end if // and a comment!");
            Check(lex.Dequeue(), Token.Type.Number, "6");
            CheckLineNum(lex.lineNum, 1);
            Check(lex.Dequeue(), Token.Type.OpTimes);
            Check(lex.Dequeue(), Token.Type.LParen);
            Check(lex.Dequeue(), Token.Type.Number, ".1");
            Check(lex.Dequeue(), Token.Type.OpMinus);
            Check(lex.Peek(), Token.Type.Identifier, "foo");
            Check(lex.Peek(), Token.Type.Identifier, "foo");
            Check(lex.Dequeue(), Token.Type.Identifier, "foo");
            Check(lex.Dequeue(), Token.Type.RParen);
            Check(lex.Dequeue(), Token.Type.Keyword, "end if");
            Check(lex.Dequeue(), Token.Type.EOL);
            UnitTest.ErrorIf(!lex.AtEnd, "AtEnd not set when it should be");
            CheckLineNum(lex.lineNum, 1);

            lex = new Lexer("\"foo\" \"isn't \"\"real\"\"\" \"now \"\"\"\" double!\"");
            Check(lex.Dequeue(), Token.Type.String, "foo");
            Check(lex.Dequeue(), Token.Type.String, "isn't \"real\"");
            Check(lex.Dequeue(), Token.Type.String, "now \"\" double!");
            UnitTest.ErrorIf(!lex.AtEnd, "AtEnd not set when it should be");

            lex = new Lexer("foo\nbar\rbaz\r\nbamf");
            Check(lex.Dequeue(), Token.Type.Identifier, "foo");
            CheckLineNum(lex.lineNum, 1);
            Check(lex.Dequeue(), Token.Type.EOL);
            Check(lex.Dequeue(), Token.Type.Identifier, "bar");
            CheckLineNum(lex.lineNum, 2);
            Check(lex.Dequeue(), Token.Type.EOL);
            Check(lex.Dequeue(), Token.Type.Identifier, "baz");
            CheckLineNum(lex.lineNum, 3);
            Check(lex.Dequeue(), Token.Type.EOL);
            Check(lex.Dequeue(), Token.Type.Identifier, "bamf");
            CheckLineNum(lex.lineNum, 4);
            Check(lex.Dequeue(), Token.Type.EOL);
            UnitTest.ErrorIf(!lex.AtEnd, "AtEnd not set when it should be");
        }
 public static void CheckLineNum(int actual, int expected)
 {
     UnitTest.ErrorIf(actual != expected, "Lexer line number: expected "
                      + expected + ", but got " + actual);
 }