示例#1
0
        public bool TryCompile(Queue <Word> splittedWords)
        {
            // Коллекций номеров правил
            List <int> rulesFound = new List <int>();
            // Коллекция элементов в магазине
            LinkedList <Word> stack = new LinkedList <Word>();

            stack.AddLast(new Word(_lastWord));

            OnCompileNextStep.Invoke(this, new CompileInfoEventArgs(splittedWords, stack, rulesFound));

            while (splittedWords.Count > 0)
            {
                CompileActions action = CompileActions.Start;

                // Серем слово, для просмотра
                Word word = splittedWords.Peek();

                // Проверяем, является ли последний символ символом конца цепочки
                if (word.Number == _lastWord.Number)
                {
                    if (stack.Count == 2)
                    {
                        // Если последний символ в стеке - символ цепочки S, а первый - символ клнца цепочки
                        // Тогда разбор окончен успешно
                        if ((stack.Last.Value.Number == _firstRule.RuleWordNumber) && (stack.First.Value.Number == _lastWord.Number))
                        {
                            CompiledText = stack.Last.Value.Temp;
                            OnCompileDone.Invoke(this, new CompileInfoEventArgs(splittedWords, stack, rulesFound));
                            return(true);
                        }
                    }
                }

                int row = stack.Last.Value.Number;
                int col = word.Number;

                // Правило, для переноса
                if ((RuleTable[row, col] == 1 && action != CompileActions.Error) || (RuleTable[row, col] == 2 && action != CompileActions.Error))
                {
                    // Вытаскиваем слово из входной цепочки и заносим в стек
                    Word tmpWord = splittedWords.Dequeue();
                    stack.AddLast(tmpWord);
                    action = CompileActions.Next;
                }

                // Правило, для свертки
                if ((RuleTable[row, col] == 3) && action != CompileActions.Next && action != CompileActions.Error)
                {
                    // Ищем количество слов, для свертки
                    // Изначально, текуший символ не может иметь правило, для сдвига => cnt = 1
                    int cntWordsInStack = 1;

                    // Начинаем поиск с конца цепочки
                    LinkedListNode <Word> node = stack.Last;

                    // Если правило не равняется сдвигу, то сдвигаем цепочку. Увеличиваем число найденных слов
                    while (RuleTable[node.Previous.Value.Number, node.Value.Number] != 1)
                    {
                        node = node.Previous;
                        cntWordsInStack++;
                    }

                    // Ищем подходящее правило
                    for (var ruleNumber = 0; ruleNumber < Rules.Length; ruleNumber++)
                    {
                        // Ищем подходящие по длене правило из списка правил
                        if (Rules[ruleNumber].CountOfWords == cntWordsInStack)
                        {
                            // Количество символов, которые последовательно совпадают в цепочке и правиле
                            int cntWordsInRule = 0;

                            // Присваиваем начальный символ цепочки, для свертки
                            LinkedListNode <Word> srchNode = node;
                            // Можно изменить способ сверки
                            for (var i = 0; i < cntWordsInStack; i++)
                            {
                                // Сверяет последовательность слов в выбранном правиле с цепочкой правил в стеке
                                if (Rules[ruleNumber].RuleList[i] == srchNode.Value.Number)
                                {
                                    cntWordsInRule++;
                                    srchNode = srchNode.Next;
                                }
                                else
                                {
                                    break;
                                }
                            }

                            // Если количество сошлось, то это то правило
                            if (cntWordsInRule == cntWordsInStack)
                            {
                                List <Word> toCompileList = new List <Word>();
                                // Загружаем последний элемент стека
                                srchNode = stack.Last;
                                toCompileList.Add(srchNode.Value);

                                // СмещаемЮ до первого элемента, в цепочке правил
                                for (int i = 1; i < cntWordsInRule; i++)
                                {
                                    srchNode = srchNode.Previous;
                                    toCompileList.Add(srchNode.Value);
                                }


                                // Присваиваем номер и символ правила, которое использовали
                                int collapsedRuleNumber = Rules[ruleNumber].RuleWordNumber;

                                // Производим покпиляцию по правилу
                                node.Value.Temp   = _compiler.Compil(ruleNumber, toCompileList.ToArray());
                                node.Value.Number = collapsedRuleNumber;
                                node.Value.Value  = Words[collapsedRuleNumber].Value;

                                // Добаляем использованное правило в коллекцию правил
                                rulesFound.Add(ruleNumber);

                                // Очищаем ненужные элементы до конца списка
                                while (node.Next != null)
                                {
                                    stack.Remove(node.Next);
                                }

                                action = CompileActions.Next;
                                break;
                            }
                        }
                    }
                }
                if (action != CompileActions.Next)
                {
                    OnCompileError.Invoke(this, new CompileErrorEventArgs(splittedWords, stack, rulesFound, RuleTable[row, col]));
                    return(false);
                }
                OnCompileNextStep.Invoke(this, new CompileInfoEventArgs(splittedWords, stack, rulesFound));
            }
            return(false);
        }
