Browse Source

Split out keywords and functions into separate files

Bepis 6 years ago
parent
commit
52e59eb86c

+ 29 - 331
NTERA.Interpreter/Interpreter.cs

@@ -1,8 +1,5 @@
 using System;
 using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-using System.Text.RegularExpressions;
 using NTERA.Core;
 
 namespace NTERA.Interpreter
@@ -38,27 +35,22 @@ namespace NTERA.Interpreter
             GenerateFunctionDictionary();
         }
 
-        public Value GetVar(string name)
+        private void Error(string text)
         {
-            if (!Variables.ContainsKey(name))
-                throw new Exception("Variable with name " + name + " does not exist.");
-            return Variables[name];
+            throw new Exception(text + " at line: " + lineMarker.Line);
         }
 
-        public void SetVar(string name, Value val)
+        protected bool TryAssertNextToken(Token tok, bool pullNext = true)
         {
-            if (!Variables.ContainsKey(name)) Variables.Add(name, val);
-            else Variables[name] = val;
-        }
+            if (pullNext)
+                GetNextToken();
 
-        void Error(string text)
-        {
-            throw new Exception(text + " at line: " + lineMarker.Line);
+            return lastToken == tok;
         }
 
-        void Match(Token tok)
+        protected void AssertToken(Token tok, bool pullNext = true)
         {
-            if (lastToken != tok)
+            if (!TryAssertNextToken(tok, pullNext))
                 Error("Expect " + tok + " got " + lastToken);
         }
 
@@ -71,10 +63,12 @@ namespace NTERA.Interpreter
             tokens = lex.GetTokens().GetEnumerator();
 
             GetNextToken();
-            while (!exit) Line();
+
+            while (!exit)
+                Line();
         }
 
-        Token GetNextToken()
+        protected Token GetNextToken()
         {
             prevToken = lastToken;
 
@@ -87,7 +81,7 @@ namespace NTERA.Interpreter
             return lastToken;
         }
 
-        void Line()
+        private void Line()
         {
             while (lastToken == Token.NewLine) GetNextToken();
 
@@ -98,13 +92,13 @@ namespace NTERA.Interpreter
             }
 
             lineMarker = lex.TokenMarker;
-            Statment();
+            Statement();
 
             if (lastToken != Token.NewLine && lastToken != Token.EOF)
                 Error("Expect new line got " + lastToken);
         }
 
-        void Statment()
+        private void Statement()
         {
             Token keyword = lastToken;
             GetNextToken();
@@ -140,317 +134,20 @@ namespace NTERA.Interpreter
             if (lastToken == Token.Colon)
             {
                 GetNextToken();
-                Statment();
+                Statement();
             }
         }
-
-        #region Functions
         
