|
@@ -13,7 +13,7 @@ namespace NTERA.Interpreter
|
|
|
private Token prevToken;
|
|
|
private Token lastToken;
|
|
|
|
|
|
- private Dictionary<string, Value> vars;
|
|
|
+ public readonly Dictionary<string, Value> Variables;
|
|
|
private Dictionary<string, Marker> loops;
|
|
|
|
|
|
public delegate Value BasicFunction(List<Value> args);
|
|
@@ -30,7 +30,7 @@ namespace NTERA.Interpreter
|
|
|
{
|
|
|
this.console = console;
|
|
|
lex = new Lexer(input);
|
|
|
- vars = new Dictionary<string, Value>();
|
|
|
+ Variables = new Dictionary<string, Value>();
|
|
|
loops = new Dictionary<string, Marker>();
|
|
|
ifcounter = 0;
|
|
|
|
|
@@ -40,15 +40,15 @@ namespace NTERA.Interpreter
|
|
|
|
|
|
public Value GetVar(string name)
|
|
|
{
|
|
|
- if (!vars.ContainsKey(name))
|
|
|
+ if (!Variables.ContainsKey(name))
|
|
|
throw new Exception("Variable with name " + name + " does not exist.");
|
|
|
- return vars[name];
|
|
|
+ return Variables[name];
|
|
|
}
|
|
|
|
|
|
public void SetVar(string name, Value val)
|
|
|
{
|
|
|
- if (!vars.ContainsKey(name)) vars.Add(name, val);
|
|
|
- else vars[name] = val;
|
|
|
+ if (!Variables.ContainsKey(name)) Variables.Add(name, val);
|
|
|
+ else Variables[name] = val;
|
|
|
}
|
|
|
|
|
|
void Error(string text)
|
|
@@ -163,25 +163,6 @@ namespace NTERA.Interpreter
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- [BuiltInFunction("str")]
|
|
|
- private Value Str(List<Value> args)
|
|
|
- {
|
|
|
- if (args.Count < 1)
|
|
|
- throw new ArgumentException();
|
|
|
-
|
|
|
- return args[0].Convert(ValueType.String);
|
|
|
- }
|
|
|
-
|
|
|
- [BuiltInFunction("num")]
|
|
|
- private Value Num(List<Value> args)
|
|
|
- {
|
|
|
- if (args.Count < 1)
|
|
|
- throw new ArgumentException();
|
|
|
-
|
|
|
- return args[0].Convert(ValueType.Real);
|
|
|
- }
|
|
|
-
|
|
|
[BuiltInFunction("abs")]
|
|
|
private Value Abs(List<Value> args)
|
|
|
{
|
|
@@ -241,7 +222,7 @@ namespace NTERA.Interpreter
|
|
|
|
|
|
foreach (var method in typeof(Interpreter).GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
|
|
|
{
|
|
|
- var attribute = method.GetCustomAttributes(typeof(TargetKeywordAttribute), true).FirstOrDefault() as TargetKeywordAttribute;
|
|
|
+ var attribute = method.GetCustomAttributes(typeof(KeywordMethodAttribute), true).FirstOrDefault() as KeywordMethodAttribute;
|
|
|
|
|
|
if (attribute == null)
|
|
|
continue;
|
|
@@ -251,27 +232,27 @@ namespace NTERA.Interpreter
|
|
|
}
|
|
|
|
|
|
|
|
|
- [TargetKeyword(Token.Print)]
|
|
|
+ [KeywordMethod(Token.Print)]
|
|
|
void Print()
|
|
|
{
|
|
|
console.Write(Expr().ToString());
|
|
|
}
|
|
|
|
|
|
- [TargetKeyword(Token.PrintL)]
|
|
|
+ [KeywordMethod(Token.PrintL)]
|
|
|
void PrintL()
|
|
|
{
|
|
|
console.PrintSingleLine(Expr().ToString());
|
|
|
}
|
|
|
|
|
|
|
|
|
- [TargetKeyword(Token.PrintImg)]
|
|
|
+ [KeywordMethod(Token.PrintImg)]
|
|
|
void PrintImg()
|
|
|
{
|
|
|
console.PrintImg(Expr().ToString().Trim().Trim('"'));
|
|
|
}
|
|
|
|
|
|
|
|
|
- [TargetKeyword(Token.PrintButton)]
|
|
|
+ [KeywordMethod(Token.PrintButton)]
|
|
|
void PrintButton()
|
|
|
{
|
|
|
console.PrintButton(Expr().ToString(), 0);
|
|
@@ -279,32 +260,32 @@ namespace NTERA.Interpreter
|
|
|
|
|
|
private static readonly Regex FormRegex = new Regex("{(.*?)}");
|
|
|
|
|
|
- [TargetKeyword(Token.PrintFormL)]
|
|
|
+ [KeywordMethod(Token.PrintFormL)]
|
|
|
void PrintFormL()
|
|
|
{
|
|
|
string rawString = Expr().ToString();
|
|
|
|
|
|
- var evaluator = new MatchEvaluator(match => vars[match.Groups[1].Value].ToString());
|
|
|
+ var evaluator = new MatchEvaluator(match => Variables[match.Groups[1].Value].ToString());
|
|
|
|
|
|
console.PrintSingleLine(FormRegex.Replace(rawString, evaluator));
|
|
|
}
|
|
|
|
|
|
- [TargetKeyword(Token.DrawLine)]
|
|
|
+ [KeywordMethod(Token.DrawLine)]
|
|
|
void DrawLine()
|
|
|
{
|
|
|
console.PrintBar();
|
|
|
}
|
|
|
|
|
|
- [TargetKeyword(Token.DrawLineForm)]
|
|
|
+ [KeywordMethod(Token.DrawLineForm)]
|
|
|
void DrawLineForm()
|
|
|
{
|
|
|
console.printCustomBar(Expr().ToString().Trim());
|
|
|
}
|
|
|
|
|
|
- [TargetKeyword(Token.If)]
|
|
|
+ [KeywordMethod(Token.If)]
|
|
|
private void If()
|
|
|
{
|
|
|
- bool result = Expr().BinOp(new Value(0), Token.Equal).Real == 1;
|
|
|
+ bool result = Expr().Real == 1;
|
|
|
|
|
|
Match(Token.Then);
|
|
|
GetNextToken();
|
|
@@ -340,7 +321,7 @@ namespace NTERA.Interpreter
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- [TargetKeyword(Token.Else)]
|
|
|
+ [KeywordMethod(Token.Else)]
|
|
|
private void Else()
|
|
|
{
|
|
|
int i = ifcounter;
|
|
@@ -363,19 +344,19 @@ namespace NTERA.Interpreter
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- [TargetKeyword(Token.EndIf)]
|
|
|
+ [KeywordMethod(Token.EndIf)]
|
|
|
private void EndIf()
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
- [TargetKeyword(Token.End)]
|
|
|
+ [KeywordMethod(Token.End)]
|
|
|
private void End()
|
|
|
{
|
|
|
exit = true;
|
|
|
}
|
|
|
|
|
|
- [TargetKeyword(Token.Let)]
|
|
|
+ [KeywordMethod(Token.Let)]
|
|
|
private void Let()
|
|
|
{
|
|
|
if (lastToken != Token.Equal)
|
|
@@ -392,7 +373,7 @@ namespace NTERA.Interpreter
|
|
|
SetVar(id, Expr());
|
|
|
}
|
|
|
|
|
|
- [TargetKeyword(Token.For)]
|
|
|
+ [KeywordMethod(Token.For)]
|
|
|
private void For()
|
|
|
{
|
|
|
Match(Token.Identifer);
|
|
@@ -419,7 +400,7 @@ namespace NTERA.Interpreter
|
|
|
GetNextToken();
|
|
|
v = Expr();
|
|
|
|
|
|
- if (vars[var].BinOp(v, Token.More).Real == 1)
|
|
|
+ if (Variables[var].Operate(v, Token.More).Real == 1)
|
|
|
{
|
|
|
while (true)
|
|
|
{
|
|
@@ -435,17 +416,17 @@ namespace NTERA.Interpreter
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- [TargetKeyword(Token.Next)]
|
|
|
+ [KeywordMethod(Token.Next)]
|
|
|
private void Next()
|
|
|
{
|
|
|
Match(Token.Identifer);
|
|
|
string var = lex.Identifer;
|
|
|
- vars[var] = vars[var].BinOp(new Value(1), Token.Plus);
|
|
|
+ Variables[var] = Variables[var].Operate(new Value(1), Token.Plus);
|
|
|
lex.GoTo(new Marker(loops[var].Pointer - 1, loops[var].Line, loops[var].Column - 1));
|
|
|
lastToken = Token.NewLine;
|
|
|
}
|
|
|
|
|
|
- [TargetKeyword(Token.Times)]
|
|
|
+ [KeywordMethod(Token.Times)]
|
|
|
private void Times()
|
|
|
{
|
|
|
Match(Token.Identifer);
|
|
@@ -458,7 +439,7 @@ namespace NTERA.Interpreter
|
|
|
GetNextToken();
|
|
|
var arg2 = Expr();
|
|
|
|
|
|
- vars[var] = vars[var].BinOp(arg2, Token.Asterisk);
|
|
|
+ Variables[var] = Variables[var].Operate(arg2, Token.Asterisk);
|
|
|
|
|
|
Match(Token.NewLine);
|
|
|
}
|
|
@@ -471,15 +452,15 @@ namespace NTERA.Interpreter
|
|
|
{
|
|
|
Match(Token.Identifer);
|
|
|
|
|
|
- if (!vars.ContainsKey(lex.Identifer)) vars.Add(lex.Identifer, new Value());
|
|
|
+ if (!Variables.ContainsKey(lex.Identifer)) Variables.Add(lex.Identifer, new Value());
|
|
|
|
|
|
console.WaitInput(new Core.Interop.InputRequest() { InputType = Core.Interop.InputType.StrValue });
|
|
|
string input = console.LastInput;
|
|
|
double d;
|
|
|
if (double.TryParse(input, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out d))
|
|
|
- vars[lex.Identifer] = new Value(d);
|
|
|
+ Variables[lex.Identifer] = new Value(d);
|
|
|
else
|
|
|
- vars[lex.Identifer] = new Value(input);
|
|
|
+ Variables[lex.Identifer] = new Value(input);
|
|
|
|
|
|
GetNextToken();
|
|
|
if (lastToken != Token.Comma) break;
|
|
@@ -487,18 +468,18 @@ namespace NTERA.Interpreter
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- Value Expr()
|
|
|
+ private static readonly Dictionary<Token, int> OrderOfOps = new Dictionary<Token, int>()
|
|
|
{
|
|
|
- Dictionary<Token, int> prec = 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 }
|
|
|
- };
|
|
|
+ { 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 }
|
|
|
+ };
|
|
|
|
|
|
+ Value Expr()
|
|
|
+ {
|
|
|
Stack<Value> stack = new Stack<Value>();
|
|
|
Stack<Token> operators = new Stack<Token>();
|
|
|
|
|
@@ -511,9 +492,9 @@ namespace NTERA.Interpreter
|
|
|
}
|
|
|
else if (lastToken == Token.Identifer)
|
|
|
{
|
|
|
- if (vars.ContainsKey(lex.Identifer))
|
|
|
+ if (Variables.ContainsKey(lex.Identifer))
|
|
|
{
|
|
|
- stack.Push(vars[lex.Identifer]);
|
|
|
+ stack.Push(Variables[lex.Identifer]);
|
|
|
}
|
|
|
else if (FunctionDictionary.ContainsKey(lex.Identifer))
|
|
|
{
|
|
@@ -521,13 +502,12 @@ namespace NTERA.Interpreter
|
|
|
List<Value> args = new List<Value>();
|
|
|
GetNextToken();
|
|
|
Match(Token.LParen);
|
|
|
-
|
|
|
- start:
|
|
|
- if (GetNextToken() != Token.RParen)
|
|
|
+
|
|
|
+ while (GetNextToken() != Token.RParen)
|
|
|
{
|
|
|
args.Add(Expr());
|
|
|
- if (lastToken == Token.Comma)
|
|
|
- goto start;
|
|
|
+ if (lastToken != Token.Comma)
|
|
|
+ break;
|
|
|
}
|
|
|
|
|
|
stack.Push(FunctionDictionary[name](args));
|
|
@@ -543,17 +523,17 @@ namespace NTERA.Interpreter
|
|
|
stack.Push(Expr());
|
|
|
Match(Token.RParen);
|
|
|
}
|
|
|
- else if (lastToken >= Token.Plus && lastToken <= Token.Not)
|
|
|
+ else if (lastToken.IsArithmetic())
|
|
|
{
|
|
|
- if ((lastToken == Token.Minus || lastToken == Token.Minus) && (i == 0 || prevToken == Token.LParen))
|
|
|
+ if (lastToken.IsUnary() && (i == 0 || prevToken == Token.LParen))
|
|
|
{
|
|
|
- stack.Push(new Value(0));
|
|
|
+ stack.Push(0);
|
|
|
operators.Push(lastToken);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- while (operators.Count > 0 && prec[lastToken] <= prec[operators.Peek()])
|
|
|
- Operation(ref stack, operators.Pop());
|
|
|
+ while (operators.Count > 0 && OrderOfOps[lastToken] <= OrderOfOps[operators.Peek()])
|
|
|
+ Operation(stack, operators.Pop());
|
|
|
operators.Push(lastToken);
|
|
|
}
|
|
|
}
|
|
@@ -569,16 +549,16 @@ namespace NTERA.Interpreter
|
|
|
}
|
|
|
|
|
|
while (operators.Count > 0)
|
|
|
- Operation(ref stack, operators.Pop());
|
|
|
+ Operation(stack, operators.Pop());
|
|
|
|
|
|
return stack.Pop();
|
|
|
}
|
|
|
|
|
|
- void Operation(ref Stack<Value> stack, Token token)
|
|
|
+ void Operation(Stack<Value> stack, Token token)
|
|
|
{
|
|
|
Value b = stack.Pop();
|
|
|
Value a = stack.Pop();
|
|
|
- Value result = a.BinOp(b, token);
|
|
|
+ Value result = a.Operate(b, token);
|
|
|
stack.Push(result);
|
|
|
}
|
|
|
}
|