/**************************************************************************** ** ** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt VS Tools. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text.RegularExpressions; namespace QtVsTools.SyntaxAnalysis { public abstract partial class RegExpr { //////////////////////////////////////////////////////////////////////////////////////////// /// /// RegExpr.ParseTree /// //////////////////////////////////////////////////////////////////////////////////////////// /// /// Result of processing input text with a pattern rendered from a RegExpr. /// /// /// Nodes in a ParseTree correspond to captured tokens. The parent-child relationship /// between nodes reflects token embedding. /// public class ParseTree { public Node Root { get; set; } public const string KeyRoot = "0"; public class Node : IOperatorCapture, IOperandCapture { public string CaptureId { get; set; } public string Value { get; set; } public int Begin { get; set; } public int End { get; set; } public int GroupIdx { get; set; } public int CaptureIdx { get; set; } class NodeComparer : IComparer { public int Compare(Node x, Node y) { return Comparer.Default.Compare(x.Begin, y.Begin); } } static NodeComparer _Comparer = new NodeComparer(); public static IComparer Comparer { get { return _Comparer; } } public Token Token { get; set; } public string TokenId { get { return Token.Id; } } public object Production { get; set; } public Node Parent { get; set; } SortedList _ChildNodes = new SortedList(); public SortedList ChildNodes { get { return _ChildNodes; } } ProductionObjects _ChildProductions = new ProductionObjects(); public ProductionObjects ChildProductions { get { return _ChildProductions; } } public Queue TokenStream { get; set; } public Stack OperatorStack { get; set; } public Stack OperandStack { get; set; } IProductionRule _Rule = null; public IProductionRule Rule { get { if (_Rule == null) _Rule = Token.SelectRule(this); return _Rule; } } public string Key { get { if (CaptureId == KeyRoot) return KeyRoot; return string.Format("{0}:{1}:{2}", CaptureId, Begin, End); } } public override string ToString() { return string.Format("{0}[{1}]", TokenId, Value); } public static implicit operator ParseTree(Node node) { return new ParseTree { Root = node }; } int SiblingIdx { get { if (Parent == null) return 0; return Parent.ChildNodes.IndexOfKey(Begin); } } int SiblingCount { get { if (Parent == null) return 1; return Parent.ChildNodes.Count; } } public bool IsFirst { get { return SiblingIdx == 0; } } public bool IsLast { get { return SiblingIdx == SiblingCount - 1; } } public IEnumerable LookAhead(params TokenGroup[] ids) { if (Parent == null) return Empty(); var lookAhead = Parent.ChildNodes.Values .Skip(SiblingIdx + 1); if (ids.Any()) lookAhead = lookAhead.Where(x => ids.Any(g => g.Contains(x.TokenId))); return lookAhead.Cast().Concat(Items(EndOfList)); } public IEnumerable LookBehind(params TokenGroup[] ids) { if (Parent == null) return Empty(); var lookBehind = Parent.ChildNodes.Values .Take(SiblingIdx) .Reverse(); if (ids.Any()) lookBehind = lookBehind.Where(x => ids.Any(g => g.Contains(x.TokenId))); return lookBehind.Cast().Concat(Items(EndOfList)); } public bool Is(params TokenGroup[] tokenIds) { return tokenIds.Any(g => g.Contains(TokenId)); } public bool IsNot(params TokenGroup[] tokenIds) { return !tokenIds.Any(g => g.Contains(TokenId)); } public IOperandCapture Operand { get { if (Parent == null) return EndOfList; if (Parent.OperandStack == null) return EndOfList; if (!Parent.OperandStack.Any()) return EndOfList; return Parent.OperandStack.Peek(); } } public IOperandCapture LeftOperand { get { if (Parent == null) return EndOfList; if (Parent.OperandStack == null) return EndOfList; if (Parent.OperandStack.Count() < 2) return EndOfList; return Parent.OperandStack.Skip(1).First(); } } public IOperandCapture RightOperand { get { if (Parent == null) return EndOfList; if (Parent.OperandStack == null) return EndOfList; if (Parent.OperandStack.Count() < 2) return EndOfList; return Parent.OperandStack.Peek(); } } public bool HasOperand { get { return Operand != EndOfList; } } public bool HasLeftOperand { get { return LeftOperand != EndOfList; } } public bool HasRightOperand { get { return RightOperand != EndOfList; } } } } } }