-        private Dictionary<string, BasicFunction> FunctionDictionary { get; set; }
-
-        private void GenerateFunctionDictionary()
-        {
-            FunctionDictionary = new Dictionary<string, BasicFunction>(StringComparer.InvariantCultureIgnoreCase);
-
-            foreach (var method in typeof(Interpreter).GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
-            {
-                var attribute = method.GetCustomAttributes(typeof(BuiltInFunctionAttribute), true).FirstOrDefault() as BuiltInFunctionAttribute;
-
-                if (attribute == null)
-                    continue;
-
-                FunctionDictionary[attribute.Name] = args => (Value)method.Invoke(this, new object[] { args });
-            }
-        }
-
-        [BuiltInFunction("abs")]
-        private Value Abs(List<Value> args)
-        {
-            if (args.Count < 1)
-                throw new ArgumentException();
-
-            return new Value(Math.Abs(args[0].Real));
-        }
-
-        [BuiltInFunction("min")]
-        private Value Min(List<Value> args)
-        {
-            if (args.Count < 2)
-                throw new ArgumentException();
-
-            return new Value(Math.Min(args[0].Real, args[1].Real));
-        }
-
-        [BuiltInFunction("max")]
-        private Value Max(List<Value> args)
-        {
-            if (args.Count < 2)
-                throw new ArgumentException();
-
-            return new Value(Math.Max(args[0].Real, args[1].Real));
-        }
-
-        [BuiltInFunction("not")]
-        private Value Not(List<Value> args)
-        {
-            if (args.Count < 1)
-                throw new ArgumentException();
-
-            return new Value(args[0].Real == 0 ? 1 : 0);
-        }
-
-        private readonly Random random = new Random();
-
-        [BuiltInFunction("rand")]
-        private Value Rand(List<Value> args)
-        {
-            if (args.Count < 2)
-                throw new ArgumentException();
-
-            return new Value(random.Next((int)args[0].Real, (int)args[1].Real - 1));
-        }
-
-        #endregion
-
-        #region Keywords
-
-        private Dictionary<Token, Action> KeywordMethods { get; set; }
-
-        private void GenerateKeywordDictionary()
-        {
-            KeywordMethods = new Dictionary<Token, Action>();
-
-            foreach (var method in typeof(Interpreter).GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
-            {
-                var attribute = method.GetCustomAttributes(typeof(KeywordMethodAttribute), true).FirstOrDefault() as KeywordMethodAttribute;
-
-                if (attribute == null)
-                    continue;
-
-                KeywordMethods[attribute.Token] = () => method.Invoke(this, null);
-            }
-        }
-
-
-        [KeywordMethod(Token.Print)]
-        void Print()
-        {
-            console.Write(Expr().ToString());
-        }
-
-        [KeywordMethod(Token.PrintL)]
-        void PrintL()
-        {
-            console.PrintSingleLine(Expr().ToString());
-        }
-
-
-        [KeywordMethod(Token.PrintImg)]
-        void PrintImg()
-        {
-            console.PrintImg(Expr().ToString().Trim().Trim('"'));
-        }
-
-
-        [KeywordMethod(Token.PrintButton)]
-        void PrintButton()
-        {
-            console.PrintButton(Expr().ToString(), 0);
-        }
-
-        private static readonly Regex FormRegex = new Regex("{(.*?)}");
-
-        [KeywordMethod(Token.PrintFormL)]
-        void PrintFormL()
-        {
-            string rawString = Expr().ToString();
-
-            var evaluator = new MatchEvaluator(match => Variables[match.Groups[1].Value].ToString());
-
-            console.PrintSingleLine(FormRegex.Replace(rawString, evaluator));
-        }
-
-        [KeywordMethod(Token.DrawLine)]
-        void DrawLine()
-        {
-            console.PrintBar();
-        }
-
-        [KeywordMethod(Token.DrawLineForm)]
-        void DrawLineForm()
-        {
-            console.printCustomBar(Expr().ToString().Trim());
-        }
-
-        [KeywordMethod(Token.If)]
-        private void If()
-        {
-            bool result = Expr().Real == 1;
-
-            Match(Token.Then);
-            GetNextToken();
-
-            if (result)
-            {
-                int i = ifcounter;
-                while (true)
-                {
-                    if (lastToken == Token.If)
-                    {
-                        i++;
-                    }
-                    else if (lastToken == Token.Else)
-                    {
-                        if (i == ifcounter)
-                        {
-                            GetNextToken();
-                            return;
-                        }
-                    }
-                    else if (lastToken == Token.EndIf)
-                    {
-                        if (i == ifcounter)
-                        {
-                            GetNextToken();
-                            return;
-                        }
-                        i--;
-                    }
-                    GetNextToken();
-                }
-            }
-        }
-
-        [KeywordMethod(Token.Else)]
-        private void Else()
-        {
-            int i = ifcounter;
-            while (true)
-            {
-                if (lastToken == Token.If)
-                {
-                    i++;
-                }
-                else if (lastToken == Token.EndIf)
-                {
-                    if (i == ifcounter)
-                    {
-                        GetNextToken();
-                        return;
-                    }
-                    i--;
-                }
-                GetNextToken();
-            }
-        }
+        public Dictionary<string, BasicFunction> FunctionDictionary { get; protected set; }
 
-        [KeywordMethod(Token.EndIf)]
-        private void EndIf()
-        {
+        public Dictionary<Token, Action> KeywordMethods { get; set; }
 
-        }
 
-        [KeywordMethod(Token.End)]
-        private void End()
-        {
-            exit = true;
-        }
-
-        [KeywordMethod(Token.Let)]
-        private void Let()
-        {
-            if (lastToken != Token.Equal)
-            {
-                Match(Token.Identifer);
-                GetNextToken();
-                Match(Token.Equal);
-            }
-
-            string id = lex.Identifer;
-
-            GetNextToken();
-
-            SetVar(id, Expr());
-        }
-
-        [KeywordMethod(Token.For)]
-        private void For()
-        {
-            Match(Token.Identifer);
-            string var = lex.Identifer;
-
-            GetNextToken();
-            Match(Token.Equal);
-
-            GetNextToken();
-            Value v = Expr();
-
-            if (loops.ContainsKey(var))
-            {
-                loops[var] = lineMarker;
-            }
-            else
-            {
-                SetVar(var, v);
-                loops.Add(var, lineMarker);
-            }
-
-            Match(Token.To);
-
-            GetNextToken();
-            v = Expr();
-
-            if (Variables[var].Operate(v, Token.More).Real == 1)
-            {
-                while (true)
-                {
-                    while (!(GetNextToken() == Token.Identifer && prevToken == Token.Next)) ;
-                    if (lex.Identifer == var)
-                    {
-                        loops.Remove(var);
-                        GetNextToken();
-                        Match(Token.NewLine);
-                        break;
-                    }
-                }
-            }
-        }
-
-        [KeywordMethod(Token.Next)]
-        private void Next()
-        {
-            Match(Token.Identifer);
-            string var = lex.Identifer;
-            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;
-        }
-
-        [KeywordMethod(Token.Times)]
-        private void Times()
-        {
-            Match(Token.Identifer);
-
-            string var = lex.Identifer;
-
-            GetNextToken();
-            Match(Token.Comma);
-
-            GetNextToken();
-            var arg2 = Expr();
-
-            Variables[var] = Variables[var].Operate(arg2, Token.Asterisk);
-            
-            Match(Token.NewLine);
-        }
-
-        #endregion
-
-        void Input()
+        private void Input()
         {
             while (true)
             {
-                Match(Token.Identifer);
+                AssertToken(Token.Identifer);
                
                 if (!Variables.ContainsKey(lex.Identifer)) Variables.Add(lex.Identifer, new Value());
 
@@ -462,13 +159,14 @@ namespace NTERA.Interpreter
                 else
                     Variables[lex.Identifer] = new Value(input);
                 
-                GetNextToken();
-                if (lastToken != Token.Comma) break;
+                if (!TryAssertNextToken(Token.Comma))
+                    break;
+
                 GetNextToken();
             }
         }
 
-        private static readonly Dictionary<Token, int> OrderOfOps = new Dictionary<Token, int>()
+        private static readonly Dictionary<Token, int> OrderOfOps = new Dictionary<Token, int>
         {
             { Token.Or, 0 }, { Token.And, 0 },
             { Token.Equal, 1 }, { Token.NotEqual, 1 },
@@ -478,7 +176,7 @@ namespace NTERA.Interpreter
             { Token.Caret, 4 }
         };
 
-        Value Expr()
+        private Value Expr()
         {
             Stack<Value> stack = new Stack<Value>();
             Stack<Token> operators = new Stack<Token>();
@@ -501,9 +199,9 @@ namespace NTERA.Interpreter
                         string name = lex.Identifer;
                         List<Value> args = new List<Value>();
                         GetNextToken();
-                        Match(Token.LParen);
+                        AssertToken(Token.LParen, false);
                         
-                        while (GetNextToken() != Token.RParen)
+                        while (!TryAssertNextToken(Token.RParen))
                         {
                             args.Add(Expr());
                             if (lastToken != Token.Comma)
@@ -521,7 +219,7 @@ namespace NTERA.Interpreter
                 {
                     GetNextToken();
                     stack.Push(Expr());
-                    Match(Token.RParen);
+                    AssertToken(Token.RParen, false);
                 }
                 else if (lastToken.IsArithmetic())
                 {
@@ -554,7 +252,7 @@ namespace NTERA.Interpreter
             return stack.Pop();
         }
 
-        void Operation(Stack<Value> stack, Token token)
+        private void Operation(Stack<Value> stack, Token token)
         {
             Value b = stack.Pop();
             Value a = stack.Pop();

+ 72 - 0
NTERA.Interpreter/Interpreter/BuiltInFunctions.cs

@@ -0,0 +1,72 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace NTERA.Interpreter
+{
+    public partial class Interpreter
+    {
+        private void GenerateFunctionDictionary()
+        {
+            FunctionDictionary = new Dictionary<string, BasicFunction>(StringComparer.InvariantCultureIgnoreCase);
+
+            foreach (var method in typeof(Interpreter).GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
+            {
+                var attribute = (BuiltInFunctionAttribute)method.GetCustomAttributes(typeof(BuiltInFunctionAttribute), true).FirstOrDefault();
+
+                if (attribute == null)
+                    continue;
+
+                FunctionDictionary[attribute.Name] = args => (Value)method.Invoke(this, new object[] { args });
+            }
+        }
+
+        [BuiltInFunction("abs")]
+        private Value Abs(List<Value> args)
+        {
+            if (args.Count < 1)
+                throw new ArgumentException();
+
+            return new Value(Math.Abs(args[0].Real));
+        }
+
+        [BuiltInFunction("min")]
+        private Value Min(List<Value> args)
+        {
+            if (args.Count < 2)
+                throw new ArgumentException();
+
+            return new Value(Math.Min(args[0].Real, args[1].Real));
+        }
+
+        [BuiltInFunction("max")]
+        private Value Max(List<Value> args)
+        {
+            if (args.Count < 2)
+                throw new ArgumentException();
+
+            return new Value(Math.Max(args[0].Real, args[1].Real));
+        }
+
+        [BuiltInFunction("not")]
+        private Value Not(List<Value> args)
+        {
+            if (args.Count < 1)
+                throw new ArgumentException();
+
+            return new Value(args[0].Real == 0 ? 1 : 0);
+        }
+
+        private readonly Random random = new Random();
+
+        [BuiltInFunction("rand")]
+        private Value Rand(List<Value> args)
+        {
+            if (args.Count < 2)
+                throw new ArgumentException();
+
+            return new Value(random.Next((int)args[0].Real, (int)args[1].Real - 1));
+        }
+    }
+}

+ 236 - 0
NTERA.Interpreter/Interpreter/Keywords.cs

@@ -0,0 +1,236 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text.RegularExpressions;
+
+namespace NTERA.Interpreter
+{
+    public partial class Interpreter
+    {
+        private void GenerateKeywordDictionary()
+        {
+            KeywordMethods = new Dictionary<Token, Action>();
+
+            foreach (var method in typeof(Interpreter).GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
+            {
+                var attribute = method.GetCustomAttributes(typeof(KeywordMethodAttribute), true).FirstOrDefault() as KeywordMethodAttribute;
+
+                if (attribute == null)
+                    continue;
+
+                KeywordMethods[attribute.Token] = () => method.Invoke(this, null);
+            }
+        }
+
+
+        [KeywordMethod(Token.Print)]
+        private void Print()
+        {
+            console.Write(Expr().ToString());
+        }
+
+        [KeywordMethod(Token.PrintL)]
+        private void PrintL()
+        {
+            console.PrintSingleLine(Expr().ToString());
+        }
+
+
+        [KeywordMethod(Token.PrintImg)]
+        private void PrintImg()
+        {
+            console.PrintImg(Expr().ToString().Trim().Trim('"'));
+        }
+
+
+        [KeywordMethod(Token.PrintButton)]
+        private void PrintButton()
+        {
+            console.PrintButton(Expr().ToString(), 0);
+        }
+
+        private static readonly Regex FormRegex = new Regex("{(.*?)}");
+
+        [KeywordMethod(Token.PrintFormL)]
+        private void PrintFormL()
+        {
+            string rawString = Expr().ToString();
+
+            var evaluator = new MatchEvaluator(match => Variables[match.Groups[1].Value].ToString());
+
+            console.PrintSingleLine(FormRegex.Replace(rawString, evaluator));
+        }
+
+        [KeywordMethod(Token.DrawLine)]
+        private void DrawLine()
+        {
+            console.PrintBar();
+        }
+
+        [KeywordMethod(Token.DrawLineForm)]
+        private void DrawLineForm()
+        {
+            console.printCustomBar(Expr().ToString().Trim());
+        }
+
+        [KeywordMethod(Token.If)]
+        private void If()
+        {
+            bool result = Expr().Real == 1;
+
+            AssertToken(Token.Then, false);
+            GetNextToken();
+
+            if (result)
+            {
+                int i = ifcounter;
+                while (true)
+                {
+                    if (lastToken == Token.If)
+                    {
+                        i++;
+                    }
+                    else if (lastToken == Token.Else)
+                    {
+                        if (i == ifcounter)
+                        {
+                            GetNextToken();
+                            return;
+                        }
+                    }
+                    else if (lastToken == Token.EndIf)
+                    {
+                        if (i == ifcounter)
+                        {
+                            GetNextToken();
+                            return;
+                        }
+                        i--;
+                    }
+                    GetNextToken();
+                }
+            }
+        }
+
+        [KeywordMethod(Token.Else)]
+        private void Else()
+        {
+            int i = ifcounter;
+            while (true)
+            {
+                if (lastToken == Token.If)
+                {
+                    i++;
+                }
+                else if (lastToken == Token.EndIf)
+                {
+                    if (i == ifcounter)
+                    {
+                        GetNextToken();
+                        return;
+                    }
+                    i--;
+                }
+                GetNextToken();
+            }
+        }
+
+        [KeywordMethod(Token.EndIf)]
+        private void EndIf()
+        {
+
+        }
+
+        [KeywordMethod(Token.End)]
+        private void End()
+        {
+            exit = true;
+        }
+
+        [KeywordMethod(Token.Let)]
+        private void Let()
+        {
+            if (lastToken != Token.Equal)
+            {
+                AssertToken(Token.Identifer, false);
+                AssertToken(Token.Equal);
+            }
+
+            string id = lex.Identifer;
+
+            GetNextToken();
+
+            Variables[id] = Expr();
+        }
+
+        [KeywordMethod(Token.For)]
+        private void For()
+        {
+            AssertToken(Token.Identifer, false);
+            string var = lex.Identifer;
+
+            AssertToken(Token.Equal);
+
+            GetNextToken();
+            Value v = Expr();
+
+            if (loops.ContainsKey(var))
+            {
+                loops[var] = lineMarker;
+            }
+            else
+            {
+                Variables[var] = v;
+                loops.Add(var, lineMarker);
+            }
+
+            AssertToken(Token.To, false);
+
+            GetNextToken();
+            v = Expr();
+
+            if (Variables[var].Operate(v, Token.More).Real == 1)
+            {
+                while (true)
+                {
+                    while (!(GetNextToken() == Token.Identifer && prevToken == Token.Next)) { }
+
+                    if (lex.Identifer == var)
+                    {
+                        loops.Remove(var);
+                        AssertToken(Token.NewLine);
+                        break;
+                    }
+                }
+            }
+        }
+
+        [KeywordMethod(Token.Next)]
+        private void Next()
+        {
+            AssertToken(Token.Identifer, false);
+            string var = lex.Identifer;
+            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;
+        }
+
+        [KeywordMethod(Token.Times)]
+        private void Times()
+        {
+            AssertToken(Token.Identifer, false);
+
+            string var = lex.Identifer;
+
+            AssertToken(Token.Comma);
+
+            GetNextToken();
+            var arg2 = Expr();
+
+            Variables[var] = Variables[var].Operate(arg2, Token.Asterisk);
+
+            AssertToken(Token.NewLine, false);
+        }
+    }
+}

+ 2 - 0
NTERA.Interpreter/NTERA.Interpreter.csproj

@@ -41,6 +41,8 @@
     <Compile Include="Attributes.cs" />
     <Compile Include="Engine.cs" />
     <Compile Include="Interpreter.cs" />
+    <Compile Include="Interpreter\BuiltInFunctions.cs" />
+    <Compile Include="Interpreter\Keywords.cs" />
     <Compile Include="Lexer.cs" />
     <Compile Include="Marker.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />