Lexer.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  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 "IF": return Token.If;
  49. case "ENDIF": return Token.EndIf;
  50. case "THEN": return Token.Then;
  51. case "ELSE": return Token.Else;
  52. case "FOR": return Token.For;
  53. case "TO": return Token.To;
  54. case "NEXT": return Token.Next;
  55. case "INPUT": return Token.Input;
  56. case "LET": return Token.Let;
  57. case "GOSUB": return Token.Gosub;
  58. case "RETURN": return Token.Return;
  59. case "END": return Token.End;
  60. case "OR": return Token.Or;
  61. case "AND": return Token.And;
  62. case "REM":
  63. while (lastChar != '\n') GetChar();
  64. GetChar();
  65. return GetToken();
  66. default:
  67. return Token.Identifer;
  68. }
  69. }
  70. if (char.IsDigit(lastChar))
  71. {
  72. string num = "";
  73. do { num += lastChar; } while (char.IsDigit(GetChar()) || lastChar == '.');
  74. double real;
  75. if (!double.TryParse(num, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out real))
  76. throw new Exception("ERROR while parsing number");
  77. Value = new Value(real);
  78. return Token.Value;
  79. }
  80. Token tok = Token.Unkown;
  81. switch (lastChar)
  82. {
  83. case '\n': tok = Token.NewLine; break;
  84. case ':': tok = Token.Colon; break;
  85. case ';': tok = Token.Semicolon; break;
  86. case ',': tok = Token.Comma; break;
  87. case '=': tok = Token.Equal; break;
  88. case '+': tok = Token.Plus; break;
  89. case '-': tok = Token.Minus; break;
  90. case '/': tok = Token.Slash; break;
  91. case '*': tok = Token.Asterisk; break;
  92. case '^': tok = Token.Caret; break;
  93. case '(': tok = Token.LParen; break;
  94. case ')': tok = Token.RParen; break;
  95. case '\'':
  96. while (lastChar != '\n') GetChar();
  97. GetChar();
  98. return GetToken();
  99. case '<':
  100. GetChar();
  101. if (lastChar == '>') tok = Token.NotEqual;
  102. else if (lastChar == '=') tok = Token.LessEqual;
  103. else return Token.Less;
  104. break;
  105. case '>':
  106. GetChar();
  107. if (lastChar == '=') tok = Token.MoreEqual;
  108. else return Token.More;
  109. break;
  110. case '"':
  111. string str = "";
  112. while (GetChar() != '"')
  113. {
  114. if (lastChar == '\\')
  115. {
  116. switch (char.ToLower(GetChar()))
  117. {
  118. case 'n': str += '\n'; break;
  119. case 't': str += '\t'; break;
  120. case '\\': str += '\\'; break;
  121. case '"': str += '"'; break;
  122. }
  123. }
  124. else
  125. {
  126. str += lastChar;
  127. }
  128. }
  129. Value = new Value(str);
  130. tok = Token.Value;
  131. break;
  132. case (char)0:
  133. return Token.EOF;
  134. }
  135. GetChar();
  136. return tok;
  137. }
  138. }
  139. }