コード例 #1
0
        private void AddOperatorToStack(string @operator)
        {
            // Відкриваюча дужка "(" повинна мати найнижчий пріоритет, але записуватися в стек, нічого не виштовхуючи
            if (@operator == "(")
            {
                Stack.Push(new PolishNotation {
                    Token = @operator, Type = PolishNotationTokenType.Operator
                });
                return;
            }

            // 3.	Якщо стек порожній, то поточна операція заноситься в стек
            if (Stack.Count == 0)
            {
                Stack.Push(new PolishNotation {
                    Token = @operator, Type = PolishNotationTokenType.Operator
                });
                return;
            }

            PolishNotation head      = Stack.Peek();
            string         headToken = head.Token.StartsWith("if")
                                ? "if"
                                : head.Token.StartsWith("while")
                                        ? "while"
                                        : head.Token;

            // 2.	Якщо пріоритет операції, що знаходиться в стеку,
            //      не менший за пріоритет поточної вхідної операції,
            //      то операція зі стека подається на вихід і п.2 повторюється,
            if (_operatorsPriorities[headToken] >= _operatorsPriorities[@operator])
            {
                PolishNotation notation = Stack.Pop();
                if (notation.Token != "(")                 // Причому "(" ніколи не передається на вихід
                {
                    ReversePolishNotation.Add(notation);   // операція зі стека подається на вихід
                }

                AddOperatorToStack(@operator);                 // п.2 повторюється
                return;
            }

            // інакше поточна операція заноситься в стек.
            if (@operator != ")")             // Причому ")" ніколи не заноситься в стек
            {
                Stack.Push(new PolishNotation {
                    Token = @operator, Type = PolishNotationTokenType.Operator
                });
            }
        }
コード例 #2
0
        private void DijkstraStep(string input, PolishNotationTokenType type, bool isAssignmentToThisIdentifier = false)
        {
            switch (type)
            {
            // 1.	Ідентифікатори та константи проходять від входу прямо до виходу
            case PolishNotationTokenType.Identifier:
            case PolishNotationTokenType.Literal:
                ReversePolishNotation.Add(new PolishNotation
                {
                    Token = input, Type = type, IsAssignmentToThisIdentifier = isAssignmentToThisIdentifier
                });
                break;

            // Операції звичайно потрапляють на вихід через магазин
            case PolishNotationTokenType.Operator:
                AddOperatorToStack(input);
                break;

            // 4.	Якщо вхідний ланцюжок порожній, всі операції зі стека по черзі передаються на вихід
            //      за ознакою кінця виразу (наприклад, ";").
            case PolishNotationTokenType.Delimiter:
            {
                while (Stack.Count != 0 &&
                       !Stack.Peek().Token.StartsWith("if") &&
                       !Stack.Peek().Token.StartsWith("while"))
                {
                    ReversePolishNotation.Add(Stack.Pop());
                }

//					ReversePolishNotation.Add(new PolishNotation {Token = input, Type = type});
            }
            break;

            case PolishNotationTokenType.If:
                Stack.Push(new PolishNotation {
                    Token = input, Type = type
                });
                break;

            // Символ then з пріоритетом 1 виштовхує зі стека всі знаки до першого
            // if виключно. При цьому генерується нова мітка mi й у вихідний рядок
            // заноситься mi УПХ. Потім мітка mi заноситься в таблицю міток і дописується у вершину стека,
            // таким чином, запис if у вершині стека перетворюється на запис if mi
            case PolishNotationTokenType.Then:
            {
                PolishNotation head = Stack.Peek();
                while (!head.Token.StartsWith("if"))
                {
                    ReversePolishNotation.Add(Stack.Pop());
                    head = Stack.Peek();
                }

                string label = GenerateLabel();
                head.Token = $"{head.Token} {label}";
                ReversePolishNotation.Add(new PolishNotation
                    {
                        Token = $"{label}", Type = PolishNotationTokenType.Label
                    });
                ReversePolishNotation.Add(new PolishNotation {
                        Token = "УПХ", Type = type
                    });
            }
            break;

            // Символ кінця умовного оператора (наприклад, ; або end) виштовхує зі
            // стека все до найближчого if. Це може бути if mi mi+1 (або if mi у разі
            // конструкції if <вираз> then <оператор>;). Запис видаляється зі стека,
            // а у вихідний рядок додається mi+1: (або mi: у випадку неповного оператора умовного переходу).
            case PolishNotationTokenType.Fi:
            {
                PolishNotation head = Stack.Peek();
                while (!head.Token.StartsWith("if"))
                {
                    ReversePolishNotation.Add(Stack.Pop());
                    head = Stack.Peek();
                }

                head = Stack.Pop();
                string label = head.Token.Split(" ").Last();
                ReversePolishNotation.Add(new PolishNotation
                    {
                        Token = $"{label}", Type = PolishNotationTokenType.Label
                    });
                ReversePolishNotation.Add(new PolishNotation {
                        Token = ":", Type = type
                    });
                _labelAddresses[label] = ReversePolishNotation.Count;
            }
            break;

            case PolishNotationTokenType.While:
            {
                string label = GenerateLabel();
                Stack.Push(new PolishNotation {
                        Token = $"{input} {label}", Type = type
                    });
                ReversePolishNotation.Add(new PolishNotation
                    {
                        Token = $"{label}", Type = PolishNotationTokenType.Label
                    });
                ReversePolishNotation.Add(new PolishNotation {
                        Token = $":", Type = type
                    });
                _labelAddresses[label] = ReversePolishNotation.Count;
            }
            break;

            case PolishNotationTokenType.TechnicalDo:
            {
                PolishNotation head = Stack.Peek();
                while (!head.Token.StartsWith("while"))
                {
                    ReversePolishNotation.Add(Stack.Pop());
                    head = Stack.Peek();
                }

                string label = GenerateLabel();
                head.Token = $"{head.Token} {label}";
                ReversePolishNotation.Add(new PolishNotation
                    {
                        Token = $"{label}", Type = PolishNotationTokenType.Label
                    });
                ReversePolishNotation.Add(new PolishNotation {
                        Token = "УПХ", Type = type
                    });
            }
            break;

            case PolishNotationTokenType.Enddo:
            {
                PolishNotation head = Stack.Peek();
                while (!head.Token.StartsWith("while"))
                {
                    ReversePolishNotation.Add(Stack.Pop());
                    head = Stack.Peek();
                }

                head = Stack.Pop();
                string[] labels = head.Token.Split(" ");
                ReversePolishNotation.Add(new PolishNotation
                    {
                        Token = $"{labels[1]}", Type = PolishNotationTokenType.Label
                    });
                ReversePolishNotation.Add(new PolishNotation {
                        Token = "БП", Type = type
                    });
                ReversePolishNotation.Add(new PolishNotation
                    {
                        Token = $"{labels.Last()}", Type = PolishNotationTokenType.Label
                    });
                ReversePolishNotation.Add(new PolishNotation {
                        Token = $":", Type = type
                    });
                _labelAddresses[labels.Last()] = ReversePolishNotation.Count;
            }
            break;

            default:
                throw new ArgumentOutOfRangeException(nameof(type), type, null);
            }

            Trace.Add(new PolishTrace
            {
                Input = input,
//				Stack = new Stack<PolishNotation>(Stack),
                Stack = Stack.Clone(),
                ReversePolishNotation = new List <PolishNotation>(ReversePolishNotation)
            });
            MoveNext();
        }