예제 #1
0
파일: Parser.cs 프로젝트: Throttle/compiler
        /// <summary>
        /// Создать дерево вывода
        /// </summary>
        /// <returns>Дерево</returns>
        public ParseTreeNode CreateParseTree()
        {
            // флаг отслеживающий вхождение в блок коментариев
            bool inCommentBlock = false;

            // стек парсера
            Stack stack = new Stack();

            // стек дерева
            Stack treeStack = new Stack();

            // установка начальных значений
            m_Scanner.Reset();
            ParserState currentState = m_Language.ParserStartState;

            // запихиваем в стек начальное состояние
            stack.Push(currentState);

            while (true)
            {
                // получить следующий токен
                Symbol nextSymbol = m_Scanner.PeekNextToken().Symbol;

                // не учитываем символы разделители
                if (nextSymbol.Type == SymbolType.Whitespace)
                {
                    m_Scanner.GetNextToken();
                    continue;
                }

                // игнорируем блоки комментариев
                // вошли в блок
                if (nextSymbol.Type == SymbolType.CommentStart)
                {
                    m_Scanner.GetNextToken();
                    inCommentBlock = true;
                    continue;
                }

                // игнорируем блоки комментариев
                // вышли из блока
                if (nextSymbol.Type == SymbolType.CommentEnd)
                {
                    m_Scanner.GetNextToken();
                    inCommentBlock = false;
                    continue;
                }

                // игнорируем контент комментариев
                if (inCommentBlock)
                {
                    m_Scanner.GetNextToken();
                    continue;
                }

                // вывести содержимое стека на экран
                Print(stack);

                // получить действие в зависимости от символа
                Action action = currentState.Find(nextSymbol);

                // Если находимся в ошибочном состоянии - действеи null
                if (action == null)
                {
                    Debug.WriteLine("Error");
                    break;
                }

                // СДВИГ
                else if (action.Type == ActionType.Shift)
                {
                    stack.Push(m_Scanner.GetNextToken().Symbol);
                    stack.Push(action.ParserState);

                    // запихиваем терминал в стек дерева
                    treeStack.Push(new ParseTreeNode(nextSymbol.Name, nextSymbol, null));
                }
                // ПЕРЕХОД
                else if (action.Type == ActionType.Goto)
                {
                    Debug.WriteLine("Goto");
                }
                // СВЕРТКА
                else if (action.Type == ActionType.Reduce)
                {
                    // Pop off the stack however many state-symbol pairs as the Production
                    // has Right Terminals,Nonterminals.

                    int rightItems = action.Production.Right.Length;
                    for (int i = 0; i < rightItems; i++)
                    {
                        stack.Pop();
                        stack.Pop();
                    }

                    // получаем вершину стека
                    ParserState topState = (ParserState)stack.Peek();
                    // запихиваем левую часть правила вывода.
                    stack.Push(action.Production.Left);
                    // запихиваем состояние в которое переходим из
                    // состояния top по символу из левой части правила вывода
                    stack.Push(topState.Find(action.Production.Left).ParserState);

                    // создаем потомков
                    ParseTreeNode[] children = new ParseTreeNode[rightItems];
                    ParseTreeNode node = new ParseTreeNode(action.Production.Left.Name, action.Production.Left, children);
                    for (int i = rightItems - 1; i >= 0; i--)
                    {
                        children[i] = (ParseTreeNode)treeStack.Pop();
                        children[i].Parent = node;
                    }
                    treeStack.Push(node);
                }
                // выдать результирующее дерево
                else if (action.Type == ActionType.Accept)
                {
                    Debug.WriteLine("Accept");
                    return (ParseTreeNode)treeStack.Pop();
                }
                currentState = (ParserState)stack.Peek();
            }

            return null;
        }
예제 #2
0
파일: Parser.cs 프로젝트: Throttle/compiler
 public ParseTreeNode(string name, Symbol symbol, ParseTreeNode[] children)
 {
     Name = name;
     Symbol = symbol;
     Children = children;
 }