/****************************************************************************
**
** 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.Collections.Generic;
using System.Text;
namespace QtVsTools.SyntaxAnalysis
{
using static RegExprAssert;
////////////////////////////////////////////////////////////////////////////////////////////////
///
/// RegExprAssert ( -> RegExpr)
///
////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Asserts a pattern on the input string without consuming chars.
///
///
public partial class RegExprAssert : RegExpr
{
public enum AssertLook { Ahead, Behind }
public AssertLook Context { get; set; }
public bool Negative { get; set; }
public RegExpr Expr { get; set; }
protected override IEnumerable OnRender(RegExpr defaultTokenWs, RegExpr parent,
StringBuilder pattern, ref RenderMode mode, Stack tokenStack)
{
base.OnRender(defaultTokenWs, parent, pattern, ref mode, tokenStack);
if (mode.HasFlag(RenderMode.Assert))
throw new NestedAssertException();
switch (Context) {
case AssertLook.Ahead:
if (Negative)
pattern.Append("(?!");
else
pattern.Append("(?=");
break;
case AssertLook.Behind:
if (Negative)
pattern.Append("(? tokenStack)
{
base.OnRenderEnd(defaultTokenWs, parent, pattern, ref mode, tokenStack);
pattern.Append(")");
mode &= ~RenderMode.Assert;
}
}
public abstract partial class RegExpr
{
RegExprAssert AsAssert()
{
if (this is RegExprAssert)
return this as RegExprAssert;
return new RegExprAssert
{
Context = AssertLook.Ahead,
Negative = false,
Expr = this
};
}
public static RegExprAssert AssertLookAhead(RegExpr expr)
{
var assert = expr.AsAssert();
return new RegExprAssert
{
Context = AssertLook.Ahead,
Negative = assert.Negative,
Expr = assert.Expr
};
}
public static RegExprAssert AssertLookBehind(RegExpr expr)
{
var assert = expr.AsAssert();
return new RegExprAssert
{
Context = AssertLook.Behind,
Negative = assert.Negative,
Expr = assert.Expr
};
}
public static RegExprAssert AssertNegated(RegExpr expr)
{
var assert = expr.AsAssert();
return new RegExprAssert
{
Context = assert.Context,
Negative = !assert.Negative,
Expr = assert.Expr
};
}
public delegate RegExprAssert AssertTemplate(RegExpr expr);
public class AssertExprBuilder
{
AssertTemplate Template { get; }
public AssertExprBuilder(AssertTemplate template)
{
Template = template;
}
public class Expr
{
public RegExprAssert Assert { get; set; }
public Expr(RegExprAssert assert) { Assert = assert; }
public static implicit operator RegExpr(Expr e)
{
return e.Assert;
}
public static RegExpr operator &(RegExpr rx1, Expr rx2)
{
return Concat(rx1, rx2);
}
public static RegExpr operator |(RegExpr rx1, Expr rx2)
{
return Choice(rx1, rx2);
}
}
public class NegateableExpr : Expr
{
public NegateableExpr(RegExprAssert assert) : base(assert) { }
public static Expr operator !(NegateableExpr x)
{
return new Expr(AssertNegated(x.Assert));
}
}
public NegateableExpr this[RegExpr expr]
{
get { return new NegateableExpr(Template(expr)); }
}
}
public class NestedAssertException : RegExprException
{
public NestedAssertException(string message = null) : base(message) { }
}
}
}