/// <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; }
public ParseTreeNode(string name, Symbol symbol, ParseTreeNode[] children) { Name = name; Symbol = symbol; Children = children; }