/**************************************************************************** ** ** 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.Reflection; namespace QtVsTools.SyntaxAnalysis { public abstract partial class RegExpr { public interface IRuleAction { int NumOperands { get; } string SourceTokenId { get; set; } bool Execute(ref T productionObj, string capturedValue, params object[] operandObjs); MethodInfo AssertInfo { get; } MethodInfo ActionInfo { get; } } public class RuleAction : IRuleAction { public Delegate Assert { get; set; } public Delegate Action { get; set; } public MethodInfo AssertInfo { get { return Assert != null ? Assert.Method : null; } } public MethodInfo ActionInfo { get { return Action != null ? Action.Method : null; } } public string SourceTokenId { get; set; } static readonly int _NumOperands = (typeof(T1) != typeof(Void) ? 1 : 0) + (typeof(T2) != typeof(Void) ? 1 : 0); public int NumOperands { get { return _NumOperands; } } bool TestAssert(T prod, string value, T1 x, T2 y) { if (Assert == null) return true; else if (Assert is CaptureCallback.Predicate) return ((CaptureCallback.Predicate)Assert)(value); else if (Assert is UnaryCallback.Predicate) return ((UnaryCallback.Predicate)Assert)(x); else if (Assert is UnaryCallback.Predicate) return ((UnaryCallback.Predicate)Assert)(prod, x); else if (Assert is BinaryCallback.Predicate) return ((BinaryCallback.Predicate)Assert)(x, y); else if (Assert is BinaryCallback.Predicate) return ((BinaryCallback.Predicate)Assert)(prod, x, y); else throw new InvalidOperationException("Incompatible assert callback."); } void RunAction(ref T prod, string value, T1 x, T2 y) { if (Action == null) throw new InvalidOperationException("Missing action callback."); else if (Action is CaptureCallback.Create) prod = ((CaptureCallback.Create)Action)(value); else if (Action is UnaryCallback.Create) prod = ((UnaryCallback.Create)Action)(x); else if (Action is BinaryCallback.Create) prod = ((BinaryCallback.Create)Action)(x, y); else if (Action is UnaryCallback.Transform) prod = ((UnaryCallback.Transform)Action)(prod, x); else if (Action is BinaryCallback.Transform) prod = ((BinaryCallback.Transform)Action)(prod, x, y); else if (Action is UnaryCallback.Update) ((UnaryCallback.Update)Action)(prod, x); else if (Action is BinaryCallback.Update) ((BinaryCallback.Update)Action)(prod, x, y); else if (Action is UnaryCallback.Error) throw new ErrorException(((UnaryCallback.Error)Action)(prod, x)); else if (Action is BinaryCallback.Error) throw new ErrorException(((BinaryCallback.Error)Action)(prod, x, y)); else throw new InvalidOperationException("Incompatible action callback."); } bool GetOperand(out TOperand x, object[] operands, ref int idx) { x = default(TOperand); if (typeof(TOperand) == typeof(Void)) return true; if (operands.Length <= idx) return false; object operandObj = operands[idx++]; if (!(operandObj is TOperand)) return false; x = (TOperand)operandObj; return true; } public bool Execute(ref T prod, string value, params object[] operands) { int idx = 0; T1 x; T2 y; if (!GetOperand(out x, operands, ref idx)) return false; if (!GetOperand(out y, operands, ref idx)) return false; if (!TestAssert(prod, value, x, y)) return false; RunAction(ref prod, value, x, y); return true; } } public class RuleAction : RuleAction { } public class RuleAction : RuleAction { } /////////////////////////////////////////////////////////////////////////////////////////// #region Capture public static RuleAction Capture( CaptureCallback.Predicate p, CaptureCallback.Create a) { return new RuleAction { Assert = p, Action = a }; } public static RuleAction Capture( CaptureCallback.Create a) { return new RuleAction { Assert = null, Action = a }; } #endregion Capture /////////////////////////////////////////////////////////////////////////////////////////// #region Create public static RuleAction Create( string sid, UnaryCallback.Predicate p, UnaryCallback.Create a) { return new RuleAction { SourceTokenId = sid, Assert = p, Action = a }; } public static RuleAction Create( Enum sid, UnaryCallback.Predicate p, UnaryCallback.Create a) { return Create(sid.ToString(), p, a); } public static RuleAction Create( string sid, UnaryCallback.Create a) { return Create(sid, null, a); } public static RuleAction Create( Enum sid, UnaryCallback.Create a) { return Create(sid, null, a); } public static RuleAction Create( UnaryCallback.Predicate p, UnaryCallback.Create a) { return Create(string.Empty, p, a); } public static RuleAction Create( UnaryCallback.Create a) { return Create(string.Empty, null, a); } public static RuleAction Create( BinaryCallback.Predicate p, BinaryCallback.Create a) { return new RuleAction { Assert = p, Action = a }; } public static RuleAction Create( BinaryCallback.Create a) { return Create(null, a); } #endregion Create /////////////////////////////////////////////////////////////////////////////////////////// #region Transform public static RuleAction Transform( string sid, UnaryCallback.Predicate p, UnaryCallback.Transform a) { return new RuleAction { SourceTokenId = sid, Assert = p, Action = a }; } public static RuleAction Transform( Enum sid, UnaryCallback.Predicate p, UnaryCallback.Transform a) { return Transform(sid.ToString(), p, a); } public static RuleAction Transform( string sid, UnaryCallback.Transform a) { return Transform(sid, null, a); } public static RuleAction Transform( Enum sid, UnaryCallback.Transform a) { return Transform(sid, null, a); } public static RuleAction Transform( UnaryCallback.Transform a) { return Transform(string.Empty, null, a); } public static RuleAction Transform( BinaryCallback.Predicate p, BinaryCallback.Transform a) { return new RuleAction { Assert = p, Action = a }; } public static RuleAction Transform( BinaryCallback.Transform a) { return Transform(null, a); } #endregion Transform /////////////////////////////////////////////////////////////////////////////////////////// #region Update public static RuleAction Update( string sid, UnaryCallback.Predicate p, UnaryCallback.Update a) { return new RuleAction { SourceTokenId = sid, Assert = p, Action = a }; } public static RuleAction Update( Enum sid, UnaryCallback.Predicate p, UnaryCallback.Update a) { return Update(sid.ToString(), p, a); } public static RuleAction Update( string sid, UnaryCallback.Update a) { return Update(sid, null, a); } public static RuleAction Update( Enum sid, UnaryCallback.Update a) { return Update(sid, null, a); } public static RuleAction Update( UnaryCallback.Update a) { return Update(string.Empty, null, a); } public static RuleAction Update( BinaryCallback.Predicate p, BinaryCallback.Update a) { return new RuleAction { Assert = p, Action = a }; } public static RuleAction Update( BinaryCallback.Update a) { return Update(null, a); } #endregion Update /////////////////////////////////////////////////////////////////////////////////////////// #region Error public static RuleAction Error( string sid, UnaryCallback.Predicate p, UnaryCallback.Error a) { return new RuleAction { SourceTokenId = sid, Assert = p, Action = a }; } public static RuleAction Error( Enum sid, UnaryCallback.Predicate p, UnaryCallback.Error a) { return Error(sid.ToString(), p, a); } public static RuleAction Error( string sid, UnaryCallback.Error a) { return Error(sid, null, a); } public static RuleAction Error( Enum sid, UnaryCallback.Error a) { return Error(sid, null, a); } public static RuleAction Error( UnaryCallback.Predicate p, UnaryCallback.Error a) { return Error(string.Empty, p, a); } public static RuleAction Error( UnaryCallback.Error a) { return Error(string.Empty, null, a); } public static RuleAction Error( BinaryCallback.Predicate p, BinaryCallback.Error a) { return new RuleAction { Assert = p, Action = a }; } public static RuleAction Error( BinaryCallback.Error a) { return Error(null, a); } public class ErrorException : RegExprException { public ErrorException(string message = null) : base(message) { } } #endregion Error /////////////////////////////////////////////////////////////////////////////////////////// #region Callbacks public static class CaptureCallback { public delegate bool Predicate(string capture); public delegate T Create(string capture); } public static class UnaryCallback { public delegate bool Predicate(T1 operand1); public delegate bool Predicate(T obj, T1 operand1); public delegate T Create(T1 operand1); public delegate T Transform(T obj, T1 operand1); public delegate void Update(T obj, T1 operand1); public delegate string Error(T obj, T1 operand1); } public static class BinaryCallback { public delegate bool Predicate(T1 operand1, T2 operand2); public delegate bool Predicate(T obj, T1 operand1, T2 operand2); public delegate T Create(T1 operand1, T2 operand2); public delegate T Transform(T obj, T1 operand1, T2 operand2); public delegate void Update(T obj, T1 operand1, T2 operand2); public delegate string Error(T obj, T1 operand1, T2 operand2); } #endregion Callbacks } }