예제 #1
0
        public bool Execute(string line)
        {
            if (string.IsNullOrWhiteSpace(line))
                return false;

            // remove comments
            int firstCommentIndex = line.IndexOf(commentChar);
            if (firstCommentIndex >= 0)
                line = line.Substring(0, firstCommentIndex);

            if (string.IsNullOrWhiteSpace(line))
                return false;

            // split by white space
            var matches = splitRegex.Matches(line);

            foreach (Match m in matches)
            {
                word = m.Value;

                #region Values, Definition, WordSet-Recording
                if (TryPushString())
                    continue;
                if (TryPushInt())
                    continue;
                if (TryPushNameDef())
                    continue;
                if (Record())
                    continue;
                #endregion

                #region Word evaluation switch-statement
                switch (word)
                {
                    #region Reset / Clear
                    case "clear":
                        recordStack.Clear();
                        stack.Clear();
                        dictionary.Clear();
                        break;
                    case "delstack":
                        stack.Clear();
                        break;
                    case "deldict":
                        dictionary.Clear();
                        break;
                    case "ccon":
                        Console.Clear();
                        break;
                    #endregion
                    #region Output
                    case ".":
                        Pop1();
                        Console.Write(a1.Value);
                        break;
                    case "h":
                        CheckType1(FTType.Int);
                        Console.Write("0x{0:x}", (int)a1.Value);
                        break;
                    case "pstack":
                        Console.WriteLine("----------------------------\r\nStack    Count: {0}", stack.Count);
                        for (int i = 0; i < stack.Count; i++)
                        {
                            a1 = stack.ElementAt(i);
                            if (a1.Type == FTType.String)
                                Console.WriteLine("{0} ->\tString:\t\"{1}\"", i, a1.Value);
                            else if (a1.Type == FTType.Int)
                                Console.WriteLine("{0} ->\tInt:\t{1}", i, a1.Value);
                            else if (a1.Type == FTType.Bool)
                                Console.WriteLine("{0} ->\tBool:\t{1}", i, a1.Value);
                            else
                                Console.WriteLine("{0} ->\t{1}", i, a1.Value);
                        }
                        Console.WriteLine("----------------------------");
                        break;
                    case "pdict":
                        Console.WriteLine("----------------------------\r\nDict    Count: {0}", dictionary.Count);
                        for (int i = 0; i < dictionary.Count; i++)
                        {
                            string key = dictionary.Keys.ElementAt(i);
                            a1 = dictionary[key];

                            Console.WriteLine("{0}\t->\t{1}", key, a1.Value);
                        }
                        Console.WriteLine("----------------------------");
                        break;
                    case "cr":
                        Console.WriteLine();
                        break;
                    #endregion
                    #region Integer Manipulation
                    case "+":
                        CheckType2(FTType.Int);
                        stack.Push(FTType.Int, (int)a1.Value + (int)a2.Value);
                        break;
                    case "-":
                        CheckType2(FTType.Int);
                        stack.Push(FTType.Int, (int)a2.Value - (int)a1.Value);
                        break;
                    case "*":
                        CheckType2(FTType.Int);
                        stack.Push(FTType.Int, (int)a1.Value * (int)a2.Value);
                        break;
                    case "/":
                        CheckType2(FTType.Int);
                        stack.Push(FTType.Int, (int)a2.Value / (int)a1.Value);
                        break;
                    case "mod":
                        CheckType2(FTType.Int);
                        stack.Push(FTType.Int, (int)a2.Value % (int)a1.Value);
                        break;
                    #endregion
                    #region Stack Manipulation
                    case "dup":
                        if (stack.Count == 0)
                            throw new FTStackUnderFlowException("'dup': no items on stack.");
                        stack.Push(stack.Peek());
                        break;
                    case "swap":
                        Pop2();
                        stack.Push(a1);
                        stack.Push(a2);
                        break;
                    case "drop":
                        Pop1();
                        break;
                    #endregion
                    #region Definition
                    case "def":
                        Pop2();
                        if (a2.Type == FTType.NameDef)
                        {
                            string name = a2.Value as string;
                            if (dictionary.ContainsKey(name))
                                dictionary[name] = a1;
                            else
                                dictionary.Add(name, a1);
                        }
                        else
                            throw new FTWrongTypeException("'def': second top most object of stack has to be of type 'NameDef'.");
                        break;
                    case "undef":
                        CheckType1(FTType.NameDef);
                        string val = a1.Value as string;
                        if (dictionary.ContainsKey(val))
                            dictionary.Remove(val);
                        else
                            throw new FTUnexpectedSymbolException("variable '{0}' not defined in dictionary.");
                        break;
                    #endregion
                    #region WordSet
                    case "{":
                        recordStack.Push(RecordMode.Wordset);
                        stack.Push(FTType.StartSet, recordStack.Count);
                        break;
                    case "}":
                        if (recordStack.Count <= 0 || stack.Count <= 0)
                            throw new FTUnexpectedSymbolException("'}': Stack empty.");
                        break;
                    #endregion
                    #region Values
                    case "true":
                    case "false":
                        stack.Push(FTType.Bool, bool.Parse(word));
                        break;
                    #endregion
                    #region Integer Comparison
                    case "neg":
                        CheckType1(FTType.Int);
                        stack.Push(FTType.Int, -(int)a1.Value);
                        break;
                    case "=":
                        CheckType2(FTType.Int);
                        stack.Push(FTType.Bool, (int)a1.Value == (int)a2.Value);
                        break;
                    case ">":
                        CheckType2(FTType.Int);
                        stack.Push(FTType.Bool, (int)a2.Value > (int)a1.Value);
                        break;
                    case "<":
                        CheckType2(FTType.Int);
                        stack.Push(FTType.Bool, (int)a2.Value < (int)a1.Value);
                        break;
                    #endregion
                    #region Bool Comparison
                    case "not":
                        CheckType1(FTType.Bool);
                        stack.Push(FTType.Bool, !(bool)a1.Value);
                        break;
                    case "and":
                        CheckType2(FTType.Bool);
                        stack.Push(FTType.Bool, (bool)a1.Value && (bool)a2.Value);
                        break;
                    case "or":
                        CheckType2(FTType.Bool);
                        stack.Push(FTType.Bool, (bool)a1.Value || (bool)a2.Value);
                        break;
                    #endregion
                    #region Flow Control
                    case "if":
                        CheckType2(FTType.WordSet, FTType.Bool);
                        if ((bool)a2.Value)
                            ExecuteWordSet((FTWordSet)a1.Value);
                        break;
                    case "ifelse":
                        CheckType3(FTType.WordSet, FTType.WordSet, FTType.Bool);
                        if ((bool)a3.Value)
                            ExecuteWordSet((FTWordSet)a2.Value);
                        else
                            ExecuteWordSet((FTWordSet)a1.Value);
                        break;
                    #endregion
                    #region Files
                    case "exec":
                        CheckType1(FTType.String);
                        ExecuteFile(a1.Value as string);
                        break;
                    #endregion
                    #region Input
                    case "linein":
                        stack.Push(FTType.String, Console.ReadLine());
                        break;
                    #endregion
                    #region String Manipulation
                    case "len":
                        CheckType1(FTType.String);
                        stack.Push(FTType.Int, (a1.Value as string).Length);
                        break;
                    case "concat":
                        CheckType2(FTType.String);
                        stack.Push(FTType.String, (string)a2.Value + (string)a1.Value);
                        break;
                    case "comp":
                        CheckType2(FTType.String);
                        stack.Push(FTType.Bool, ((string)a1.Value).Equals(a2.Value as string));
                        break;
                    case "trim":
                        CheckType1(FTType.String);
                        stack.Push(FTType.String, ((string)a1.Value).Trim());
                        break;
                    case "getchar":
                        CheckType2(FTType.Int, FTType.String);
                        stack.Push(FTType.Int, (int)((string)a2.Value)[(int)a1.Value]);
                        break;
                    case "substr":
                        CheckType3(FTType.Int, FTType.Int, FTType.String);
                        stack.Push(FTType.String, ((string)a3.Value).Substring((int)a2.Value, (int)a1.Value));
                        break;
                    #endregion
                    #region Loops
                    case "repeat":
                        CheckType2(FTType.WordSet, FTType.Int);
                        int num = (int)a2.Value;
                        FTWordSet s = (FTWordSet)a1.Value;
                        for (int i = 0; i < num; i++)
                            ExecuteWordSet(s);
                        break;
                    case "while":
                        CheckType2(FTType.WordSet, FTType.Bool);
                        bool cond = (bool)a2.Value;
                        FTWordSet set = (FTWordSet)a1.Value;
                        while (cond)
                        {
                            ExecuteWordSet(set);
                            CheckType1(FTType.Bool);
                            cond = (bool)a1.Value;
                        }
                        break;
                    #endregion
                    #region Coversion
                    case "tostr":
                        Pop1();
                        if (a1.Type != FTType.Int && a1.Type != FTType.Bool)
                            throw new FTWrongTypeException(string.Format("'tostr': object to convert is of type {0}.\r\ncan only parse types Int and Bool.", a1.Type));
                        stack.Push(FTType.String, a1.Value.ToString().ToLower());
                        break;
                    case "tobool":
                        CheckType1(FTType.Int);
                        stack.Push(FTType.Bool, (int)a1.Value != 0);
                        break;
                    #endregion
                    #region List
                    case "list":
                        stack.Push(FTType.List, new FTList());
                        break;
                    case "count":
                        Peek1();
                        if (a1.Type != FTType.List)
                            throw new FTWrongTypeException("'count' expects top object of stack to be from type FTList.");
                        stack.Push(FTType.Int, ((FTList)a1.Value).Count);
                        break;
                    case "add":
                        Pop2();
                        if (a2.Type != FTType.List)
                            throw new FTWrongTypeException("'add': second top most object of stack has to be of type FTList.");
                        ((FTList)a2.Value).Add(a1);
                        stack.Push(FTType.List, a2.Value);
                        break;
                    case "get":
                        CheckType2(FTType.Int, FTType.List);
                        stack.Push(FTType.List, a2.Value);
                        // TODO: add IndexOutOfBounds check and exception
                        stack.Push(((FTList)a2.Value)[(int)a1.Value]);
                        break;
                    case "set":
                        Pop3();
                        if (a3.Type != FTType.List || a1.Type != FTType.Int)
                            throw new FTWrongTypeException(word);
                        // TODO: add IndexOutOfBounds check and exception
                        ((FTList)a3.Value)[(int)a1.Value] = a2;
                        stack.Push(FTType.List, a3.Value);
                        break;
                    case "remove":
                        CheckType2(FTType.Int, FTType.List);
                        stack.Push(FTType.List, a2.Value);
                        // TODO: add IndexOutOfBounds check and exception
                        ((FTList)a2.Value).RemoveAt((int)a1.Value);
                        break;
                    case "[":
                        recordStack.Push(RecordMode.List);
                        stack.Push(FTType.StartList, recordStack.Count);
                        break;
                    case "]":
                        if (recordStack.Count <= 0 || stack.Count <= 0)
                            throw new FTUnexpectedSymbolException("']': Stack empty.");
                        break;
                    #endregion
                    case "quit":
                        return true;
                        break;
                    #region default
                    default:
                        if (dictionary.ContainsKey(word))
                        {
                            FTObject v = dictionary[word];
                            if (v.Type == FTType.WordSet)
                                ExecuteWordSet((FTWordSet)v.Value);
                            else
                                stack.Push(v);
                            continue;
                        }

                        throw new FTUnknownSymbolException(string.Format("Unable to parse symbol: '{0}'", word));
                        break;
                    #endregion
                }
                #endregion
            }
            return false;
        }
예제 #2
0
 private void Pop1()
 {
     if (stack.Count == 0)
         throw new FTStackUnderFlowException(string.Format("Command '{0}' tried to pop 1 Object.", word));
     a1 = stack.Pop();
 }
예제 #3
0
        private void Pop3()
        {
            if (stack.Count < 3)
                throw new FTStackUnderFlowException(string.Format("Command '{0}' tried to pop 3 Objects.", word));

            a1 = stack.Pop();
            a2 = stack.Pop();
            a3 = stack.Pop();
        }
예제 #4
0
 private void Execute(FTObject obj)
 {
     switch (obj.Type)
     {
         case FTType.Bool:
         case FTType.Int:
         case FTType.String:
         case FTType.NameDef:
         case FTType.WordSet:
             stack.Push(obj);
             break;
         case FTType.Word:
             Execute((string)obj.Value);
             break;
     }
 }