/****************************************************************************
**
** 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; }
}
}
}
}
}