コード例 #1
0
 /// <summary>
 /// Проверка строки с операцией INC
 /// </summary>
 /// <param name="se">строка с операцией INC</param>
 public static void checkINC(SourceEntity se, TMOEntity te)
 {
     if (!String.IsNullOrEmpty(se.label))
     {
         throw new SPException("В директиве INC метки не должно быть: " + se.sourceString);
     }
     if (se.operands.Count == 1)
     {
         if (!Global.isInGlobal(se.operands[0]))
         {
             throw new SPException("Некорректное имя глобальной переменной: " + se.sourceString);
         }
         if (Global.searchInGlobal(se.operands[0]).value == null)
         {
             throw new SPException("Глобальной переменной " + se.operands[0] + " не присвоено значение.");
         }
         foreach (Dictionary <List <string>, TMOEntity> dict in Global.whileVar)
         {
             if (dict.Keys.First().Contains(se.operands[0]) && dict.Values.First() != te)
             {
                 throw new SPException("Глобальная переменная " + se.operands[0] + " используется как счетчик в цикле: " + se.sourceString);
             }
         }
     }
     else
     {
         throw new SPException("Некорректное количество операндов в директиве INC: " + se.sourceString);
     }
 }
コード例 #2
0
ファイル: TMOEntity.cs プロジェクト: StarkyLife/spo-program
 /// <summary>
 /// Проверка вложенностей
 /// </summary>
 /// <param name="current"></param>
 /// <param name="stack"></param>
 public static void checkInner(SourceEntity current, Stack <Command> stack)
 {
     if (current.operation == "IF")
     {
         return;
     }
     if (current.operation == "ELSE")
     {
         if (stack.Count > 0 && stack.Peek() != Command.if_)
         {
             throw new SPException("Некорректное использование директивы ELSE");
         }
         return;
     }
     if (current.operation == "ENDIF")
     {
         if (stack.Count > 0 && stack.Peek() != Command.if_ && stack.Peek() != Command.else_)
         {
             throw new SPException("Некорректное использование директивы ENDIF");
         }
         return;
     }
     if (current.operation == "WHILE")
     {
         return;
     }
     if (current.operation == "ENDW")
     {
         if (stack.Count > 0 && stack.Peek() != Command.while_)
         {
             throw new SPException("Некорректное использование директивы ENDW");
         }
         return;
     }
 }
コード例 #3
0
 /// <summary>
 /// Проверка строки с операцией SET
 /// </summary>
 /// <param name="se">строка с операцией SET</param>
 public static void checkSET(SourceEntity se, TMOEntity te)
 {
     if (!String.IsNullOrEmpty(se.label))
     {
         throw new SPException("В директиве SET метки не должно быть: " + se.sourceString);
     }
     if (se.operands.Count == 2)
     {
         if (!Global.isInGlobal(se.operands[0]))
         {
             throw new SPException("Некорректное имя глобальной переменной: " + se.sourceString);
         }
         int temp;
         if (Int32.TryParse(se.operands[1], out temp) == false)
         {
             throw new SPException("Некорректное значение глобальной переменной: " + se.sourceString);
         }
         foreach (Dictionary <List <string>, TMOEntity> dict in Global.whileVar)
         {
             if (dict.Keys.First().Contains(se.operands[0]) && dict.Values.First() != te)
             {
                 throw new SPException("Глобальная переменная " + se.operands[0] + " используется как счетчик в цикле: " + se.sourceString);
             }
         }
     }
     else
     {
         throw new SPException("Некорректное количество операндов в директиве SET: " + se.sourceString);
     }
 }
コード例 #4
0
 /// <summary>
 /// Проверка на метку (может быть пустая или много двоеточий)
 /// </summary>
 /// <param name="se">строка с операцией меткой</param>
 public static void checkLabel(SourceEntity se)
 {
     if (se.sourceString.Split(':').Length > 2 && se.operation != "BYTE")
     {
         throw new SPException("Слишком много двоеточий в строке: " + se.sourceString);
     }
     if (se.sourceString.Split(':').Length > 1 && String.IsNullOrEmpty(se.sourceString.Split(':')[0]))
     {
         throw new SPException("Слишком много двоеточий в строке: " + se.sourceString);
     }
 }
