Interpreter.cs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. using System;
  2. using System.Collections.Generic;
  3. using NTERA.Interpreter.Functions;
  4. namespace NTERA.Interpreter
  5. {
  6. public partial class Interpreter
  7. {
  8. public bool HasPrint { get; set; } = true;
  9. public bool HasInput { get; set; } = true;
  10. private Lexer lex;
  11. private Token prevToken;
  12. private Token lastToken;
  13. private Dictionary<string, Value> vars;
  14. private Dictionary<string, Marker> loops;
  15. public delegate Value BasicFunction(Interpreter interpreter, List<Value> args);
  16. private Dictionary<string, BasicFunction> funcs;
  17. private int ifcounter;
  18. private Marker lineMarker;
  19. private bool exit;
  20. public Interpreter(string input)
  21. {
  22. lex = new Lexer(input);
  23. vars = new Dictionary<string, Value>();
  24. loops = new Dictionary<string, Marker>();
  25. funcs = new Dictionary<string, BasicFunction>();
  26. ifcounter = 0;
  27. BuiltInFunctions.InstallAll(this);
  28. }
  29. public Value GetVar(string name)
  30. {
  31. if (!vars.ContainsKey(name))
  32. throw new Exception("Variable with name " + name + " does not exist.");
  33. return vars[name];
  34. }
  35. public void SetVar(string name, Value val)
  36. {
  37. if (!vars.ContainsKey(name)) vars.Add(name, val);
  38. else vars[name] = val;
  39. }
  40. public void AddFunction(string name, BasicFunction function)
  41. {
  42. if (!funcs.ContainsKey(name)) funcs.Add(name, function);
  43. else funcs[name] = function;
  44. }
  45. void Error(string text)
  46. {
  47. throw new Exception(text + " at line: " + lineMarker.Line);
  48. }
  49. void Match(Token tok)
  50. {
  51. if (lastToken != tok)
  52. Error("Expect " + tok + " got " + lastToken);
  53. }
  54. public void Exec()
  55. {
  56. exit = false;
  57. GetNextToken();
  58. while (!exit) Line();
  59. }
  60. Token GetNextToken()
  61. {
  62. prevToken = lastToken;
  63. lastToken = lex.GetToken();
  64. if (lastToken == Token.EOF && prevToken == Token.EOF)
  65. Error("Unexpected end of file");
  66. return lastToken;
  67. }
  68. void Line()
  69. {
  70. while (lastToken == Token.NewLine) GetNextToken();
  71. if (lastToken == Token.EOF)
  72. {
  73. exit = true;
  74. return;
  75. }
  76. lineMarker = lex.TokenMarker;
  77. Statment();
  78. if (lastToken != Token.NewLine && lastToken != Token.EOF)
  79. Error("Expect new line got " + lastToken);
  80. }
  81. void Statment()
  82. {
  83. Token keyword = lastToken;
  84. GetNextToken();
  85. switch (keyword)
  86. {
  87. case Token.Print: Print(); break;
  88. case Token.Input: Input(); break;
  89. case Token.If: If(); break;
  90. case Token.Else: Else(); break;
  91. case Token.EndIf: break;
  92. case Token.For: For(); break;
  93. case Token.Next: Next(); break;
  94. case Token.Let: Let(); break;
  95. case Token.End: End(); break;
  96. case Token.Identifer:
  97. if (lastToken == Token.Equal) Let();
  98. else goto default;
  99. break;
  100. case Token.EOF:
  101. exit = true;
  102. break;
  103. default:
  104. Error("Expect keyword got " + keyword);
  105. break;
  106. }
  107. if (lastToken == Token.Colon)
  108. {
  109. GetNextToken();
  110. Statment();
  111. }
  112. }
  113. void Print()
  114. {
  115. if (!HasPrint)
  116. Error("Print command not allowed");
  117. Console.WriteLine(Expr().ToString());
  118. }
  119. void Input()
  120. {
  121. if (!HasInput)
  122. Error("Input command not allowed");
  123. while (true)
  124. {
  125. Match(Token.Identifer);
  126. if (!vars.ContainsKey(lex.Identifer)) vars.Add(lex.Identifer, new Value());
  127. string input = Console.ReadLine();
  128. double d;
  129. if (double.TryParse(input, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out d))
  130. vars[lex.Identifer] = new Value(d);
  131. else
  132. vars[lex.Identifer] = new Value(input);
  133. GetNextToken();
  134. if (lastToken != Token.Comma) break;
  135. GetNextToken();
  136. }
  137. }
  138. Value Expr()
  139. {
  140. Dictionary<Token, int> prec = new Dictionary<Token, int>()
  141. {
  142. { Token.Or, 0 }, { Token.And, 0 },
  143. { Token.Equal, 1 }, { Token.NotEqual, 1 },
  144. { Token.Less, 1 }, { Token.More, 1 }, { Token.LessEqual, 1 }, { Token.MoreEqual, 1 },
  145. { Token.Plus, 2 }, { Token.Minus, 2 },
  146. { Token.Asterisk, 3 }, {Token.Slash, 3 },
  147. { Token.Caret, 4 }
  148. };
  149. Stack<Value> stack = new Stack<Value>();
  150. Stack<Token> operators = new Stack<Token>();
  151. int i = 0;
  152. while (true)
  153. {
  154. if (lastToken == Token.Value)
  155. {
  156. stack.Push(lex.Value);
  157. }
  158. else if (lastToken == Token.Identifer)
  159. {
  160. if (vars.ContainsKey(lex.Identifer))
  161. {
  162. stack.Push(vars[lex.Identifer]);
  163. }
  164. else if (funcs.ContainsKey(lex.Identifer))
  165. {
  166. string name = lex.Identifer;
  167. List<Value> args = new List<Value>();
  168. GetNextToken();
  169. Match(Token.LParen);
  170. start:
  171. if (GetNextToken() != Token.RParen)
  172. {
  173. args.Add(Expr());
  174. if (lastToken == Token.Comma)
  175. goto start;
  176. }
  177. stack.Push(funcs[name](null, args));
  178. }
  179. else
  180. {
  181. Error("Undeclared variable " + lex.Identifer);
  182. }
  183. }
  184. else if (lastToken == Token.LParen)
  185. {
  186. GetNextToken();
  187. stack.Push(Expr());
  188. Match(Token.RParen);
  189. }
  190. else if (lastToken >= Token.Plus && lastToken <= Token.Not)
  191. {
  192. if ((lastToken == Token.Minus || lastToken == Token.Minus) && (i == 0 || prevToken == Token.LParen))
  193. {
  194. stack.Push(new Value(0));
  195. operators.Push(lastToken);
  196. }
  197. else
  198. {
  199. while (operators.Count > 0 && prec[lastToken] <= prec[operators.Peek()])
  200. Operation(ref stack, operators.Pop());
  201. operators.Push(lastToken);
  202. }
  203. }
  204. else
  205. {
  206. if (i == 0)
  207. Error("Empty expression");
  208. break;
  209. }
  210. i++;
  211. GetNextToken();
  212. }
  213. while (operators.Count > 0)
  214. Operation(ref stack, operators.Pop());
  215. return stack.Pop();
  216. }
  217. void Operation(ref Stack<Value> stack, Token token)
  218. {
  219. Value b = stack.Pop();
  220. Value a = stack.Pop();
  221. Value result = a.BinOp(b, token);
  222. stack.Push(result);
  223. }
  224. }
  225. }