123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- using System;
- namespace NTERA.Interpreter
- {
- public class Lexer
- {
- private readonly string source;
- private Marker sourceMarker;
- private char lastChar;
- public Marker TokenMarker { get; set; }
- public string Identifer { get; set; }
- public Value Value { get; set; }
- public Lexer(string input)
- {
- source = input;
- sourceMarker = new Marker(0, 1, 1);
- lastChar = source[0];
- }
- public void GoTo(Marker marker)
- {
- sourceMarker = marker;
- }
- char GetChar()
- {
- sourceMarker.Column++;
- sourceMarker.Pointer++;
- if (sourceMarker.Pointer >= source.Length)
- return lastChar = (char)0;
- if ((lastChar = source[sourceMarker.Pointer]) == '\n')
- {
- sourceMarker.Column = 1;
- sourceMarker.Line++;
- }
- return lastChar;
- }
- public Token GetToken()
- {
- while (lastChar == ' ' || lastChar == '\t' || lastChar == '\r')
- GetChar();
- TokenMarker = sourceMarker;
- if (char.IsLetter(lastChar))
- {
- Identifer = lastChar.ToString();
- while (char.IsLetterOrDigit(GetChar()))
- Identifer += lastChar;
- switch (Identifer.ToUpper())
- {
- case "PRINT": return Token.Print;
- case "PRINTL": return Token.PrintL;
- case "DRAWLINE": return Token.DrawLine;
- case "DRAWLINEFORM": return Token.DrawLineForm;
- case "DIM": return Token.Dim;
- case "CONST": return Token.Const;
- case "IF": return Token.If;
- case "ENDIF": return Token.EndIf;
- case "THEN": return Token.Then;
- case "ELSE": return Token.Else;
- case "FOR": return Token.For;
- case "TO": return Token.To;
- case "NEXT": return Token.Next;
- case "INPUT": return Token.Input;
- case "LET": return Token.Let;
- case "GOSUB": return Token.Gosub;
- case "RETURN": return Token.Return;
- case "END": return Token.End;
- case "OR": return Token.Or;
- case "AND": return Token.And;
- case "REM":
- while (lastChar != '\n') GetChar();
- GetChar();
- return GetToken();
- default:
- return Token.Identifer;
- }
- }
- if (char.IsDigit(lastChar))
- {
- string num = "";
- do { num += lastChar; } while (char.IsDigit(GetChar()) || lastChar == '.');
- double real;
- if (!double.TryParse(num, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out real))
- throw new Exception("ERROR while parsing number");
- Value = new Value(real);
- return Token.Value;
- }
- Token tok = Token.Unkown;
- switch (lastChar)
- {
- case '\n': tok = Token.NewLine; break;
- case '@': tok = Token.Function; break;
- case '#': tok = Token.Global; break;
- case ':': tok = Token.Colon; break;
- case ';': tok = Token.Semicolon; break;
- case ',': tok = Token.Comma; break;
- case '=': tok = Token.Equal; break;
- case '+': tok = Token.Plus; break;
- case '-': tok = Token.Minus; break;
- case '/': tok = Token.Slash; break;
- case '*': tok = Token.Asterisk; break;
- case '^': tok = Token.Caret; break;
- case '(': tok = Token.LParen; break;
- case ')': tok = Token.RParen; break;
- case '\'':
- while (lastChar != '\n') GetChar();
- GetChar();
- return GetToken();
- case '<':
- GetChar();
- if (lastChar == '>') tok = Token.NotEqual;
- else if (lastChar == '=') tok = Token.LessEqual;
- else return Token.Less;
- break;
- case '>':
- GetChar();
- if (lastChar == '=') tok = Token.MoreEqual;
- else return Token.More;
- break;
- case '"':
- string str = "";
- while (GetChar() != '"')
- {
- if (lastChar == '\\')
- {
- switch (char.ToLower(GetChar()))
- {
- case 'n': str += '\n'; break;
- case 't': str += '\t'; break;
- case '\\': str += '\\'; break;
- case '"': str += '"'; break;
- }
- }
- else
- {
- str += lastChar;
- }
- }
- Value = new Value(str);
- tok = Token.Value;
- break;
- case (char)0:
- return Token.EOF;
- }
- GetChar();
- return tok;
- }
- }
- }
|