コード例 #5
0
        /// <summary>
        /// Проверка строки с операцией MACRO
        /// </summary>
        /// <param name="se">строка с операцией MACRO</param>
        public static void checkMACRO(SourceEntity se, bool macroFlag)
        {
            if (se.sourceString.Contains(":"))
            {
                throw new SPException("При объявлении макроса не должно быть меток: " + se.sourceString);
            }
            if (String.IsNullOrEmpty(se.label) || !Utils.isLabel(se.label))
            {
                throw new SPException("Имя макроса некорректно: " + se.sourceString);
            }
            if (TMO.isInTMO(se.label))
            {
                throw new SPException("Макрос " + se.label + " уже описан: " + se.sourceString);
            }
            //if (macroFlag == true)
            //{
            //    throw new SPException("Макроопределения внутри макроса запрещены: " + se.sourceString);
            //}
            //if (se.operands.Count != 0)
            //{
            //    throw new SPException("У макроса не должно быть параметров: " + se.sourceString);
            //}

            foreach (string o in se.operands)
            {
                if (se.operands.Count(p => p == o) > 1)
                {
                    throw new SPException("Имя параметра \"" + o + "\" повторяется: " + se.sourceString);
                }
                if (!Utils.isLabel(o))
                {
                    throw new SPException("Имя параметра \"" + o + "\" некорректно: " + se.sourceString);
                }
                foreach (TMOEntity te in TMO.entities)
                {
                    foreach (string par in te.parameters)
                    {
                        if (par == o)
                        {
                            throw new SPException("Имя параметра " + o + " уже используется в другом макросе: " + se.sourceString);
                        }
                    }
                }
                Utils.checkNames(o);
                if (o == se.label)
                {
                    throw new SPException("Имя параметра " + o + " некорректно (совпадает с названием макроса): " + se.sourceString);
                }
            }

            Utils.checkNames(se.label);
        }
コード例 #6
0
 /// <summary>
 /// Проверка строки с операцией MEND
 /// </summary>
 /// <param name="se">строка с операцией MEND</param>
 public static void checkMEND(SourceEntity se, bool macroFlag)
 {
     if (se.operands.Count != 0)
     {
         throw new SPException("У директивы MEND не должно быть параметров: " + se.sourceString);
     }
     if (!String.IsNullOrEmpty(se.label))
     {
         throw new SPException("У директивы MEND не должно быть метки: " + se.sourceString);
     }
     if (macroFlag == false)
     {
         throw new SPException("Лишняя директива MEND: " + se.sourceString);
     }
 }
コード例 #7
0
 /// <summary>
 /// Проверка строки с операцией END
 /// </summary>
 /// <param name="se">строка с операцией END</param>
 public static void checkEND(SourceEntity se, bool macroFlag, string macroName)
 {
     if (macroFlag == true)
     {
         throw new SPException("Макрос " + macroName + " не описан полностью: " + se.sourceString);
     }
     //foreach (TMOEntity te in TMO.entities)
     //{
     //    foreach (SourceEntity sse in te.body)
     //    {
     //        if (TMO.isInTMO(sse.operation))
     //        {
     //            throw new SPException("Макровызовы внутри макроса запрещены");
     //        }
     //    }
     //}
 }
コード例 #8
0
ファイル: Utils.cs プロジェクト: StarkyLife/spo-program
        public static SourceEntity print(SourceEntity str)
        {
            SourceEntity newStr = str.Clone();

            for (int j = 0; j < newStr.operands.Count; j++)
            {
                if (Global.isInGlobal(newStr.operands[j]))
                {
                    if (Global.searchInGlobal(newStr.operands[j]).value.HasValue)
                    {
                        newStr.operands[j] = Global.searchInGlobal(newStr.operands[j]).value.Value.ToString();
                    }
                    else
                    {
                        throw new SPException("Глобальная переменная " + newStr.operands[j] + " не инициализирована.");
                    }
                }
            }
            return(newStr);
        }