示例#2
0
        public void Algorithm(Queue <Word> splittedWords)
        {
            // Коллекций номеров правил
            List <int> rulesFound = new List <int>();
            //TODO: XML док
            LinkedList <Word> stack = new LinkedList <Word>();

            //TODO: Избавиться от зависимости последнего символа
            stack.AddLast(Words.Last());

            PrintInfo(stack, rulesFound, splittedWords);

            while (splittedWords.Count > 0)
            {
                CompileActions action = CompileActions.Start;

                // Серем слово, для просмотра
                Word word = splittedWords.Peek();

                // Проверяем, является ли последний символ символом конца цепочки
                if (word.Number == Words.Last().Number)
                {
                    if (stack.Count == 2)
                    {
                        // Если последний символ в стеке - символ цепочки S, а первый - символ клнца цепочки
                        // Тогда разбор окончен успешно
                        // TODO: Убрать первый сивол, заменить
                        if ((stack.Last.Value.Number == Words.First().Number) && (stack.First.Value.Number == Words.Last().Number))
                        {
                            PrintCompileResult.Invoke(stack.Last.Value.Temp);
                            return;
                        }
                    }
                }

                int row = stack.Last.Value.Number;
                int col = word.Number;

                // Правило, для переноса
                if ((RuleRuleTable[row, col] == 1 && action != CompileActions.Error) || (RuleRuleTable[row, col] == 2 && action != CompileActions.Error))
                {
                    // Вытаскиваем слово из входной цепочки и заносим в стек
                    Word tmpWord = splittedWords.Dequeue();
                    stack.AddLast(tmpWord);
                    action = CompileActions.Next;
                }

                // Правило, для свертки
                if ((RuleRuleTable[row, col] == 3) && action != CompileActions.Next && action != CompileActions.Error)
                {
                    // Ищем количество слов, для свертки
                    // Изначально, текуший символ не может иметь правило, для сдвига => cnt = 1
                    int cntWordsInStack = 1;

                    // Начинаем поиск с конца цепочки
                    LinkedListNode <Word> node = stack.Last;

                    // Если правило не равняется сдвигу, то сдвигаем цепочку. Увеличиваем число найденных слов
                    while (RuleRuleTable[node.Previous.Value.Number, node.Value.Number] != 1)
                    {
                        node = node.Previous;
                        cntWordsInStack++;
                    }

                    // Ищем подходящее правило
                    for (var ruleNumber = 0; ruleNumber < Rules.Length; ruleNumber++)
                    {
                        // Ищем подходящие по длене правило из списка правил
                        if (Rules[ruleNumber].CountOfWords == cntWordsInStack)
                        {
                            // Количество символов, которые последовательно совпадают в цепочке и правиле
                            int cntWordsInRule = 0;

                            // Присваиваем начальный символ цепочки, для свертки
                            LinkedListNode <Word> srchNode = node;
                            // Можно изменить способ сверки
                            for (var i = 0; i < cntWordsInStack; i++)
                            {
                                // Сверяет последовательность слов в выбранном правиле с цепочкой правил в стеке
                                if (Rules[ruleNumber].RuleList[i] == srchNode.Value.Number)
                                {
                                    cntWordsInRule++;
                                    srchNode = srchNode.Next;
                                }
                                else
                                {
                                    break;
                                }
                            }

                            // Если количество сошлось, то это то правило
                            if (cntWordsInRule == cntWordsInStack)
                            {
                                // Загружаем последний элемент стека
                                srchNode = stack.Last;

                                // СмещаемЮ до первого элемента, в цепочке правил
                                for (int i = 1; i < cntWordsInRule; i++)
                                {
                                    srchNode = srchNode.Previous;
                                }

                                // Производим покпиляцию по правилу
                                MyCompil(ruleNumber, srchNode);

                                // Присваиваем номер и символ правила, которое использовали
                                int collapsedRuleNumber = Rules[ruleNumber].RuleNumber;

                                node.Value.Number = collapsedRuleNumber;
                                node.Value.Value  = Words[collapsedRuleNumber].Value;

                                // Добаляем использованное правило в коллекцию правил
                                rulesFound.Add(ruleNumber);

                                // Очищаем ненужные элементы до конца списка
                                while (node.Next != null)
                                {
                                    stack.Remove(node.Next);
                                }

                                action = CompileActions.Next;
                                //PrintCompileResult.Invoke($"Value: {node.Value.Value} \nRule: {node.Value.Number} \nTemp: {node.Value.Temp}");
                                PrintCompileResult.Invoke(string.Format("Value: {0} \nRule: {1} \nTemp: {2}", node.Value.Value, node.Value.Number, node.Value.Temp));
                                break;
                            }
                        }
                    }
                }
                if (action != CompileActions.Next)
                {
                    PrintCompileInfo.Invoke(@"Ошибка при выполнении восходящего разбора!");
                    PrintCompileResult.Invoke("");
                    return;
                }
                PrintInfo(stack, rulesFound, splittedWords);
            }
        }