using System; using System.Collections.Generic; using NTERA.Core; namespace NTERA.Interpreter { public partial class Interpreter { protected Lexer Lexer { get; set; } private Token previousToken; private Token CurrentToken => Tokens.Current; public VariableDictionary Variables { get; internal set; } = new VariableDictionary(); protected Dictionary Loops { get; } = new Dictionary(); public delegate Value BasicFunction(List args); protected readonly IConsole Console; protected Marker LineMarker; private bool exit; public Interpreter(IConsole console, string input) { this.Console = console; Lexer = new Lexer(input); GenerateKeywordDictionary(); GenerateFunctionDictionary(); } private void Error(string text) { throw new ParserException(text, LineMarker); } protected bool TryAssertToken(Token tok, bool pullNext = true) { if (pullNext) GetNextToken(); return CurrentToken == tok; } protected void AssertToken(Token tok, bool pullNext = true) { if (!TryAssertToken(tok, pullNext)) Error("Expect " + tok + " got " + CurrentToken); } protected IEnumerator Tokens; public void Exec() { exit = false; Tokens = Lexer.GetEnumerator(); while (!exit) Line(); } protected Token GetNextToken() { previousToken = CurrentToken; Tokens.MoveNext(); if (CurrentToken == Token.EOF && previousToken == Token.EOF) Error("Unexpected end of file"); return CurrentToken; } private void Line() { while (CurrentToken == Token.NewLine) GetNextToken(); if (CurrentToken == Token.EOF) { exit = true; return; } LineMarker = Lexer.TokenMarker; Statement(); if (CurrentToken != Token.NewLine && CurrentToken != Token.EOF) Error("Expect new line got " + CurrentToken); } private void Statement() { Token keyword = CurrentToken; GetNextToken(); if (KeywordMethods.ContainsKey(keyword)) KeywordMethods[keyword](); else { switch (keyword) { case Token.Input: Input(); break; case Token.Function: while (GetNextToken() != Token.NewLine) { } break; case Token.Identifer: if (CurrentToken != Token.Equal && CurrentToken != Token.Colon) Error("Expected assignment got " + CurrentToken); Let(); break; case Token.EOF: exit = true; break; default: Error("Expect keyword got " + keyword); break; } } } public Dictionary FunctionDictionary { get; protected set; } public Dictionary KeywordMethods { get; set; } private void Input() { while (true) { AssertToken(Token.Identifer); if (!Variables.ContainsKey(Lexer.Identifer)) Variables.Add(Lexer.Identifer, new Value()); Console.WaitInput(new Core.Interop.InputRequest() { InputType = Core.Interop.InputType.StrValue }); string input = Console.LastInput; if (double.TryParse(input, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out var d)) Variables[Lexer.Identifer] = new Value(d); else Variables[Lexer.Identifer] = new Value(input); if (!TryAssertToken(Token.Comma)) break; GetNextToken(); } } private Value RealExpression() { return Lexer.Expression(this); } private Value RealExpression(string input) { return new Lexer(input).Expression(this); } private Value StringExpression() { Lexer.Type = LexerType.String; GetNextToken(); var result = Lexer.Expression(this); Lexer.Type = LexerType.Real; return result; } } }