コード例 #9
0
 /// <summary>
 /// Проверка строки с операцией GLOBAL
 /// </summary>
 /// <param name="se">строка с операцией GLOBAL</param>
 public static void checkGLOBAL(SourceEntity se)
 {
     //if (macroFlag == true)
     //{
     //    throw new SPException("Глобальные переменные нельзя объявлять в макросе");
     //}
     if (se.operands.Count > 0 && Global.isInGlobal(se.operands[0]))
     {
         throw new SPException("Повторное задание глобальной переменной: " + se.sourceString);
     }
     if (!String.IsNullOrEmpty(se.label))
     {
         throw new SPException("В описании глобальной переменной метки не нужны: " + se.sourceString);
     }
     if (se.operands.Count == 2)
     {
         if (!Utils.isLabel(se.operands[0]))
         {
             throw new SPException("Некорректное имя глобальной переменной: " + se.sourceString);
         }
         int temp;
         if (Int32.TryParse(se.operands[1], out temp) == false)
         {
             throw new SPException("Некорректное значение глобальной переменной: " + se.sourceString);
         }
     }
     else if (se.operands.Count == 1)
     {
         if (!Utils.isLabel(se.operands[0]))
         {
             throw new SPException("Некорректное имя глобальной переменной: " + se.sourceString);
         }
     }
     else
     {
         throw new SPException("Некорректное количество операндов в директиве GLOBAL: " + se.sourceString);
     }
     Utils.checkNames(se.operands[0]);
 }
コード例 #10
0
        /// <summary>
        /// Проверка макроподстановки
        /// </summary>
        public static void checkMacroSubstitution(SourceEntity se, TMOEntity te)
        {
            if (se.operands.Count != te.parameters.Count)
            {
                throw new SPException("Некорректное количество параметров. Введено: " + se.operands.Count + ". Ожидается: " + te.parameters.Count);
            }
            //if (se.operands.Count != 0)
            //{
            //    throw new SPException("Вызов макроса не должен содержать параметров: " + se.sourceString);
            //}
            if (!String.IsNullOrEmpty(se.label))
            {
                throw new SPException("При макровызове макроса не должно быть меток: " + se.sourceString);
            }

            int temp; string[] vals = null;

            foreach (string prm in se.operands)
            {
                vals = prm.Split('=');
                if (vals.Length != 2)
                {
                    throw new SPException("Параметр '" + prm + "'. Параметры определены некорректно, разделители между '=', названием и значением параметра недопустимы.");
                }

                if (!Global.isInGlobal(vals[1]) && !Int32.TryParse(vals[1], out temp))
                {
                    throw new SPException("Параметр '" + vals[0] + "' имеет некорректное значение (" + vals[1] + ")");
                }
                if (Global.isInGlobal(vals[1]) && Global.searchInGlobal(vals[1]).value == null)
                {
                    throw new SPException("Параметр '" + vals[0] + "' - неинициализованная глобальная переменная");
                }
            }
            //if (!String.IsNullOrEmpty(se.label))
            //{
            //    throw new SPException("При макровызове макрса не должно быть меток: " + se.sourceString);
            //}
        }
コード例 #11
0
 /// <summary>
 /// Проверка макроподстановки
 /// </summary>
 public static void checkMacroRun(SourceEntity se, TMOEntity parent, TMOEntity child)
 {
     //TMOEntity current = parent;
     //List<TMOEntity> list = new List<TMOEntity>();
     //while (current.prev != null)
     //{
     //    if (list.Contains(current))
     //    {
     //        throw new SPException("Перекрестные ссылки и рекурсия запрещены.");
     //    }
     //    list.Add(current);
     //    current = current.prev;
     //}
     if (TMO.isInTMO(child.name) && parent.name == child.name)
     {
         throw new SPException("Макрос \"" + child.name + "\" не может быть вызван из себя (Рекурсия запрещена).");
     }
     //if (TMO.isInTMO(child.name) && !parent.localTMO.Contains(child))
     //{
     //    throw new SPException("Макрос " + child.name + " не входит в область видимости " +
     //        (parent.name == "root" ? "основной программы" : "тела макроса " + parent.name) + ".");
     //}
 }
