|
@@ -1,6 +1,7 @@
|
|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Linq;
|
|
|
+using System.Text;
|
|
|
|
|
|
namespace NTERA.Interpreter.Compiler
|
|
|
{
|
|
@@ -103,7 +104,7 @@ namespace NTERA.Interpreter.Compiler
|
|
|
{
|
|
|
enumerator.MoveNext();
|
|
|
|
|
|
- defaultValue = lexer.ConstantExpression();
|
|
|
+ defaultValue = ConstantExpression(lexer);
|
|
|
|
|
|
//enumerator.MoveNext();
|
|
|
}
|
|
@@ -177,7 +178,7 @@ namespace NTERA.Interpreter.Compiler
|
|
|
{
|
|
|
enumerator.MoveNext();
|
|
|
|
|
|
- defaultValue = lexer.ConstantExpression();
|
|
|
+ defaultValue = ConstantExpression(lexer);
|
|
|
}
|
|
|
else if (enumerator.Current != Token.NewLine
|
|
|
&& enumerator.Current != Token.EOF)
|
|
@@ -338,5 +339,88 @@ namespace NTERA.Interpreter.Compiler
|
|
|
|
|
|
//AddVariableIndices(Path.GetFileNameWithoutExtension(filename));
|
|
|
}
|
|
|
+
|
|
|
+ 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 }
|
|
|
+ };
|
|
|
+
|
|
|
+ public static Value ConstantExpression(Lexer lexer)
|
|
|
+ {
|
|
|
+ IEnumerator<Token> currentEnumerator = lexer.GetEnumerator();
|
|
|
+
|
|
|
+ Stack<Value> stack = new Stack<Value>();
|
|
|
+ Stack<Token> operators = new Stack<Token>();
|
|
|
+
|
|
|
+ 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 (currentEnumerator.Current == Token.Value)
|
|
|
+ {
|
|
|
+ stack.Push(lexer.Value);
|
|
|
+ }
|
|
|
+ else if (currentEnumerator.Current == Token.QuotationMark)
|
|
|
+ {
|
|
|
+ StringBuilder builder = new StringBuilder();
|
|
|
+ char stringChar;
|
|
|
+
|
|
|
+ while ((stringChar = lexer.GetNextChar()) != '"')
|
|
|
+ builder.Append(stringChar);
|
|
|
+
|
|
|
+ stack.Push(builder.ToString());
|
|
|
+ }
|
|
|
+ else if (currentEnumerator.Current == Token.Identifer)
|
|
|
+ {
|
|
|
+ throw new ParserException("Undeclared variable " + lexer.Identifier, lexer.TokenMarker);
|
|
|
+ }
|
|
|
+ else if (currentEnumerator.Current == Token.LParen)
|
|
|
+ {
|
|
|
+ currentEnumerator.MoveNext();
|
|
|
+ stack.Push(ConstantExpression(lexer));
|
|
|
+
|
|
|
+ if (currentEnumerator.Current != Token.RParen)
|
|
|
+ throw new ParserException($"Was expecting [LParen] got [{currentEnumerator.Current}]", lexer.TokenMarker);
|
|
|
+ }
|
|
|
+ else if (currentEnumerator.Current.IsArithmetic() && currentEnumerator.Current.IsUnary() && i == 0)
|
|
|
+ {
|
|
|
+ stack.Push(0);
|
|
|
+ operators.Push(currentEnumerator.Current);
|
|
|
+ }
|
|
|
+ else if (currentEnumerator.Current.IsArithmetic())
|
|
|
+ {
|
|
|
+ while (operators.Count > 0 && OrderOfOps[currentEnumerator.Current] <= OrderOfOps[operators.Peek()])
|
|
|
+ Operation(operators.Pop());
|
|
|
+ operators.Push(currentEnumerator.Current);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (i == 0)
|
|
|
+ throw new ParserException("Empty expression", lexer.TokenMarker);
|
|
|
+
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ i++;
|
|
|
+ currentEnumerator.MoveNext();
|
|
|
+ }
|
|
|
+
|
|
|
+ while (operators.Count > 0)
|
|
|
+ Operation(operators.Pop());
|
|
|
+
|
|
|
+ return stack.Pop();
|
|
|
+ }
|
|
|
}
|
|
|
}
|