Lexer.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. using System;
  2. namespace NTERA.Interpreter
  3. {
  4. public class Lexer
  5. {
  6. private readonly string source;
  7. private Marker sourceMarker;
  8. private char lastChar;
  9. public Marker TokenMarker { get; set; }
  10. public string Identifer { get; set; }
  11. public Value Value { get; set; }
  12. public Lexer(string input)
  13. {
  14. source = input;
  15. sourceMarker = new Marker(0, 1, 1);
  16. lastChar = source[0];
  17. }
  18. public void GoTo(Marker marker)
  19. {
  20. sourceMarker = marker;
  21. }
  22. char GetChar()
  23. {
  24. sourceMarker.Column++;
  25. sourceMarker.Pointer++;
  26. if (sourceMarker.Pointer >= source.Length)
  27. return lastChar = (char)0;
  28. if ((lastChar = source[sourceMarker.Pointer]) == '\n')
  29. {
  30. sourceMarker.Column = 1;
  31. sourceMarker.Line++;
  32. }
  33. return lastChar;
  34. }
  35. public Token GetToken()
  36. {
  37. while (lastChar == ' ' || lastChar == '\t' || lastChar == '\r')
  38. GetChar();
  39. TokenMarker = sourceMarker;
  40. if (char.IsLetter(lastChar))
  41. {
  42. Identifer = lastChar.ToString();
  43. while (char.IsLetterOrDigit(GetChar()))
  44. Identifer += lastChar;
  45. switch (Identifer.ToUpper())
  46. {
  47. case "PRINT": return Token.Print;
  48. case "PRINTL": return Token.PrintL;
  49. case "DRAWLINE": return Token.DrawLine;
  50. case "DRAWLINEFORM": return Token.DrawLineForm;
  51. case "DIM": return Token.Dim;
  52. case "CONST": return Token.Const;
  53. case "IF": return Token.If;
  54. case "ENDIF": return Token.EndIf;
  55. case "THEN": return Token.Then;
  56. case "ELSE": return Token.Else;
  57. case "FOR": return Token.For;
  58. case "TO": return Token.To;
  59. case "NEXT": return Token.Next;
  60. case "INPUT": return Token.Input;
  61. case "LET": return Token.Let;
  62. case "GOSUB": return Token.Gosub;
  63. case "RETURN": return Token.Return;
  64. case "END": return Token.End;
  65. case "OR": return Token.Or;
  66. case "AND": return Token.And;
  67. case "REM":
  68. while (lastChar != '\n') GetChar();
  69. GetChar();
  70. return GetToken();
  71. default:
  72. return Token.Identifer;
  73. }
  74. }
  75. if (char.IsDigit(lastChar))
  76. {
  77. string num = "";
  78. do { num += lastChar; } while (char.IsDigit(GetChar()) || lastChar == '.');
  79. double real;
  80. if (!double.TryParse(num, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out real))
  81. throw new Exception("ERROR while parsing number");
  82. Value = new Value(real);
  83. return Token.Value;
  84. }
  85. Token tok = Token.Unkown;
  86. switch (lastChar)
  87. {
  88. case '\n': tok = Token.NewLine; break;
  89. case '@': tok = Token.Function; break;
  90. case '#': tok = Token.Global; break;
  91. case ':': tok = Token.Colon; break;
  92. case ';': tok = Token.Semicolon; break;
  93. case ',': tok = Token.Comma; break;
  94. case '=': tok = Token.Equal; break;
  95. case '+': tok = Token.Plus; break;
  96. case '-': tok = Token.Minus; break;
  97. case '/': tok = Token.Slash; break;
  98. case '*': tok = Token.Asterisk; break;
  99. case '^': tok = Token.Caret; break;
  100. case '(': tok = Token.LParen; break;
  101. case ')': tok = Token.RParen; break;
  102. case '\'':
  103. while (lastChar != '\n') GetChar();
  104. GetChar();
  105. return GetToken();
  106. case '<':
  107. GetChar();
  108. if (lastChar == '>') tok = Token.NotEqual;
  109. else if (lastChar == '=') tok = Token.LessEqual;
  110. else return Token.Less;
  111. break;
  112. case '>':
  113. GetChar();
  114. if (lastChar == '=') tok = Token.MoreEqual;
  115. else return Token.More;
  116. break;
  117. case '"':
  118. string str = "";
  119. while (GetChar() != '"')
  120. {
  121. if (lastChar == '\\')
  122. {
  123. switch (char.ToLower(GetChar()))
  124. {
  125. case 'n': str += '\n'; break;
  126. case 't': str += '\t'; break;
  127. case '\\': str += '\\'; break;
  128. case '"': str += '"'; break;
  129. }
  130. }
  131. else
  132. {
  133. str += lastChar;
  134. }
  135. }
  136. Value = new Value(str);
  137. tok = Token.Value;
  138. break;
  139. case (char)0:
  140. return Token.EOF;
  141. }
  142. GetChar();
  143. return tok;
  144. }
  145. }
  146. }