コード例 #12
0
        /// <summary>
        /// Шаг первого прохода
        /// </summary>
        public void firstRunStep(SourceEntity se, TMOEntity te)
        {
            String        operation = se.operation;
            String        label     = se.label;
            List <String> operands  = se.operands;

            try
            {
                CheckSourceEntity.checkLabel(se);
                if (operation == "END")
                {
                    CheckSourceEntity.checkEND(se, this.macroFlag, this.macroName);
                    result.Add(Utils.print(se));
                }
                else if (operation == "GLOBAL" && this.macroFlag == false)
                {
                    CheckSourceEntity.checkGLOBAL(se);
                    if (operands.Count == 1)
                    {
                        Global.entities.Add(new GlobalEntity(operands[0], null));
                    }
                    else
                    {
                        Global.entities.Add(new GlobalEntity(operands[0], Int32.Parse(operands[1])));
                    }
                }
                else if (operation == "SET" && this.macroFlag == false)
                {
                    CheckSourceEntity.checkSET(se, te);
                    Global.searchInGlobal(se.operands[0]).value = Int32.Parse(se.operands[1]);
                }
                else if (operation == "INC" && this.macroFlag == false)
                {
                    CheckSourceEntity.checkINC(se, te);
                    Global.searchInGlobal(operands[0]).value++;
                }
                else if (operation == "MACRO")
                {
                    if (te != TMO.root)
                    {
                        throw new SPException("Макроопределения внутри макросов запрещены");
                    }
                    CheckSourceEntity.checkMACRO(se, macroFlag);

                    TMO.entities.Add(new TMOEntity()
                    {
                        name = label, parameters = se.operands
                    });
                    this.macroFlag = true;
                    this.macroName = label;
                }
                else if (operation == "MEND")
                {
                    if (te != TMO.root)
                    {
                        throw new SPException("Макроопределения внутри макросов запрещены");
                    }
                    CheckSourceEntity.checkMEND(se, macroFlag);

                    foreach (SourceEntity mc in mbMacroCall)
                    {
                        if (mc.operation == this.macroName)
                        {
                            TMOEntity currentTe = TMO.searchInTMO(this.macroName);
                            CheckSourceEntity.checkMacroSubstitution(mc, currentTe);
                            List <SourceEntity> res = CheckBody.checkMacroBody(currentTe, operands);
                            // результат макроподстановки
                            List <SourceEntity> macroSubs = new List <SourceEntity>();
                            foreach (SourceEntity str in res)
                            {
                                macroSubs.Add(Utils.print(str));
                            }
                            // Заменяем в результате макровызов на результат макроподстановки
                            for (int i = 0; i < this.result.Count; i++)
                            {
                                if (this.result[i].operation == mc.operation && this.result[i].isRemove == "true")
                                {
                                    this.result.Remove(this.result[i]);
                                    this.result.InsertRange(i, macroSubs);
                                    i += macroSubs.Count - 1;
                                }
                            }
                        }
                    }

                    TMOEntity curTe = TMO.searchInTMO(this.macroName);
                    curTe.IsFinished = true;

                    var prevTe = TMO.GetPrevNotFinishedMacro();
                    if (prevTe != null)
                    {
                        this.macroFlag = true;
                        this.macroName = prevTe.name;
                    }
                    else
                    {
                        this.macroFlag = false;
                        this.macroName = null;
                    }
                }
                else
                {
                    if (this.macroFlag == true)
                    {
                        TMO.searchInTMO(this.macroName).body.Add(se);
                    }
                    else
                    {
                        if (te == TMO.root && (operation == "WHILE" || operation == "ENDW"))
                        {
                            throw new SPException("Использование директивы " + operation + " возможно только в теле макроса: " + se.sourceString);
                        }
                        // макровызов
                        if (TMO.isInTMO(operation))
                        {
                            TMOEntity currentTe = TMO.searchInTMO(operation);
                            CheckSourceEntity.checkMacroSubstitution(se, currentTe);
                            CheckBody.checkMacroRun(se, te, currentTe);

                            List <SourceEntity> res = CheckBody.checkMacroBody(currentTe, operands);
                            foreach (SourceEntity str in res)
                            {
                                result.Add(Utils.print(str));
                            }

                            //if (te == TMO.root)
                            //{

                            //}
                            //else
                            //{
                            //    throw new SPException("Макровызовы внутри макроса запрещены");
                            //}
                        }
                        else
                        {
                            // Добавляем строку в список подозрительных на макровызов и в результат
                            se = Utils.print(se);
                            if (te == TMO.root && macroFlag == false)
                            {
                                se.isRemove = "true";
                                mbMacroCall.Add(se);
                            }
                            result.Add(se);
                        }
                    }
                }
            }
            catch (SPException ex)
            {
                throw new SPException(ex.Message);
            }
        }
