|
@@ -1,6 +1,5 @@
|
|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
-using System.Linq;
|
|
|
using NTERA.Core;
|
|
|
|
|
|
namespace NTERA.Interpreter
|
|
@@ -11,7 +10,7 @@ namespace NTERA.Interpreter
|
|
|
private Token previousToken;
|
|
|
private Token CurrentToken => Tokens.Current;
|
|
|
|
|
|
- public VariableDictionary Variables { get; } = new VariableDictionary();
|
|
|
+ public VariableDictionary Variables { get; internal set; } = new VariableDictionary();
|
|
|
protected Dictionary<string, Marker> Loops { get; } = new Dictionary<string, Marker>();
|
|
|
|
|
|
public delegate Value BasicFunction(List<Value> args);
|
|
@@ -33,7 +32,7 @@ namespace NTERA.Interpreter
|
|
|
|
|
|
private void Error(string text)
|
|
|
{
|
|
|
- throw new Exception(text + " at line: " + LineMarker.Line);
|
|
|
+ throw new ParserException(text, LineMarker);
|
|
|
}
|
|
|
|
|
|
protected bool TryAssertToken(Token tok, bool pullNext = true)
|
|
@@ -56,9 +55,7 @@ namespace NTERA.Interpreter
|
|
|
{
|
|
|
exit = false;
|
|
|
|
|
|
- Tokens = Lexer.GetTokens().GetEnumerator();
|
|
|
-
|
|
|
- GetNextToken();
|
|
|
+ Tokens = Lexer.GetEnumerator();
|
|
|
|
|
|
while (!exit)
|
|
|
Line();
|
|
@@ -157,150 +154,24 @@ namespace NTERA.Interpreter
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private static readonly Dictionary<Token, int> OrderOfOps = new Dictionary<Token, int>
|
|
|
- {
|
|
|
- { Token.Or, 0 }, { Token.And, 0 },
|
|
|
- { Token.Equal, 1 }, { Token.NotEqual, 1 },
|
|
|
- { Token.Less, 1 }, { Token.More, 1 }, { Token.LessEqual, 1 }, { Token.MoreEqual, 1 },
|
|
|
- { Token.Plus, 2 }, { Token.Minus, 2 },
|
|
|
- { Token.Asterisk, 3 }, {Token.Slash, 3 },
|
|
|
- { Token.Caret, 4 }
|
|
|
- };
|
|
|
-
|
|
|
private Value RealExpression()
|
|
|
{
|
|
|
- return Expression(Lexer, Tokens);
|
|
|
+ return Lexer.Expression(this);
|
|
|
}
|
|
|
|
|
|
private Value RealExpression(string input)
|
|
|
{
|
|
|
- return Expression(new Lexer(input));
|
|
|
+ return new Lexer(input).Expression(this);
|
|
|
}
|
|
|
|
|
|
private Value StringExpression()
|
|
|
{
|
|
|
Lexer.Type = LexerType.String;
|
|
|
GetNextToken();
|
|
|
- var result = Expression(Lexer, Tokens, LexerType.String);
|
|
|
+ var result = Lexer.Expression(this);
|
|
|
Lexer.Type = LexerType.Real;
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
-
|
|
|
- private Value Expression(Lexer lexer, IEnumerator<Token> enumerator = null, LexerType type = LexerType.Real)
|
|
|
- {
|
|
|
- Stack<Value> stack = new Stack<Value>();
|
|
|
- Stack<Token> operators = new Stack<Token>();
|
|
|
-
|
|
|
- if (enumerator == null)
|
|
|
- {
|
|
|
- enumerator = lexer.GetTokens().GetEnumerator();
|
|
|
- enumerator.MoveNext();
|
|
|
- }
|
|
|
-
|
|
|
- void Operation(Token token)
|
|
|
- {
|
|
|
- Value b = stack.Pop();
|
|
|
- Value a = stack.Pop();
|
|
|
- Value result = a.Operate(b, token);
|
|
|
- stack.Push(result);
|
|
|
- }
|
|
|
-
|
|
|
- int i = 0;
|
|
|
- while (true)
|
|
|
- {
|
|
|
- if (enumerator.Current == Token.Value)
|
|
|
- {
|
|
|
- stack.Push(lexer.Value);
|
|
|
- }
|
|
|
- else if (enumerator.Current == Token.Identifer)
|
|
|
- {
|
|
|
- if (Variables.ContainsKey(lexer.Identifer))
|
|
|
- {
|
|
|
- string varName = lexer.Identifer;
|
|
|
- int index = 0;
|
|
|
- enumerator.MoveNext();
|
|
|
- if (enumerator.Current == Token.Colon)
|
|
|
- {
|
|
|
- enumerator.MoveNext();
|
|
|
- index = (int)Expression(lexer, enumerator).Real;
|
|
|
- }
|
|
|
-
|
|
|
- stack.Push(Variables[varName, index]);
|
|
|
-
|
|
|
- i++;
|
|
|
- continue;
|
|
|
- }
|
|
|
- else if (FunctionDictionary.ContainsKey(lexer.Identifer))
|
|
|
- {
|
|
|
- string name = lexer.Identifer;
|
|
|
- List<Value> args = new List<Value>();
|
|
|
- enumerator.MoveNext();
|
|
|
-
|
|
|
- if (enumerator.Current != Token.LParen)
|
|
|
- Error($"Was expecting [LParen] got [{enumerator.Current}]");
|
|
|
-
|
|
|
- while (enumerator.MoveNext() && enumerator.Current != Token.RParen)
|
|
|
- {
|
|
|
- args.Add(Expression(lexer, enumerator, type));
|
|
|
- if (enumerator.Current != Token.Comma)
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- stack.Push(FunctionDictionary[name](args));
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- if (type == LexerType.String)
|
|
|
- stack.Push(lexer.Identifer);
|
|
|
- else
|
|
|
- Error("Undeclared variable " + lexer.Identifer);
|
|
|
- }
|
|
|
- }
|
|
|
- else if (enumerator.Current == Token.LParen)
|
|
|
- {
|
|
|
- enumerator.MoveNext();
|
|
|
- stack.Push(Expression(lexer, enumerator, type));
|
|
|
-
|
|
|
- if (enumerator.Current != Token.RParen)
|
|
|
- Error($"Was expecting [LParen] got [{enumerator.Current}]");
|
|
|
- }
|
|
|
- else if (type == LexerType.Real && enumerator.Current.IsArithmetic()
|
|
|
- && enumerator.Current.IsUnary() && (i == 0 || previousToken == Token.LParen))
|
|
|
- {
|
|
|
- stack.Push(0);
|
|
|
- operators.Push(enumerator.Current);
|
|
|
- }
|
|
|
- else if (type == LexerType.String && enumerator.Current.IsStringOp()
|
|
|
- || type == LexerType.Real && enumerator.Current.IsArithmetic())
|
|
|
- {
|
|
|
- while (operators.Count > 0 && OrderOfOps[enumerator.Current] <= OrderOfOps[operators.Peek()])
|
|
|
- Operation(operators.Pop());
|
|
|
- operators.Push(enumerator.Current);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- if (i == 0)
|
|
|
- {
|
|
|
- if (type == LexerType.String)
|
|
|
- stack.Push("");
|
|
|
- else
|
|
|
- Error("Empty expression");
|
|
|
- }
|
|
|
-
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- i++;
|
|
|
- enumerator.MoveNext();
|
|
|
- }
|
|
|
-
|
|
|
- while (operators.Count > 0)
|
|
|
- Operation(operators.Pop());
|
|
|
-
|
|
|
- return type == LexerType.String
|
|
|
- ? stack.Aggregate((a, b) => b.String + a.String)
|
|
|
- : stack.Pop();
|
|
|
- }
|
|
|
}
|
|
|
}
|