| /****************************************************************************  | 
| **  | 
| ** 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<T>  | 
|         {  | 
|             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<T, T1, T2> : IRuleAction<T>  | 
|         {  | 
|             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<T1>)  | 
|                     return ((UnaryCallback.Predicate<T1>)Assert)(x);  | 
|   | 
|                 else if (Assert is UnaryCallback.Predicate<T, T1>)  | 
|                     return ((UnaryCallback.Predicate<T, T1>)Assert)(prod, x);  | 
|   | 
|                 else if (Assert is BinaryCallback.Predicate<T1, T2>)  | 
|                     return ((BinaryCallback.Predicate<T1, T2>)Assert)(x, y);  | 
|   | 
|                 else if (Assert is BinaryCallback.Predicate<T, T1, T2>)  | 
|                     return ((BinaryCallback.Predicate<T, T1, T2>)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<T>)  | 
|                     prod = ((CaptureCallback.Create<T>)Action)(value);  | 
|   | 
|                 else if (Action is UnaryCallback.Create<T, T1>)  | 
|                     prod = ((UnaryCallback.Create<T, T1>)Action)(x);  | 
|   | 
|                 else if (Action is BinaryCallback.Create<T, T1, T2>)  | 
|                     prod = ((BinaryCallback.Create<T, T1, T2>)Action)(x, y);  | 
|   | 
|                 else if (Action is UnaryCallback.Transform<T, T1>)  | 
|                     prod = ((UnaryCallback.Transform<T, T1>)Action)(prod, x);  | 
|   | 
|                 else if (Action is BinaryCallback.Transform<T, T1, T2>)  | 
|                     prod = ((BinaryCallback.Transform<T, T1, T2>)Action)(prod, x, y);  | 
|   | 
|                 else if (Action is UnaryCallback.Update<T, T1>)  | 
|                     ((UnaryCallback.Update<T, T1>)Action)(prod, x);  | 
|   | 
|                 else if (Action is BinaryCallback.Update<T, T1, T2>)  | 
|                     ((BinaryCallback.Update<T, T1, T2>)Action)(prod, x, y);  | 
|   | 
|                 else if (Action is UnaryCallback.Error<T, T1>)  | 
|                     throw new ErrorException(((UnaryCallback.Error<T, T1>)Action)(prod, x));  | 
|   | 
|                 else if (Action is BinaryCallback.Error<T, T1, T2>)  | 
|                     throw new ErrorException(((BinaryCallback.Error<T, T1, T2>)Action)(prod, x, y));  | 
|   | 
|                 else  | 
|                     throw new InvalidOperationException("Incompatible action callback.");  | 
|             }  | 
|   | 
|             bool GetOperand<TOperand>(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<T, T1> : RuleAction<T, T1, Void> { }  | 
|   | 
|         public class RuleAction<T> : RuleAction<T, Void, Void> { }  | 
|   | 
|         ///////////////////////////////////////////////////////////////////////////////////////////  | 
|         #region Capture  | 
|   | 
|         public static RuleAction<T> Capture<T>(  | 
|             CaptureCallback.Predicate p, CaptureCallback.Create<T> a)  | 
|         { return new RuleAction<T> { Assert = p, Action = a }; }  | 
|   | 
|         public static RuleAction<T> Capture<T>(  | 
|             CaptureCallback.Create<T> a)  | 
|         { return new RuleAction<T> { Assert = null, Action = a }; }  | 
|   | 
|         #endregion Capture  | 
|   | 
|         ///////////////////////////////////////////////////////////////////////////////////////////  | 
|         #region Create  | 
|   | 
|         public static RuleAction<T, T1> Create<T, T1>(  | 
|             string sid, UnaryCallback.Predicate<T1> p, UnaryCallback.Create<T, T1> a)  | 
|         { return new RuleAction<T, T1> { SourceTokenId = sid, Assert = p, Action = a }; }  | 
|   | 
|         public static RuleAction<T, T1> Create<T, T1>(  | 
|             Enum sid, UnaryCallback.Predicate<T1> p, UnaryCallback.Create<T, T1> a)  | 
|         { return Create(sid.ToString(), p, a); }  | 
|   | 
|         public static RuleAction<T, T1> Create<T, T1>(  | 
|             string sid, UnaryCallback.Create<T, T1> a)  | 
|         { return Create(sid, null, a); }  | 
|   | 
|         public static RuleAction<T, T1> Create<T, T1>(  | 
|             Enum sid, UnaryCallback.Create<T, T1> a)  | 
|         { return Create(sid, null, a); }  | 
|   | 
|         public static RuleAction<T, T1> Create<T, T1>(  | 
|             UnaryCallback.Predicate<T1> p, UnaryCallback.Create<T, T1> a)  | 
|         { return Create(string.Empty, p, a); }  | 
|   | 
|         public static RuleAction<T, T1> Create<T, T1>(  | 
|             UnaryCallback.Create<T, T1> a)  | 
|         { return Create(string.Empty, null, a); }  | 
|   | 
|         public static RuleAction<T, T1, T2> Create<T, T1, T2>(  | 
|             BinaryCallback.Predicate<T1, T2> p, BinaryCallback.Create<T, T1, T2> a)  | 
|         { return new RuleAction<T, T1, T2> { Assert = p, Action = a }; }  | 
|   | 
|         public static RuleAction<T, T1, T2> Create<T, T1, T2>(  | 
|             BinaryCallback.Create<T, T1, T2> a)  | 
|         { return Create(null, a); }  | 
|   | 
|         #endregion Create  | 
|   | 
|         ///////////////////////////////////////////////////////////////////////////////////////////  | 
|         #region Transform  | 
|   | 
|         public static RuleAction<T, T1> Transform<T, T1>(  | 
|             string sid, UnaryCallback.Predicate<T, T1> p, UnaryCallback.Transform<T, T1> a)  | 
|         { return new RuleAction<T, T1> { SourceTokenId = sid, Assert = p, Action = a }; }  | 
|   | 
|         public static RuleAction<T, T1> Transform<T, T1>(  | 
|             Enum sid, UnaryCallback.Predicate<T, T1> p, UnaryCallback.Transform<T, T1> a)  | 
|         { return Transform(sid.ToString(), p, a); }  | 
|   | 
|         public static RuleAction<T, T1> Transform<T, T1>(  | 
|             string sid, UnaryCallback.Transform<T, T1> a)  | 
|         { return Transform(sid, null, a); }  | 
|   | 
|         public static RuleAction<T, T1> Transform<T, T1>(  | 
|             Enum sid, UnaryCallback.Transform<T, T1> a)  | 
|         { return Transform(sid, null, a); }  | 
|   | 
|         public static RuleAction<T, T1> Transform<T, T1>(  | 
|             UnaryCallback.Transform<T, T1> a)  | 
|         { return Transform(string.Empty, null, a); }  | 
|   | 
|         public static RuleAction<T, T1, T2> Transform<T, T1, T2>(  | 
|             BinaryCallback.Predicate<T, T1, T2> p, BinaryCallback.Transform<T, T1, T2> a)  | 
|         { return new RuleAction<T, T1, T2> { Assert = p, Action = a }; }  | 
|   | 
|         public static RuleAction<T, T1, T2> Transform<T, T1, T2>(  | 
|             BinaryCallback.Transform<T, T1, T2> a)  | 
|         { return Transform(null, a); }  | 
|   | 
|         #endregion Transform  | 
|   | 
|         ///////////////////////////////////////////////////////////////////////////////////////////  | 
|         #region Update  | 
|   | 
|         public static RuleAction<T, T1> Update<T, T1>(  | 
|             string sid, UnaryCallback.Predicate<T, T1> p, UnaryCallback.Update<T, T1> a)  | 
|         { return new RuleAction<T, T1> { SourceTokenId = sid, Assert = p, Action = a }; }  | 
|   | 
|         public static RuleAction<T, T1> Update<T, T1>(  | 
|             Enum sid, UnaryCallback.Predicate<T, T1> p, UnaryCallback.Update<T, T1> a)  | 
|         { return Update(sid.ToString(), p, a); }  | 
|   | 
|         public static RuleAction<T, T1> Update<T, T1>(  | 
|             string sid, UnaryCallback.Update<T, T1> a)  | 
|         { return Update(sid, null, a); }  | 
|   | 
|         public static RuleAction<T, T1> Update<T, T1>(  | 
|             Enum sid, UnaryCallback.Update<T, T1> a)  | 
|         { return Update(sid, null, a); }  | 
|   | 
|         public static RuleAction<T, T1> Update<T, T1>(  | 
|             UnaryCallback.Update<T, T1> a)  | 
|         { return Update(string.Empty, null, a); }  | 
|   | 
|         public static RuleAction<T, T1, T2> Update<T, T1, T2>(  | 
|             BinaryCallback.Predicate<T, T1, T2> p, BinaryCallback.Update<T, T1, T2> a)  | 
|         { return new RuleAction<T, T1, T2> { Assert = p, Action = a }; }  | 
|   | 
|         public static RuleAction<T, T1, T2> Update<T, T1, T2>(  | 
|             BinaryCallback.Update<T, T1, T2> a)  | 
|         { return Update(null, a); }  | 
|   | 
|         #endregion Update  | 
|   | 
|         ///////////////////////////////////////////////////////////////////////////////////////////  | 
|         #region Error  | 
|   | 
|         public static RuleAction<T, T1> Error<T, T1>(  | 
|             string sid, UnaryCallback.Predicate<T, T1> p, UnaryCallback.Error<T, T1> a)  | 
|         { return new RuleAction<T, T1> { SourceTokenId = sid, Assert = p, Action = a }; }  | 
|   | 
|         public static RuleAction<T, T1> Error<T, T1>(  | 
|             Enum sid, UnaryCallback.Predicate<T, T1> p, UnaryCallback.Error<T, T1> a)  | 
|         { return Error(sid.ToString(), p, a); }  | 
|   | 
|         public static RuleAction<T, T1> Error<T, T1>(  | 
|             string sid, UnaryCallback.Error<T, T1> a)  | 
|         { return Error(sid, null, a); }  | 
|   | 
|         public static RuleAction<T, T1> Error<T, T1>(  | 
|             Enum sid,  | 
|             UnaryCallback.Error<T, T1> a)  | 
|         { return Error(sid, null, a); }  | 
|   | 
|         public static RuleAction<T, T1> Error<T, T1>(  | 
|             UnaryCallback.Predicate<T, T1> p, UnaryCallback.Error<T, T1> a)  | 
|         { return Error(string.Empty, p, a); }  | 
|   | 
|         public static RuleAction<T, T1> Error<T, T1>(  | 
|             UnaryCallback.Error<T, T1> a)  | 
|         { return Error(string.Empty, null, a); }  | 
|   | 
|         public static RuleAction<T, T1, T2> Error<T, T1, T2>(  | 
|             BinaryCallback.Predicate<T, T1, T2> p, BinaryCallback.Error<T, T1, T2> a)  | 
|         { return new RuleAction<T, T1, T2> { Assert = p, Action = a }; }  | 
|   | 
|         public static RuleAction<T, T1, T2> Error<T, T1, T2>(  | 
|             BinaryCallback.Error<T, T1, T2> 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<T>(string capture);  | 
|         }  | 
|   | 
|         public static class UnaryCallback  | 
|         {  | 
|             public delegate bool Predicate<T1>(T1 operand1);  | 
|             public delegate bool Predicate<T, T1>(T obj, T1 operand1);  | 
|             public delegate T Create<T, T1>(T1 operand1);  | 
|             public delegate T Transform<T, T1>(T obj, T1 operand1);  | 
|             public delegate void Update<T, T1>(T obj, T1 operand1);  | 
|             public delegate string Error<T, T1>(T obj, T1 operand1);  | 
|         }  | 
|   | 
|         public static class BinaryCallback  | 
|         {  | 
|             public delegate bool Predicate<T1, T2>(T1 operand1, T2 operand2);  | 
|             public delegate bool Predicate<T, T1, T2>(T obj, T1 operand1, T2 operand2);  | 
|             public delegate T Create<T, T1, T2>(T1 operand1, T2 operand2);  | 
|             public delegate T Transform<T, T1, T2>(T obj, T1 operand1, T2 operand2);  | 
|             public delegate void Update<T, T1, T2>(T obj, T1 operand1, T2 operand2);  | 
|             public delegate string Error<T, T1, T2>(T obj, T1 operand1, T2 operand2);  | 
|         }  | 
|   | 
|         #endregion Callbacks  | 
|     }  | 
| }  |