コード例 #13
0
ファイル: CodeParser.cs プロジェクト: StarkyLife/spo-program
        /// <summary>
        /// Парсит массив строк в масссив SourceEntity, но только до появления первого END в качестве операции
        /// </summary>
        public static List <SourceEntity> parse(string[] strs)
        {
            List <SourceEntity> result = new List <SourceEntity>();

            foreach (string s in strs)
            {
                // пропускаем пустую строку
                if (String.IsNullOrEmpty(s.Trim()))
                {
                    continue;
                }
                string       currentString = s.ToUpper().Trim();
                SourceEntity se            = new SourceEntity()
                {
                    sourceString = currentString
                };

                //разборка метки
                if (currentString.Contains(':') && (!currentString.Contains("BYTE") || currentString.IndexOf(':') < currentString.IndexOf("C'")))
                {
                    se.label      = currentString.Split(':')[0].Trim();
                    currentString = currentString.Remove(0, currentString.Split(':')[0].Length + 1).Trim();
                }

                if (currentString.Split(null as char[], StringSplitOptions.RemoveEmptyEntries).Length > 0)
                {
                    se.operation  = currentString.Split(null as char[], StringSplitOptions.RemoveEmptyEntries)[0].Trim();
                    currentString = currentString.Remove(0, currentString.Split(null as char[], StringSplitOptions.RemoveEmptyEntries)[0].Length).Trim();
                }

                if (se.operation == "BYTE")
                {
                    se.operands.Add(currentString.Trim());
                }
                else
                {
                    for (int i = 0; i < currentString.Split(null as char[], StringSplitOptions.RemoveEmptyEntries).Length; i++)
                    {
                        se.operands.Add(currentString.Split(null as char[], StringSplitOptions.RemoveEmptyEntries)[i].Trim());
                    }
                }

                //название проги или макроса - в поле метки
                if (se.operands.Count > 0 && se.operands[0] == "MACRO")
                {
                    se.label     = se.operation;
                    se.operation = se.operands[0];
                    for (int i = 1; i < se.operands.Count; i++)
                    {
                        se.operands[i - 1] = se.operands[i];
                    }
                    se.operands.RemoveAt(se.operands.Count - 1);
                }
                result.Add(se);

                //Читаем только до энда
                if (se.operation == "END")
                {
                    return(result);
                }
            }

            return(result);
        }
