Interpreter.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. using System;
  2. using System.Collections.Generic;
  3. using NTERA.Core;
  4. namespace NTERA.Interpreter
  5. {
  6. public partial class Interpreter
  7. {
  8. protected Lexer Lexer { get; set; }
  9. private Token previousToken;
  10. private Token CurrentToken => Tokens.Current;
  11. public VariableDictionary Variables { get; internal set; } = new VariableDictionary();
  12. protected Dictionary<string, Marker> Loops { get; } = new Dictionary<string, Marker>();
  13. public delegate Value BasicFunction(List<Value> args);
  14. protected readonly IConsole Console;
  15. protected Marker LineMarker;
  16. private bool exit;
  17. public Interpreter(IConsole console, string input)
  18. {
  19. this.Console = console;
  20. Lexer = new Lexer(input);
  21. GenerateKeywordDictionary();
  22. GenerateFunctionDictionary();
  23. }
  24. private void Error(string text)
  25. {
  26. throw new ParserException(text, LineMarker);
  27. }
  28. protected bool TryAssertToken(Token tok, bool pullNext = true)
  29. {
  30. if (pullNext)
  31. GetNextToken();
  32. return CurrentToken == tok;
  33. }
  34. protected void AssertToken(Token tok, bool pullNext = true)
  35. {
  36. if (!TryAssertToken(tok, pullNext))
  37. Error("Expect " + tok + " got " + CurrentToken);
  38. }
  39. protected IEnumerator<Token> Tokens;
  40. public void Exec()
  41. {
  42. exit = false;
  43. Tokens = Lexer.GetEnumerator();
  44. while (!exit)
  45. Line();
  46. }
  47. protected Token GetNextToken()
  48. {
  49. previousToken = CurrentToken;
  50. Tokens.MoveNext();
  51. if (CurrentToken == Token.EOF && previousToken == Token.EOF)
  52. Error("Unexpected end of file");
  53. return CurrentToken;
  54. }
  55. private void Line()
  56. {
  57. while (CurrentToken == Token.NewLine)
  58. GetNextToken();
  59. if (CurrentToken == Token.EOF)
  60. {
  61. exit = true;
  62. return;
  63. }
  64. LineMarker = Lexer.TokenMarker;
  65. Statement();
  66. if (CurrentToken != Token.NewLine && CurrentToken != Token.EOF)
  67. Error("Expect new line got " + CurrentToken);
  68. }
  69. private void Statement()
  70. {
  71. Token keyword = CurrentToken;
  72. GetNextToken();
  73. if (KeywordMethods.ContainsKey(keyword))
  74. KeywordMethods[keyword]();
  75. else
  76. {
  77. switch (keyword)
  78. {
  79. case Token.Input:
  80. Input();
  81. break;
  82. case Token.Function:
  83. while (GetNextToken() != Token.NewLine) { }
  84. break;
  85. case Token.Identifer:
  86. if (CurrentToken != Token.Equal && CurrentToken != Token.Colon)
  87. Error("Expected assignment got " + CurrentToken);
  88. Let();
  89. break;
  90. case Token.EOF:
  91. exit = true;
  92. break;
  93. default:
  94. Error("Expect keyword got " + keyword);
  95. break;
  96. }
  97. }
  98. }
  99. public Dictionary<string, BasicFunction> FunctionDictionary { get; protected set; }
  100. public Dictionary<Token, Action> KeywordMethods { get; set; }
  101. private void Input()
  102. {
  103. while (true)
  104. {
  105. AssertToken(Token.Identifer);
  106. if (!Variables.ContainsKey(Lexer.Identifer)) Variables.Add(Lexer.Identifer, new Value());
  107. Console.WaitInput(new Core.Interop.InputRequest() { InputType = Core.Interop.InputType.StrValue });
  108. string input = Console.LastInput;
  109. if (double.TryParse(input, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out var d))
  110. Variables[Lexer.Identifer] = new Value(d);
  111. else
  112. Variables[Lexer.Identifer] = new Value(input);
  113. if (!TryAssertToken(Token.Comma))
  114. break;
  115. GetNextToken();
  116. }
  117. }
  118. private Value RealExpression()
  119. {
  120. return Lexer.Expression(this);
  121. }
  122. private Value RealExpression(string input)
  123. {
  124. return new Lexer(input).Expression(this);
  125. }
  126. private Value StringExpression()
  127. {
  128. Lexer.Type = LexerType.String;
  129. GetNextToken();
  130. var result = Lexer.Expression(this);
  131. Lexer.Type = LexerType.Real;
  132. return result;
  133. }
  134. }
  135. }