コード例 #14
0
ファイル: TMOEntity.cs プロジェクト: StarkyLife/spo-program
        public List <SourceEntity> invoke(string[] prms)
        {
            // Подставим значения параметров
            List <SourceEntity> newBody = CheckMacros.InvokeMacroParams(this, prms);

            SourceCode   sc      = new SourceCode(newBody);
            SourceEntity current = null;

            // проверки
            CheckMacros.CheckMacroLabels(this);

            //заменяем метки на "крутые" уникальные метки
            this.local = new Dictionary <string, int?>();
            foreach (SourceEntity se in sc.entities)
            {
                current = se.Clone();
                if (!String.IsNullOrEmpty(current.label))
                {
                    if (!Utils.isLabel(current.label))
                    {
                        throw new SPException("Некорректное задание метки в макросе: " + se.sourceString);
                    }
                    Utils.checkNames(current.label);
                    if (this.local.Keys.Contains(current.label))
                    {
                        throw new SPException("Повторное задание метки в макросе: " + se.sourceString);
                    }
                    this.local.Add(current.label, null);
                }
            }

            // исполнять ли команду дальше
            Stack <bool> runStack = new Stack <bool>();

            runStack.Push(true);
            // стек комманд, появлявшихся ранее
            Stack <Command> commandStack = new Stack <Command>();
            // стек строк, куда надо вернуться при while
            Stack <int> whileStack = new Stack <int>();
            //
            bool elseFlag;

            for (int i = 0; i < sc.entities.Count; i++)
            {
                this.counter++;
                if (this.counter == 1000000)
                {
                    throw new SPException("Обнаружен бесконечный цикл");
                }

                current = newBody[i].Clone();
                CheckMacros.checkInner(current, commandStack);

                #region IF
                //if (current.operation == "IF")
                //{
                //    CheckMacros.checkIF(this);
                //    commandStack.Push(Command.if_);
                //    runStack.Push(runStack.Peek() && Utils.compare(current.operands[0]));
                //    continue;
                //}
                //if (current.operation == "ELSE")
                //{
                //    CheckMacros.checkIF(this);
                //    commandStack.Pop();
                //    commandStack.Push(Command.else_);
                //    elseFlag = runStack.Pop();
                //    runStack.Push(runStack.Peek() && !elseFlag);
                //    continue;
                //}
                //if (current.operation == "ENDIF")
                //{
                //    CheckMacros.checkIF(this);
                //    commandStack.Pop();
                //    runStack.Pop();
                //    continue;
                //}
                #endregion

                if (current.operation == "WHILE")
                {
                    CheckMacros.checkWhileEndw(this);
                    commandStack.Push(Command.while_);
                    runStack.Push(runStack.Peek() && Utils.compare(current.operands[0]));
                    whileStack.Push(i);
                    continue;
                }
                if (current.operation == "ENDW")
                {
                    CheckMacros.checkWhileEndw(this);
                    commandStack.Pop();
                    int newI = whileStack.Pop() - 1;
                    if (runStack.Pop())
                    {
                        i = newI;
                    }
                    continue;
                }

                #region AIF AGO

                //if (current.operation == "AIF" && Utils.compare(current.operands[0]) || current.operation == "AGO")
                //{
                //    CheckMacros.checkAIF(this);
                //    if (runStack.Peek())
                //    {
                //        string label = current.operation == "AIF" ? current.operands[1] : current.operands[0];
                //        // находим метку, чтобы туда прыгнуть
                //        bool ready = false;
                //        Stack<bool> agoStack = new Stack<bool>();
                //        // вверх
                //        for (int j = i; j >= 0; j--)
                //        {
                //            if (this.body[j].operation == "IF" || this.body[j].operation == "WHILE")
                //            {
                //                if (agoStack.Count > 0)
                //                {
                //                    agoStack.Pop();
                //                }
                //            }
                //            if (this.body[j].operation == "ELSE")
                //            {
                //                if (agoStack.Count > 0)
                //                {
                //                    agoStack.Pop();
                //                }
                //                agoStack.Push(false);
                //            }
                //            if (this.body[j].operation == "ENDIF" || this.body[j].operation == "ENDW")
                //            {
                //                agoStack.Push(false);
                //            }
                //            if (this.body[j].label == label && (agoStack.Count == 0 || agoStack.Peek()))
                //            {
                //                i = j - 1;
                //                ready = true;
                //                break;
                //            }
                //        }

                //        // вниз
                //        if (!ready)
                //        {
                //            for (int j = i; j < this.body.Count; j++)
                //            {
                //                if (this.body[j].operation == "IF" || this.body[j].operation == "WHILE")
                //                {
                //                    agoStack.Push(false);
                //                }
                //                if (this.body[j].operation == "ELSE")
                //                {
                //                    if (agoStack.Count > 0)
                //                    {
                //                        agoStack.Pop();
                //                    }
                //                    agoStack.Push(false);
                //                }
                //                if (this.body[j].operation == "ENDIF" || this.body[j].operation == "ENDW")
                //                {
                //                    if (agoStack.Count > 0)
                //                    {
                //                        agoStack.Pop();
                //                    }
                //                }
                //                if (this.body[j].label == label && (agoStack.Count == 0 || agoStack.Peek()))
                //                {
                //                    i = j - 1;
                //                    ready = true;
                //                    break;
                //                }
                //            }
                //        }
                //        if (!ready)
                //        {
                //            throw new SPException("Метка " + label + " при директиве " + current.operation + " находится вне зоны видимости или не описана");
                //        }
                //    }
                //    continue;
                //}

                #endregion

                if (runStack.Peek())
                {
                    if (!String.IsNullOrEmpty(current.label))
                    {
                        current.label = current.label + "_" + this.name + "_" + this.count;
                    }
                    for (int j = 0; j < current.operands.Count; j++)
                    {
                        if (this.local.Keys.Contains(current.operands[j]))
                        {
                            current.operands[j] = current.operands[j] + "_" + this.name + "_" + this.count;
                        }
                    }

                    sc.firstRunStep(current, this);
                }
            }
            this.count++;

            //foreach (SourceEntity se in sc.result)
            //{
            //se.label = null;
            //}
            return(sc.result);
        }