test
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fac4026eb26ea42c29c85fec8007face
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,46 @@
|
||||
namespace Unity.VisualScripting.Dependencies.NCalc
|
||||
{
|
||||
public class BinaryExpression : LogicalExpression
|
||||
{
|
||||
public BinaryExpression(BinaryExpressionType type, LogicalExpression leftExpression, LogicalExpression rightExpression)
|
||||
{
|
||||
Type = type;
|
||||
LeftExpression = leftExpression;
|
||||
RightExpression = rightExpression;
|
||||
}
|
||||
|
||||
public LogicalExpression LeftExpression { get; set; }
|
||||
|
||||
public LogicalExpression RightExpression { get; set; }
|
||||
|
||||
public BinaryExpressionType Type { get; set; }
|
||||
|
||||
public override void Accept(LogicalExpressionVisitor visitor)
|
||||
{
|
||||
visitor.Visit(this);
|
||||
}
|
||||
}
|
||||
|
||||
public enum BinaryExpressionType
|
||||
{
|
||||
And,
|
||||
Or,
|
||||
NotEqual,
|
||||
LesserOrEqual,
|
||||
GreaterOrEqual,
|
||||
Lesser,
|
||||
Greater,
|
||||
Equal,
|
||||
Minus,
|
||||
Plus,
|
||||
Modulo,
|
||||
Div,
|
||||
Times,
|
||||
BitwiseOr,
|
||||
BitwiseAnd,
|
||||
BitwiseXOr,
|
||||
LeftShift,
|
||||
RightShift,
|
||||
Unknown
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ace4e9bf94df345f183dcb34a039e1d8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,4 @@
|
||||
namespace Unity.VisualScripting.Dependencies.NCalc
|
||||
{
|
||||
public delegate void EvaluateFunctionHandler(Flow flow, string name, FunctionArgs args);
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f8b54261ed2a8497ebdd20f7ddbe1e6f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,4 @@
|
||||
namespace Unity.VisualScripting.Dependencies.NCalc
|
||||
{
|
||||
public delegate void EvaluateParameterHandler(Flow flow, string name, ParameterArgs args);
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6180c9bbe40b44d45980f2b1a0325e58
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
|
||||
namespace Unity.VisualScripting.Dependencies.NCalc
|
||||
{
|
||||
public sealed class EvaluationException : ApplicationException
|
||||
{
|
||||
public EvaluationException(string message) : base(message) { }
|
||||
|
||||
public EvaluationException(string message, Exception innerException) : base(message, innerException) { }
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6499d38cb236f4d369ab2ce0e0585ecc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
|
||||
namespace Unity.VisualScripting.Dependencies.NCalc
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides enumerated values to use to set evaluation options.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum EvaluateOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies that no options are set.
|
||||
/// </summary>
|
||||
None = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies case-insensitive matching.
|
||||
/// </summary>
|
||||
IgnoreCase = 2,
|
||||
|
||||
/// <summary>
|
||||
/// No-cache mode. Ingores any pre-compiled expression in the cache.
|
||||
/// </summary>
|
||||
NoCache = 4,
|
||||
|
||||
/// <summary>
|
||||
/// Treats parameters as arrays and result a set of results.
|
||||
/// </summary>
|
||||
IterateParameters = 8,
|
||||
|
||||
/// <summary>
|
||||
/// When using Round(), if a number is halfway between two others, it is rounded toward the nearest number that is away
|
||||
/// from zero.
|
||||
/// </summary>
|
||||
RoundAwayFromZero = 16
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b546fea2e0eea4ab98c47948cb30b03c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,450 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.VisualScripting.Dependencies.NCalc
|
||||
{
|
||||
public class EvaluationVisitor : LogicalExpressionVisitor
|
||||
{
|
||||
public EvaluationVisitor(Flow flow, EvaluateOptions options)
|
||||
{
|
||||
this.flow = flow;
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
public event EvaluateFunctionHandler EvaluateFunction;
|
||||
|
||||
public event EvaluateParameterHandler EvaluateParameter;
|
||||
|
||||
private readonly Flow flow;
|
||||
|
||||
private readonly EvaluateOptions options;
|
||||
|
||||
private bool IgnoreCase => options.HasFlag(EvaluateOptions.IgnoreCase);
|
||||
|
||||
public object Result { get; private set; }
|
||||
|
||||
public Dictionary<string, object> Parameters { get; set; }
|
||||
|
||||
private object Evaluate(LogicalExpression expression)
|
||||
{
|
||||
expression.Accept(this);
|
||||
return Result;
|
||||
}
|
||||
|
||||
public override void Visit(TernaryExpression ternary)
|
||||
{
|
||||
// Evaluates the left expression and saves the value
|
||||
ternary.LeftExpression.Accept(this);
|
||||
|
||||
var left = ConversionUtility.Convert<bool>(Result);
|
||||
|
||||
if (left)
|
||||
{
|
||||
ternary.MiddleExpression.Accept(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
ternary.RightExpression.Accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Visit(BinaryExpression binary)
|
||||
{
|
||||
// Simulate Lazy<Func<>> behavior for late evaluation
|
||||
object leftValue = null;
|
||||
Func<object> left = () =>
|
||||
{
|
||||
if (leftValue == null)
|
||||
{
|
||||
binary.LeftExpression.Accept(this);
|
||||
leftValue = Result;
|
||||
}
|
||||
return leftValue;
|
||||
};
|
||||
|
||||
// Simulate Lazy<Func<>> behavior for late evaluation
|
||||
object rightValue = null;
|
||||
Func<object> right = () =>
|
||||
{
|
||||
if (rightValue == null)
|
||||
{
|
||||
binary.RightExpression.Accept(this);
|
||||
rightValue = Result;
|
||||
}
|
||||
return rightValue;
|
||||
};
|
||||
|
||||
switch (binary.Type)
|
||||
{
|
||||
case BinaryExpressionType.And:
|
||||
Result = ConversionUtility.Convert<bool>(left()) && ConversionUtility.Convert<bool>(right());
|
||||
break;
|
||||
|
||||
case BinaryExpressionType.Or:
|
||||
Result = ConversionUtility.Convert<bool>(left()) || ConversionUtility.Convert<bool>(right());
|
||||
break;
|
||||
|
||||
case BinaryExpressionType.Div:
|
||||
Result = OperatorUtility.Divide(left(), right());
|
||||
break;
|
||||
|
||||
case BinaryExpressionType.Equal:
|
||||
Result = OperatorUtility.Equal(left(), right());
|
||||
break;
|
||||
|
||||
case BinaryExpressionType.Greater:
|
||||
Result = OperatorUtility.GreaterThan(left(), right());
|
||||
break;
|
||||
|
||||
case BinaryExpressionType.GreaterOrEqual:
|
||||
Result = OperatorUtility.GreaterThanOrEqual(left(), right());
|
||||
break;
|
||||
|
||||
case BinaryExpressionType.Lesser:
|
||||
Result = OperatorUtility.LessThan(left(), right());
|
||||
break;
|
||||
|
||||
case BinaryExpressionType.LesserOrEqual:
|
||||
Result = OperatorUtility.LessThanOrEqual(left(), right());
|
||||
break;
|
||||
|
||||
case BinaryExpressionType.Minus:
|
||||
Result = OperatorUtility.Subtract(left(), right());
|
||||
break;
|
||||
|
||||
case BinaryExpressionType.Modulo:
|
||||
Result = OperatorUtility.Modulo(left(), right());
|
||||
break;
|
||||
|
||||
case BinaryExpressionType.NotEqual:
|
||||
Result = OperatorUtility.NotEqual(left(), right());
|
||||
break;
|
||||
|
||||
case BinaryExpressionType.Plus:
|
||||
Result = OperatorUtility.Add(left(), right());
|
||||
break;
|
||||
|
||||
case BinaryExpressionType.Times:
|
||||
Result = OperatorUtility.Multiply(left(), right());
|
||||
break;
|
||||
|
||||
case BinaryExpressionType.BitwiseAnd:
|
||||
Result = OperatorUtility.And(left(), right());
|
||||
break;
|
||||
|
||||
case BinaryExpressionType.BitwiseOr:
|
||||
Result = OperatorUtility.Or(left(), right());
|
||||
break;
|
||||
|
||||
case BinaryExpressionType.BitwiseXOr:
|
||||
Result = OperatorUtility.ExclusiveOr(left(), right());
|
||||
break;
|
||||
|
||||
case BinaryExpressionType.LeftShift:
|
||||
Result = OperatorUtility.LeftShift(left(), right());
|
||||
break;
|
||||
|
||||
case BinaryExpressionType.RightShift:
|
||||
Result = OperatorUtility.RightShift(left(), right());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Visit(UnaryExpression unary)
|
||||
{
|
||||
// Recursively evaluates the underlying expression
|
||||
unary.Expression.Accept(this);
|
||||
|
||||
switch (unary.Type)
|
||||
{
|
||||
case UnaryExpressionType.Not:
|
||||
Result = !ConversionUtility.Convert<bool>(Result);
|
||||
break;
|
||||
|
||||
case UnaryExpressionType.Negate:
|
||||
Result = OperatorUtility.Negate(Result);
|
||||
break;
|
||||
|
||||
case UnaryExpressionType.BitwiseNot:
|
||||
Result = OperatorUtility.Not(Result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Visit(ValueExpression value)
|
||||
{
|
||||
Result = value.Value;
|
||||
}
|
||||
|
||||
public override void Visit(FunctionExpression function)
|
||||
{
|
||||
var args = new FunctionArgs
|
||||
{
|
||||
Parameters = new Expression[function.Expressions.Length]
|
||||
};
|
||||
|
||||
// Don't call parameters right now, instead let the function do it as needed.
|
||||
// Some parameters shouldn't be called, for instance, in a if(), the "not" value might be a division by zero
|
||||
// Evaluating every value could produce unexpected behaviour
|
||||
for (var i = 0; i < function.Expressions.Length; i++)
|
||||
{
|
||||
args.Parameters[i] = new Expression(function.Expressions[i], options);
|
||||
args.Parameters[i].EvaluateFunction += EvaluateFunction;
|
||||
args.Parameters[i].EvaluateParameter += EvaluateParameter;
|
||||
|
||||
// Assign the parameters of the Expression to the arguments so that custom Functions and Parameters can use them
|
||||
args.Parameters[i].Parameters = Parameters;
|
||||
}
|
||||
|
||||
// Calls external implementation
|
||||
OnEvaluateFunction(IgnoreCase ? function.Identifier.Name.ToLower() : function.Identifier.Name, args);
|
||||
|
||||
// If an external implementation was found get the result back
|
||||
if (args.HasResult)
|
||||
{
|
||||
Result = args.Result;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (function.Identifier.Name.ToLower(CultureInfo.InvariantCulture))
|
||||
{
|
||||
case "abs":
|
||||
CheckCase(function, "Abs");
|
||||
CheckExactArgumentCount(function, 1);
|
||||
Result = Mathf.Abs(ConversionUtility.Convert<float>(Evaluate(function.Expressions[0])));
|
||||
break;
|
||||
|
||||
case "acos":
|
||||
CheckCase(function, "Acos");
|
||||
CheckExactArgumentCount(function, 1);
|
||||
Result = Mathf.Acos(ConversionUtility.Convert<float>(Evaluate(function.Expressions[0])));
|
||||
break;
|
||||
|
||||
case "asin":
|
||||
CheckCase(function, "Asin");
|
||||
CheckExactArgumentCount(function, 1);
|
||||
Result = Mathf.Asin(ConversionUtility.Convert<float>(Evaluate(function.Expressions[0])));
|
||||
break;
|
||||
|
||||
case "atan":
|
||||
CheckCase(function, "Atan");
|
||||
CheckExactArgumentCount(function, 1);
|
||||
Result = Mathf.Atan(ConversionUtility.Convert<float>(Evaluate(function.Expressions[0])));
|
||||
break;
|
||||
|
||||
case "ceil":
|
||||
CheckCase(function, "Ceil");
|
||||
CheckExactArgumentCount(function, 1);
|
||||
Result = Mathf.Ceil(ConversionUtility.Convert<float>(Evaluate(function.Expressions[0])));
|
||||
break;
|
||||
|
||||
case "cos":
|
||||
CheckCase(function, "Cos");
|
||||
CheckExactArgumentCount(function, 1);
|
||||
Result = Mathf.Cos(ConversionUtility.Convert<float>(Evaluate(function.Expressions[0])));
|
||||
break;
|
||||
|
||||
case "exp":
|
||||
CheckCase(function, "Exp");
|
||||
CheckExactArgumentCount(function, 1);
|
||||
Result = Mathf.Exp(ConversionUtility.Convert<float>(Evaluate(function.Expressions[0])));
|
||||
break;
|
||||
|
||||
case "floor":
|
||||
CheckCase(function, "Floor");
|
||||
CheckExactArgumentCount(function, 1);
|
||||
Result = Mathf.Floor(ConversionUtility.Convert<float>(Evaluate(function.Expressions[0])));
|
||||
break;
|
||||
|
||||
case "truncate":
|
||||
CheckCase(function, "Truncate");
|
||||
CheckExactArgumentCount(function, 1);
|
||||
Result = Mathf.FloorToInt(ConversionUtility.Convert<float>(Evaluate(function.Expressions[0])));
|
||||
break;
|
||||
|
||||
case "log":
|
||||
CheckCase(function, "Log");
|
||||
CheckExactArgumentCount(function, 2);
|
||||
Result = Mathf.Log(ConversionUtility.Convert<float>(Evaluate(function.Expressions[0])), ConversionUtility.Convert<float>(Evaluate(function.Expressions[1])));
|
||||
break;
|
||||
|
||||
case "log10":
|
||||
CheckCase(function, "Log10");
|
||||
CheckExactArgumentCount(function, 1);
|
||||
Result = Mathf.Log10(ConversionUtility.Convert<float>(Evaluate(function.Expressions[0])));
|
||||
break;
|
||||
|
||||
case "pow":
|
||||
CheckCase(function, "Pow");
|
||||
CheckExactArgumentCount(function, 2);
|
||||
Result = Mathf.Pow(ConversionUtility.Convert<float>(Evaluate(function.Expressions[0])), ConversionUtility.Convert<float>(Evaluate(function.Expressions[1])));
|
||||
break;
|
||||
|
||||
case "round":
|
||||
CheckCase(function, "Round");
|
||||
CheckExactArgumentCount(function, 1);
|
||||
//var rounding = (options & EvaluateOptions.RoundAwayFromZero) == EvaluateOptions.RoundAwayFromZero ? MidpointRounding.AwayFromZero : MidpointRounding.ToEven;
|
||||
Result = Mathf.Round(ConversionUtility.Convert<float>(Evaluate(function.Expressions[0])));
|
||||
break;
|
||||
|
||||
case "sign":
|
||||
CheckCase(function, "Sign");
|
||||
CheckExactArgumentCount(function, 1);
|
||||
Result = Mathf.Sign(ConversionUtility.Convert<float>(Evaluate(function.Expressions[0])));
|
||||
|
||||
break;
|
||||
|
||||
case "sin":
|
||||
CheckCase(function, "Sin");
|
||||
CheckExactArgumentCount(function, 1);
|
||||
Result = Mathf.Sin(ConversionUtility.Convert<float>(Evaluate(function.Expressions[0])));
|
||||
break;
|
||||
|
||||
case "sqrt":
|
||||
CheckCase(function, "Sqrt");
|
||||
CheckExactArgumentCount(function, 1);
|
||||
Result = Mathf.Sqrt(ConversionUtility.Convert<float>(Evaluate(function.Expressions[0])));
|
||||
|
||||
break;
|
||||
|
||||
case "tan":
|
||||
CheckCase(function, "Tan");
|
||||
CheckExactArgumentCount(function, 1);
|
||||
Result = Mathf.Tan(ConversionUtility.Convert<float>(Evaluate(function.Expressions[0])));
|
||||
|
||||
break;
|
||||
|
||||
case "max":
|
||||
CheckCase(function, "Max");
|
||||
CheckExactArgumentCount(function, 2);
|
||||
Result = Mathf.Max(ConversionUtility.Convert<float>(Evaluate(function.Expressions[0])), ConversionUtility.Convert<float>(Evaluate(function.Expressions[1])));
|
||||
break;
|
||||
|
||||
case "min":
|
||||
CheckCase(function, "Min");
|
||||
CheckExactArgumentCount(function, 2);
|
||||
Result = Mathf.Min(ConversionUtility.Convert<float>(Evaluate(function.Expressions[0])), ConversionUtility.Convert<float>(Evaluate(function.Expressions[1])));
|
||||
break;
|
||||
|
||||
case "in":
|
||||
CheckCase(function, "In");
|
||||
CheckExactArgumentCount(function, 2);
|
||||
|
||||
var parameter = Evaluate(function.Expressions[0]);
|
||||
|
||||
var evaluation = false;
|
||||
|
||||
// Goes through any values, and stop whe one is found
|
||||
for (var i = 1; i < function.Expressions.Length; i++)
|
||||
{
|
||||
var argument = Evaluate(function.Expressions[i]);
|
||||
|
||||
if (Equals(parameter, argument))
|
||||
{
|
||||
evaluation = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Result = evaluation;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new ArgumentException("Function not found", function.Identifier.Name);
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckCase(FunctionExpression function, string reference)
|
||||
{
|
||||
var called = function.Identifier.Name;
|
||||
|
||||
if (IgnoreCase)
|
||||
{
|
||||
if (string.Equals(called, reference, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
throw new ArgumentException("Function not found.", called);
|
||||
}
|
||||
|
||||
if (called != reference)
|
||||
{
|
||||
throw new ArgumentException($"Function not found: '{called}'. Try '{reference}' instead.");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnEvaluateFunction(string name, FunctionArgs args)
|
||||
{
|
||||
EvaluateFunction?.Invoke(flow, name, args);
|
||||
}
|
||||
|
||||
public override void Visit(IdentifierExpression identifier)
|
||||
{
|
||||
if (Parameters.ContainsKey(identifier.Name))
|
||||
{
|
||||
// The parameter is defined in the dictionary
|
||||
if (Parameters[identifier.Name] is Expression)
|
||||
{
|
||||
// The parameter is itself another Expression
|
||||
var expression = (Expression)Parameters[identifier.Name];
|
||||
|
||||
// Overloads parameters
|
||||
foreach (var p in Parameters)
|
||||
{
|
||||
expression.Parameters[p.Key] = p.Value;
|
||||
}
|
||||
|
||||
expression.EvaluateFunction += EvaluateFunction;
|
||||
expression.EvaluateParameter += EvaluateParameter;
|
||||
|
||||
Result = ((Expression)Parameters[identifier.Name]).Evaluate(flow);
|
||||
}
|
||||
else
|
||||
{
|
||||
Result = Parameters[identifier.Name];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The parameter should be defined in a callback method
|
||||
var args = new ParameterArgs();
|
||||
|
||||
// Calls external implementation
|
||||
OnEvaluateParameter(identifier.Name, args);
|
||||
|
||||
if (!args.HasResult)
|
||||
{
|
||||
throw new ArgumentException("Parameter was not defined", identifier.Name);
|
||||
}
|
||||
|
||||
Result = args.Result;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnEvaluateParameter(string name, ParameterArgs args)
|
||||
{
|
||||
EvaluateParameter?.Invoke(flow, name, args);
|
||||
}
|
||||
|
||||
public static void CheckExactArgumentCount(FunctionExpression function, int count)
|
||||
{
|
||||
if (function.Expressions.Length != count)
|
||||
{
|
||||
throw new ArgumentException($"{function.Identifier.Name}() takes at exactly {count} arguments. {function.Expressions.Length} provided.");
|
||||
}
|
||||
}
|
||||
|
||||
public static void CheckMinArgumentCount(FunctionExpression function, int count)
|
||||
{
|
||||
if (function.Expressions.Length < count)
|
||||
{
|
||||
throw new ArgumentException($"{function.Identifier.Name}() takes at at least {count} arguments. {function.Expressions.Length} provided.");
|
||||
}
|
||||
}
|
||||
|
||||
private delegate T Func<T>();
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b0e70958412a3493888a351443ad8866
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,301 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using Unity.VisualScripting.Antlr3.Runtime;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.VisualScripting.Dependencies.NCalc
|
||||
{
|
||||
public class Expression
|
||||
{
|
||||
private Expression()
|
||||
{
|
||||
// Fix: the original grammar doesn't include a null identifier.
|
||||
Parameters["null"] = Parameters["NULL"] = null;
|
||||
}
|
||||
|
||||
public Expression(string expression, EvaluateOptions options = EvaluateOptions.None) : this()
|
||||
{
|
||||
if (string.IsNullOrEmpty(expression))
|
||||
{
|
||||
throw new ArgumentException("Expression can't be empty", nameof(expression));
|
||||
}
|
||||
|
||||
// Fix: The original grammar doesn't allow double quotes for strings.
|
||||
expression = expression.Replace('\"', '\'');
|
||||
|
||||
OriginalExpression = expression;
|
||||
Options = options;
|
||||
}
|
||||
|
||||
public Expression(LogicalExpression expression, EvaluateOptions options = EvaluateOptions.None) : this()
|
||||
{
|
||||
if (expression == null)
|
||||
{
|
||||
throw new ArgumentException("Expression can't be null", nameof(expression));
|
||||
}
|
||||
|
||||
ParsedExpression = expression;
|
||||
Options = options;
|
||||
}
|
||||
|
||||
public event EvaluateFunctionHandler EvaluateFunction;
|
||||
public event EvaluateParameterHandler EvaluateParameter;
|
||||
|
||||
/// <summary>
|
||||
/// Textual representation of the expression to evaluate.
|
||||
/// </summary>
|
||||
protected readonly string OriginalExpression;
|
||||
|
||||
protected Dictionary<string, IEnumerator> ParameterEnumerators;
|
||||
|
||||
private Dictionary<string, object> _parameters;
|
||||
|
||||
public EvaluateOptions Options { get; set; }
|
||||
|
||||
public string Error { get; private set; }
|
||||
|
||||
public LogicalExpression ParsedExpression { get; private set; }
|
||||
|
||||
public Dictionary<string, object> Parameters
|
||||
{
|
||||
get
|
||||
{
|
||||
return _parameters ?? (_parameters = new Dictionary<string, object>());
|
||||
}
|
||||
set
|
||||
{
|
||||
_parameters = value;
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateUnityTimeParameters()
|
||||
{
|
||||
Parameters["dt"] = Parameters["DT"] = Time.deltaTime;
|
||||
Parameters["second"] = Parameters["Second"] = 1 / Time.deltaTime;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pre-compiles the expression in order to check syntax errors.
|
||||
/// If errors are detected, the Error property contains the message.
|
||||
/// </summary>
|
||||
/// <returns>True if the expression syntax is correct, otherwise false</returns>
|
||||
public bool HasErrors()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (ParsedExpression == null)
|
||||
{
|
||||
ParsedExpression = Compile(OriginalExpression, (Options & EvaluateOptions.NoCache) == EvaluateOptions.NoCache);
|
||||
}
|
||||
|
||||
// In case HasErrors() is called multiple times for the same expression
|
||||
return ParsedExpression != null && Error != null;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Error = e.Message;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public object Evaluate(Flow flow)
|
||||
{
|
||||
if (HasErrors())
|
||||
{
|
||||
throw new EvaluationException(Error);
|
||||
}
|
||||
|
||||
if (ParsedExpression == null)
|
||||
{
|
||||
ParsedExpression = Compile(OriginalExpression, (Options & EvaluateOptions.NoCache) == EvaluateOptions.NoCache);
|
||||
}
|
||||
|
||||
var visitor = new EvaluationVisitor(flow, Options);
|
||||
visitor.EvaluateFunction += EvaluateFunction;
|
||||
visitor.EvaluateParameter += EvaluateParameter;
|
||||
visitor.Parameters = Parameters;
|
||||
|
||||
// If array evaluation, execute the same expression multiple times
|
||||
if ((Options & EvaluateOptions.IterateParameters) == EvaluateOptions.IterateParameters)
|
||||
{
|
||||
var size = -1;
|
||||
|
||||
ParameterEnumerators = new Dictionary<string, IEnumerator>();
|
||||
|
||||
foreach (var parameter in Parameters.Values)
|
||||
{
|
||||
if (parameter is IEnumerable enumerable)
|
||||
{
|
||||
var localsize = 0;
|
||||
|
||||
foreach (var o in enumerable)
|
||||
{
|
||||
localsize++;
|
||||
}
|
||||
|
||||
if (size == -1)
|
||||
{
|
||||
size = localsize;
|
||||
}
|
||||
else if (localsize != size)
|
||||
{
|
||||
throw new EvaluationException("When IterateParameters option is used, IEnumerable parameters must have the same number of items.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var key in Parameters.Keys)
|
||||
{
|
||||
var parameter = Parameters[key] as IEnumerable;
|
||||
if (parameter != null)
|
||||
{
|
||||
ParameterEnumerators.Add(key, parameter.GetEnumerator());
|
||||
}
|
||||
}
|
||||
|
||||
var results = new List<object>();
|
||||
|
||||
for (var i = 0; i < size; i++)
|
||||
{
|
||||
foreach (var key in ParameterEnumerators.Keys)
|
||||
{
|
||||
var enumerator = ParameterEnumerators[key];
|
||||
enumerator.MoveNext();
|
||||
Parameters[key] = enumerator.Current;
|
||||
}
|
||||
|
||||
ParsedExpression.Accept(visitor);
|
||||
results.Add(visitor.Result);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
else
|
||||
{
|
||||
ParsedExpression.Accept(visitor);
|
||||
return visitor.Result;
|
||||
}
|
||||
}
|
||||
|
||||
public static LogicalExpression Compile(string expression, bool noCache)
|
||||
{
|
||||
LogicalExpression logicalExpression = null;
|
||||
|
||||
if (_cacheEnabled && !noCache)
|
||||
{
|
||||
try
|
||||
{
|
||||
Rwl.AcquireReaderLock(Timeout.Infinite);
|
||||
|
||||
if (_compiledExpressions.ContainsKey(expression))
|
||||
{
|
||||
Trace.TraceInformation("Expression retrieved from cache: " + expression);
|
||||
var wr = _compiledExpressions[expression];
|
||||
logicalExpression = wr.Target as LogicalExpression;
|
||||
|
||||
if (wr.IsAlive && logicalExpression != null)
|
||||
{
|
||||
return logicalExpression;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Rwl.ReleaseReaderLock();
|
||||
}
|
||||
}
|
||||
|
||||
if (logicalExpression == null)
|
||||
{
|
||||
var lexer = new NCalcLexer(new ANTLRStringStream(expression));
|
||||
var parser = new NCalcParser(new CommonTokenStream(lexer));
|
||||
|
||||
logicalExpression = parser.ncalcExpression().value;
|
||||
|
||||
if (parser.Errors != null && parser.Errors.Count > 0)
|
||||
{
|
||||
throw new EvaluationException(String.Join(Environment.NewLine, parser.Errors.ToArray()));
|
||||
}
|
||||
|
||||
if (_cacheEnabled && !noCache)
|
||||
{
|
||||
try
|
||||
{
|
||||
Rwl.AcquireWriterLock(Timeout.Infinite);
|
||||
_compiledExpressions[expression] = new WeakReference(logicalExpression);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Rwl.ReleaseWriterLock();
|
||||
}
|
||||
|
||||
CleanCache();
|
||||
|
||||
Trace.TraceInformation("Expression added to cache: " + expression);
|
||||
}
|
||||
}
|
||||
|
||||
return logicalExpression;
|
||||
}
|
||||
|
||||
#region Cache management
|
||||
|
||||
private static bool _cacheEnabled = true;
|
||||
private static Dictionary<string, WeakReference> _compiledExpressions = new Dictionary<string, WeakReference>();
|
||||
private static readonly ReaderWriterLock Rwl = new ReaderWriterLock();
|
||||
|
||||
public static bool CacheEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return _cacheEnabled;
|
||||
}
|
||||
set
|
||||
{
|
||||
_cacheEnabled = value;
|
||||
|
||||
if (!CacheEnabled)
|
||||
{
|
||||
// Clears cache
|
||||
_compiledExpressions = new Dictionary<string, WeakReference>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes unused entries from cached compiled expression.
|
||||
/// </summary>
|
||||
private static void CleanCache()
|
||||
{
|
||||
var keysToRemove = new List<string>();
|
||||
|
||||
try
|
||||
{
|
||||
Rwl.AcquireWriterLock(Timeout.Infinite);
|
||||
|
||||
foreach (var de in _compiledExpressions)
|
||||
{
|
||||
if (!de.Value.IsAlive)
|
||||
{
|
||||
keysToRemove.Add(de.Key);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var key in keysToRemove)
|
||||
{
|
||||
_compiledExpressions.Remove(key);
|
||||
Trace.TraceInformation("Cache entry released: " + key);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Rwl.ReleaseReaderLock();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3dd474c9747c7444d9ca4b191b48301d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
|
||||
namespace Unity.VisualScripting.Dependencies.NCalc
|
||||
{
|
||||
public class FunctionArgs : EventArgs
|
||||
{
|
||||
private object _result;
|
||||
|
||||
private Expression[] _parameters = new Expression[0];
|
||||
|
||||
public object Result
|
||||
{
|
||||
get
|
||||
{
|
||||
return _result;
|
||||
}
|
||||
set
|
||||
{
|
||||
_result = value;
|
||||
HasResult = true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasResult { get; set; }
|
||||
|
||||
public Expression[] Parameters
|
||||
{
|
||||
get
|
||||
{
|
||||
return _parameters;
|
||||
}
|
||||
set
|
||||
{
|
||||
_parameters = value;
|
||||
}
|
||||
}
|
||||
|
||||
public object[] EvaluateParameters(Flow flow)
|
||||
{
|
||||
var values = new object[_parameters.Length];
|
||||
for (var i = 0; i < values.Length; i++)
|
||||
{
|
||||
values[i] = _parameters[i].Evaluate(flow);
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 55514a8464191433785154307e445337
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,20 @@
|
||||
namespace Unity.VisualScripting.Dependencies.NCalc
|
||||
{
|
||||
public class FunctionExpression : LogicalExpression
|
||||
{
|
||||
public FunctionExpression(IdentifierExpression identifier, LogicalExpression[] expressions)
|
||||
{
|
||||
Identifier = identifier;
|
||||
Expressions = expressions;
|
||||
}
|
||||
|
||||
public IdentifierExpression Identifier { get; set; }
|
||||
|
||||
public LogicalExpression[] Expressions { get; set; }
|
||||
|
||||
public override void Accept(LogicalExpressionVisitor visitor)
|
||||
{
|
||||
visitor.Visit(this);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9e4f622436c3c477bb484bd0114b74cb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,17 @@
|
||||
namespace Unity.VisualScripting.Dependencies.NCalc
|
||||
{
|
||||
public class IdentifierExpression : LogicalExpression
|
||||
{
|
||||
public IdentifierExpression(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public override void Accept(LogicalExpressionVisitor visitor)
|
||||
{
|
||||
visitor.Visit(this);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ccf41f828829d4eafa25be821b8e2a60
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,258 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace Unity.VisualScripting.Dependencies.NCalc
|
||||
{
|
||||
public abstract class LogicalExpression
|
||||
{
|
||||
public BinaryExpression And(LogicalExpression operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.And, this, operand);
|
||||
}
|
||||
|
||||
public BinaryExpression And(object operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.And, this, new ValueExpression(operand));
|
||||
}
|
||||
|
||||
public BinaryExpression DividedBy(LogicalExpression operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.Div, this, operand);
|
||||
}
|
||||
|
||||
public BinaryExpression DividedBy(object operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.Div, this, new ValueExpression(operand));
|
||||
}
|
||||
|
||||
public BinaryExpression EqualsTo(LogicalExpression operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.Equal, this, operand);
|
||||
}
|
||||
|
||||
public BinaryExpression EqualsTo(object operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.Equal, this, new ValueExpression(operand));
|
||||
}
|
||||
|
||||
public BinaryExpression GreaterThan(LogicalExpression operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.Greater, this, operand);
|
||||
}
|
||||
|
||||
public BinaryExpression GreaterThan(object operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.Greater, this, new ValueExpression(operand));
|
||||
}
|
||||
|
||||
public BinaryExpression GreaterOrEqualThan(LogicalExpression operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.GreaterOrEqual, this, operand);
|
||||
}
|
||||
|
||||
public BinaryExpression GreaterOrEqualThan(object operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.GreaterOrEqual, this, new ValueExpression(operand));
|
||||
}
|
||||
|
||||
public BinaryExpression LesserThan(LogicalExpression operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.Lesser, this, operand);
|
||||
}
|
||||
|
||||
public BinaryExpression LesserThan(object operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.Lesser, this, new ValueExpression(operand));
|
||||
}
|
||||
|
||||
public BinaryExpression LesserOrEqualThan(LogicalExpression operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.LesserOrEqual, this, operand);
|
||||
}
|
||||
|
||||
public BinaryExpression LesserOrEqualThan(object operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.LesserOrEqual, this, new ValueExpression(operand));
|
||||
}
|
||||
|
||||
public BinaryExpression Minus(LogicalExpression operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.Minus, this, operand);
|
||||
}
|
||||
|
||||
public BinaryExpression Minus(object operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.Minus, this, new ValueExpression(operand));
|
||||
}
|
||||
|
||||
public BinaryExpression Modulo(LogicalExpression operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.Modulo, this, operand);
|
||||
}
|
||||
|
||||
public BinaryExpression Modulo(object operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.Modulo, this, new ValueExpression(operand));
|
||||
}
|
||||
|
||||
public BinaryExpression NotEqual(LogicalExpression operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.NotEqual, this, operand);
|
||||
}
|
||||
|
||||
public BinaryExpression NotEqual(object operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.NotEqual, this, new ValueExpression(operand));
|
||||
}
|
||||
|
||||
public BinaryExpression Or(LogicalExpression operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.Or, this, operand);
|
||||
}
|
||||
|
||||
public BinaryExpression Or(object operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.Or, this, new ValueExpression(operand));
|
||||
}
|
||||
|
||||
public BinaryExpression Plus(LogicalExpression operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.Plus, this, operand);
|
||||
}
|
||||
|
||||
public BinaryExpression Plus(object operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.Plus, this, new ValueExpression(operand));
|
||||
}
|
||||
|
||||
public BinaryExpression Mult(LogicalExpression operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.Times, this, operand);
|
||||
}
|
||||
|
||||
public BinaryExpression Mult(object operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.Times, this, new ValueExpression(operand));
|
||||
}
|
||||
|
||||
public BinaryExpression BitwiseOr(LogicalExpression operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.BitwiseOr, this, operand);
|
||||
}
|
||||
|
||||
public BinaryExpression BitwiseOr(object operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.BitwiseOr, this, new ValueExpression(operand));
|
||||
}
|
||||
|
||||
public BinaryExpression BitwiseAnd(LogicalExpression operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.BitwiseAnd, this, operand);
|
||||
}
|
||||
|
||||
public BinaryExpression BitwiseAnd(object operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.BitwiseAnd, this, new ValueExpression(operand));
|
||||
}
|
||||
|
||||
public BinaryExpression BitwiseXOr(LogicalExpression operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.BitwiseXOr, this, operand);
|
||||
}
|
||||
|
||||
public BinaryExpression BitwiseXOr(object operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.BitwiseXOr, this, new ValueExpression(operand));
|
||||
}
|
||||
|
||||
public BinaryExpression LeftShift(LogicalExpression operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.LeftShift, this, operand);
|
||||
}
|
||||
|
||||
public BinaryExpression LeftShift(object operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.LeftShift, this, new ValueExpression(operand));
|
||||
}
|
||||
|
||||
public BinaryExpression RightShift(LogicalExpression operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.RightShift, this, operand);
|
||||
}
|
||||
|
||||
public BinaryExpression RightShift(object operand)
|
||||
{
|
||||
return new BinaryExpression(BinaryExpressionType.RightShift, this, new ValueExpression(operand));
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var serializer = new SerializationVisitor();
|
||||
|
||||
Accept(serializer);
|
||||
|
||||
return serializer.Result.ToString().TrimEnd(' ');
|
||||
}
|
||||
|
||||
// This method is not just syntactic sugar.
|
||||
// It chooses the proper overload of Visit() based on the current type.
|
||||
public virtual void Accept(LogicalExpressionVisitor visitor)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private const char BS = '\\';
|
||||
|
||||
private static string ExtractString(string text)
|
||||
{
|
||||
var sb = new StringBuilder(text);
|
||||
var startIndex = 1; // Skip initial quote
|
||||
var slashIndex = -1;
|
||||
|
||||
while ((slashIndex = sb.ToString().IndexOf(BS, startIndex)) != -1)
|
||||
{
|
||||
var escapeType = sb[slashIndex + 1];
|
||||
|
||||
switch (escapeType)
|
||||
{
|
||||
case 'u':
|
||||
var hcode = String.Concat(sb[slashIndex + 4], sb[slashIndex + 5]);
|
||||
var lcode = String.Concat(sb[slashIndex + 2], sb[slashIndex + 3]);
|
||||
var unicodeChar = Encoding.Unicode.GetChars(new[] { Convert.ToByte(hcode, 16), Convert.ToByte(lcode, 16) })[0];
|
||||
sb.Remove(slashIndex, 6).Insert(slashIndex, unicodeChar);
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
sb.Remove(slashIndex, 2).Insert(slashIndex, '\n');
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
sb.Remove(slashIndex, 2).Insert(slashIndex, '\r');
|
||||
break;
|
||||
|
||||
case 't':
|
||||
sb.Remove(slashIndex, 2).Insert(slashIndex, '\t');
|
||||
break;
|
||||
|
||||
case '\'':
|
||||
sb.Remove(slashIndex, 2).Insert(slashIndex, '\'');
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
sb.Remove(slashIndex, 2).Insert(slashIndex, '\\');
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new ApplicationException("Unvalid escape sequence: \\" + escapeType);
|
||||
}
|
||||
|
||||
startIndex = slashIndex + 1;
|
||||
}
|
||||
|
||||
sb.Remove(0, 1);
|
||||
sb.Remove(sb.Length - 1, 1);
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2d630dc61d2194bf28114c04393228bb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,12 @@
|
||||
namespace Unity.VisualScripting.Dependencies.NCalc
|
||||
{
|
||||
public abstract class LogicalExpressionVisitor
|
||||
{
|
||||
public abstract void Visit(TernaryExpression ternary);
|
||||
public abstract void Visit(BinaryExpression binary);
|
||||
public abstract void Visit(UnaryExpression unary);
|
||||
public abstract void Visit(ValueExpression value);
|
||||
public abstract void Visit(FunctionExpression function);
|
||||
public abstract void Visit(IdentifierExpression identifier);
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6a2c35661d97146b2b302a94d1120f35
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,303 @@
|
||||
grammar NCalc;
|
||||
|
||||
options
|
||||
{
|
||||
output=AST;
|
||||
ASTLabelType=CommonTree;
|
||||
language=CSharp;
|
||||
}
|
||||
|
||||
@header {
|
||||
using System.Text;
|
||||
using System.Globalization;
|
||||
using System.Collections.Generic;
|
||||
using NCalc.Domain;
|
||||
}
|
||||
|
||||
@members {
|
||||
private const char BS = '\\';
|
||||
private static NumberFormatInfo numberFormatInfo = new NumberFormatInfo();
|
||||
|
||||
private string extractString(string text) {
|
||||
|
||||
StringBuilder sb = new StringBuilder(text);
|
||||
int startIndex = 1; // Skip initial quote
|
||||
int slashIndex = -1;
|
||||
|
||||
while ((slashIndex = sb.ToString().IndexOf(BS, startIndex)) != -1)
|
||||
{
|
||||
char escapeType = sb[slashIndex + 1];
|
||||
switch (escapeType)
|
||||
{
|
||||
case 'u':
|
||||
string hcode = String.Concat(sb[slashIndex+4], sb[slashIndex+5]);
|
||||
string lcode = String.Concat(sb[slashIndex+2], sb[slashIndex+3]);
|
||||
char unicodeChar = Encoding.Unicode.GetChars(new byte[] { System.Convert.ToByte(hcode, 16), System.Convert.ToByte(lcode, 16)} )[0];
|
||||
sb.Remove(slashIndex, 6).Insert(slashIndex, unicodeChar);
|
||||
break;
|
||||
case 'n': sb.Remove(slashIndex, 2).Insert(slashIndex, '\n'); break;
|
||||
case 'r': sb.Remove(slashIndex, 2).Insert(slashIndex, '\r'); break;
|
||||
case 't': sb.Remove(slashIndex, 2).Insert(slashIndex, '\t'); break;
|
||||
case '\'': sb.Remove(slashIndex, 2).Insert(slashIndex, '\''); break;
|
||||
case '\\': sb.Remove(slashIndex, 2).Insert(slashIndex, '\\'); break;
|
||||
default: throw new RecognitionException("Unvalid escape sequence: \\" + escapeType);
|
||||
}
|
||||
|
||||
startIndex = slashIndex + 1;
|
||||
|
||||
}
|
||||
|
||||
sb.Remove(0, 1);
|
||||
sb.Remove(sb.Length - 1, 1);
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public List<string> Errors { get; private set; }
|
||||
|
||||
public override void DisplayRecognitionError(String[] tokenNames, RecognitionException e) {
|
||||
|
||||
base.DisplayRecognitionError(tokenNames, e);
|
||||
|
||||
if(Errors == null)
|
||||
{
|
||||
Errors = new List<string>();
|
||||
}
|
||||
|
||||
String hdr = GetErrorHeader(e);
|
||||
String msg = GetErrorMessage(e, tokenNames);
|
||||
Errors.Add(msg + " at " + hdr);
|
||||
}
|
||||
}
|
||||
|
||||
@init {
|
||||
numberFormatInfo.NumberDecimalSeparator = ".";
|
||||
}
|
||||
|
||||
ncalcExpression returns [LogicalExpression value]
|
||||
: logicalExpression EOF! {$value = $logicalExpression.value; }
|
||||
;
|
||||
|
||||
logicalExpression returns [LogicalExpression value]
|
||||
: left=conditionalExpression { $value = $left.value; } ( '?' middle=conditionalExpression ':' right=conditionalExpression { $value = new TernaryExpression($left.value, $middle.value, $right.value); })?
|
||||
;
|
||||
|
||||
conditionalExpression returns [LogicalExpression value]
|
||||
@init {
|
||||
BinaryExpressionType type = BinaryExpressionType.Unknown;
|
||||
}
|
||||
: left=booleanAndExpression { $value = $left.value; } (
|
||||
('||' | 'or') { type = BinaryExpressionType.Or; }
|
||||
right=conditionalExpression { $value = new BinaryExpression(type, $value, $right.value); }
|
||||
)*
|
||||
;
|
||||
|
||||
booleanAndExpression returns [LogicalExpression value]
|
||||
@init {
|
||||
BinaryExpressionType type = BinaryExpressionType.Unknown;
|
||||
}
|
||||
: left=bitwiseOrExpression { $value = $left.value; } (
|
||||
('&&' | 'and') { type = BinaryExpressionType.And; }
|
||||
right=bitwiseOrExpression { $value = new BinaryExpression(type, $value, $right.value); }
|
||||
)*
|
||||
;
|
||||
|
||||
bitwiseOrExpression returns [LogicalExpression value]
|
||||
@init {
|
||||
BinaryExpressionType type = BinaryExpressionType.Unknown;
|
||||
}
|
||||
: left=bitwiseXOrExpression { $value = $left.value; } (
|
||||
'|' { type = BinaryExpressionType.BitwiseOr; }
|
||||
right=bitwiseOrExpression { $value = new BinaryExpression(type, $value, $right.value); }
|
||||
)*
|
||||
;
|
||||
|
||||
bitwiseXOrExpression returns [LogicalExpression value]
|
||||
@init {
|
||||
BinaryExpressionType type = BinaryExpressionType.Unknown;
|
||||
}
|
||||
: left=bitwiseAndExpression { $value = $left.value; } (
|
||||
'^' { type = BinaryExpressionType.BitwiseXOr; }
|
||||
right=bitwiseAndExpression { $value = new BinaryExpression(type, $value, $right.value); }
|
||||
)*
|
||||
;
|
||||
|
||||
bitwiseAndExpression returns [LogicalExpression value]
|
||||
@init {
|
||||
BinaryExpressionType type = BinaryExpressionType.Unknown;
|
||||
}
|
||||
: left=equalityExpression { $value = $left.value; } (
|
||||
'&' { type = BinaryExpressionType.BitwiseAnd; }
|
||||
right=equalityExpression { $value = new BinaryExpression(type, $value, $right.value); }
|
||||
)*
|
||||
;
|
||||
|
||||
equalityExpression returns [LogicalExpression value]
|
||||
@init {
|
||||
BinaryExpressionType type = BinaryExpressionType.Unknown;
|
||||
}
|
||||
: left=relationalExpression { $value = $left.value; } (
|
||||
( ('==' | '=' ) { type = BinaryExpressionType.Equal; }
|
||||
| ('!=' | '<>' ) { type = BinaryExpressionType.NotEqual; } )
|
||||
right=relationalExpression { $value = new BinaryExpression(type, $value, $right.value); }
|
||||
)*
|
||||
;
|
||||
|
||||
relationalExpression returns [LogicalExpression value]
|
||||
@init {
|
||||
BinaryExpressionType type = BinaryExpressionType.Unknown;
|
||||
}
|
||||
: left=shiftExpression { $value = $left.value; } (
|
||||
( '<' { type = BinaryExpressionType.Lesser; }
|
||||
| '<=' { type = BinaryExpressionType.LesserOrEqual; }
|
||||
| '>' { type = BinaryExpressionType.Greater; }
|
||||
| '>=' { type = BinaryExpressionType.GreaterOrEqual; } )
|
||||
right=shiftExpression { $value = new BinaryExpression(type, $value, $right.value); }
|
||||
)*
|
||||
;
|
||||
|
||||
shiftExpression returns [LogicalExpression value]
|
||||
@init {
|
||||
BinaryExpressionType type = BinaryExpressionType.Unknown;
|
||||
}
|
||||
: left=additiveExpression { $value = $left.value; } (
|
||||
( '<<' { type = BinaryExpressionType.LeftShift; }
|
||||
| '>>' { type = BinaryExpressionType.RightShift; } )
|
||||
right=additiveExpression { $value = new BinaryExpression(type, $value, $right.value); }
|
||||
)*
|
||||
;
|
||||
|
||||
additiveExpression returns [LogicalExpression value]
|
||||
@init {
|
||||
BinaryExpressionType type = BinaryExpressionType.Unknown;
|
||||
}
|
||||
: left=multiplicativeExpression { $value = $left.value; } (
|
||||
( '+' { type = BinaryExpressionType.Plus; }
|
||||
| '-' { type = BinaryExpressionType.Minus; } )
|
||||
right=multiplicativeExpression { $value = new BinaryExpression(type, $value, $right.value); }
|
||||
)*
|
||||
;
|
||||
|
||||
multiplicativeExpression returns [LogicalExpression value]
|
||||
@init {
|
||||
BinaryExpressionType type = BinaryExpressionType.Unknown;
|
||||
}
|
||||
: left=unaryExpression { $value = $left.value); } (
|
||||
( '*' { type = BinaryExpressionType.Times; }
|
||||
| '/' { type = BinaryExpressionType.Div; }
|
||||
| '%' { type = BinaryExpressionType.Modulo; } )
|
||||
right=unaryExpression { $value = new BinaryExpression(type, $value, $right.value); }
|
||||
)*
|
||||
;
|
||||
|
||||
|
||||
unaryExpression returns [LogicalExpression value]
|
||||
: primaryExpression { $value = $primaryExpression.value; }
|
||||
| ('!' | 'not') primaryExpression { $value = new UnaryExpression(UnaryExpressionType.Not, $primaryExpression.value); }
|
||||
| ('~') primaryExpression { $value = new UnaryExpression(UnaryExpressionType.BitwiseNot, $primaryExpression.value); }
|
||||
| '-' primaryExpression { $value = new UnaryExpression(UnaryExpressionType.Negate, $primaryExpression.value); }
|
||||
;
|
||||
|
||||
primaryExpression returns [LogicalExpression value]
|
||||
: '(' logicalExpression ')' { $value = $logicalExpression.value; }
|
||||
| expr=value { $value = $expr.value; }
|
||||
| identifier {$value = (LogicalExpression) $identifier.value; } (arguments {$value = new Function($identifier.value, ($arguments.value).ToArray()); })?
|
||||
;
|
||||
|
||||
value returns [ValueExpression value]
|
||||
: INTEGER { try { $value = new ValueExpression(int.Parse($INTEGER.text)); } catch(System.OverflowException) { $value = new ValueExpression(long.Parse($INTEGER.text)); } }
|
||||
| FLOAT { $value = new ValueExpression(double.Parse($FLOAT.text, NumberStyles.Float, numberFormatInfo)); }
|
||||
| STRING { $value = new ValueExpression(extractString($STRING.text)); }
|
||||
| DATETIME { $value = new ValueExpression(DateTime.Parse($DATETIME.text.Substring(1, $DATETIME.text.Length-2))); }
|
||||
| TRUE { $value = new ValueExpression(true); }
|
||||
| FALSE { $value = new ValueExpression(false); }
|
||||
;
|
||||
|
||||
identifier returns[Identifier value]
|
||||
: ID { $value = new Identifier($ID.text); }
|
||||
| NAME { $value = new Identifier($NAME.text.Substring(1, $NAME.text.Length-2)); }
|
||||
;
|
||||
|
||||
expressionList returns [List<LogicalExpression> value]
|
||||
@init {
|
||||
List<LogicalExpression> expressions = new List<LogicalExpression>();
|
||||
}
|
||||
: first=logicalExpression {expressions.Add($first.value);} ( ',' follow=logicalExpression {expressions.Add($follow.value);})*
|
||||
{ $value = expressions; }
|
||||
;
|
||||
|
||||
arguments returns [List<LogicalExpression> value]
|
||||
@init {
|
||||
$value = new List<LogicalExpression>();
|
||||
}
|
||||
: '(' ( expressionList {$value = $expressionList.value;} )? ')'
|
||||
;
|
||||
|
||||
TRUE
|
||||
: 'true'
|
||||
;
|
||||
|
||||
FALSE
|
||||
: 'false'
|
||||
;
|
||||
|
||||
ID
|
||||
: LETTER (LETTER | DIGIT)*
|
||||
;
|
||||
|
||||
INTEGER
|
||||
: DIGIT+
|
||||
;
|
||||
|
||||
FLOAT
|
||||
: DIGIT* '.' DIGIT+ E?
|
||||
| DIGIT+ E
|
||||
;
|
||||
|
||||
STRING
|
||||
: '\'' ( EscapeSequence | (options {greedy=false;} : ~('\u0000'..'\u001f' | '\\' | '\'' ) ) )* '\''
|
||||
;
|
||||
|
||||
DATETIME
|
||||
: '#' (options {greedy=false;} : ~('#')*) '#'
|
||||
;
|
||||
|
||||
NAME : '[' (options {greedy=false;} : ~(']')*) ']'
|
||||
;
|
||||
|
||||
E : ('E'|'e') ('+'|'-')? DIGIT+
|
||||
;
|
||||
|
||||
fragment LETTER
|
||||
: 'a'..'z'
|
||||
| 'A'..'Z'
|
||||
| '_'
|
||||
;
|
||||
|
||||
fragment DIGIT
|
||||
: '0'..'9'
|
||||
;
|
||||
|
||||
fragment EscapeSequence
|
||||
: '\\'
|
||||
(
|
||||
'n'
|
||||
| 'r'
|
||||
| 't'
|
||||
| '\''
|
||||
| '\\'
|
||||
| UnicodeEscape
|
||||
)
|
||||
;
|
||||
|
||||
fragment HexDigit
|
||||
: ('0'..'9'|'a'..'f'|'A'..'F') ;
|
||||
|
||||
|
||||
fragment UnicodeEscape
|
||||
: 'u' HexDigit HexDigit HexDigit HexDigit
|
||||
;
|
||||
|
||||
/* Ignore white spaces */
|
||||
WS : (' '|'\r'|'\t'|'\u000C'|'\n') {$channel=HIDDEN;}
|
||||
;
|
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1d65eede9661f46a88d6e1949070eb9f
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d81700b95c8e3471584ffa94fd06b03f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 87e1dcf4a9a154ad291d02cad1d920ca
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
|
||||
namespace Unity.VisualScripting.Dependencies.NCalc
|
||||
{
|
||||
public class ParameterArgs : EventArgs
|
||||
{
|
||||
private object _result;
|
||||
|
||||
public object Result
|
||||
{
|
||||
get
|
||||
{
|
||||
return _result;
|
||||
}
|
||||
set
|
||||
{
|
||||
_result = value;
|
||||
HasResult = true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasResult { get; set; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1b211073028ea4467ad1c7f48e0b3530
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,211 @@
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
namespace Unity.VisualScripting.Dependencies.NCalc
|
||||
{
|
||||
public class SerializationVisitor : LogicalExpressionVisitor
|
||||
{
|
||||
public SerializationVisitor()
|
||||
{
|
||||
Result = new StringBuilder();
|
||||
_numberFormatInfo = new NumberFormatInfo { NumberDecimalSeparator = "." };
|
||||
}
|
||||
|
||||
private readonly NumberFormatInfo _numberFormatInfo;
|
||||
|
||||
public StringBuilder Result { get; protected set; }
|
||||
|
||||
public override void Visit(TernaryExpression ternary)
|
||||
{
|
||||
EncapsulateNoValue(ternary.LeftExpression);
|
||||
|
||||
Result.Append("? ");
|
||||
|
||||
EncapsulateNoValue(ternary.MiddleExpression);
|
||||
|
||||
Result.Append(": ");
|
||||
|
||||
EncapsulateNoValue(ternary.RightExpression);
|
||||
}
|
||||
|
||||
public override void Visit(BinaryExpression binary)
|
||||
{
|
||||
EncapsulateNoValue(binary.LeftExpression);
|
||||
|
||||
switch (binary.Type)
|
||||
{
|
||||
case BinaryExpressionType.And:
|
||||
Result.Append("and ");
|
||||
break;
|
||||
|
||||
case BinaryExpressionType.Or:
|
||||
Result.Append("or ");
|
||||
break;
|
||||
|
||||
case BinaryExpressionType.Div:
|
||||
Result.Append("/ ");
|
||||
break;
|
||||
|
||||
case BinaryExpressionType.Equal:
|
||||
Result.Append("= ");
|
||||
break;
|
||||
|
||||
case BinaryExpressionType.Greater:
|
||||
Result.Append("> ");
|
||||
break;
|
||||
|
||||
case BinaryExpressionType.GreaterOrEqual:
|
||||
Result.Append(">= ");
|
||||
break;
|
||||
|
||||
case BinaryExpressionType.Lesser:
|
||||
Result.Append("< ");
|
||||
break;
|
||||
|
||||
case BinaryExpressionType.LesserOrEqual:
|
||||
Result.Append("<= ");
|
||||
break;
|
||||
|
||||
case BinaryExpressionType.Minus:
|
||||
Result.Append("- ");
|
||||
break;
|
||||
|
||||
case BinaryExpressionType.Modulo:
|
||||
Result.Append("% ");
|
||||
break;
|
||||
|
||||
case BinaryExpressionType.NotEqual:
|
||||
Result.Append("!= ");
|
||||
break;
|
||||
|
||||
case BinaryExpressionType.Plus:
|
||||
Result.Append("+ ");
|
||||
break;
|
||||
|
||||
case BinaryExpressionType.Times:
|
||||
Result.Append("* ");
|
||||
break;
|
||||
|
||||
case BinaryExpressionType.BitwiseAnd:
|
||||
Result.Append("& ");
|
||||
break;
|
||||
|
||||
case BinaryExpressionType.BitwiseOr:
|
||||
Result.Append("| ");
|
||||
break;
|
||||
|
||||
case BinaryExpressionType.BitwiseXOr:
|
||||
Result.Append("~ ");
|
||||
break;
|
||||
|
||||
case BinaryExpressionType.LeftShift:
|
||||
Result.Append("<< ");
|
||||
break;
|
||||
|
||||
case BinaryExpressionType.RightShift:
|
||||
Result.Append(">> ");
|
||||
break;
|
||||
}
|
||||
|
||||
EncapsulateNoValue(binary.RightExpression);
|
||||
}
|
||||
|
||||
public override void Visit(UnaryExpression unary)
|
||||
{
|
||||
switch (unary.Type)
|
||||
{
|
||||
case UnaryExpressionType.Not:
|
||||
Result.Append("!");
|
||||
break;
|
||||
|
||||
case UnaryExpressionType.Negate:
|
||||
Result.Append("-");
|
||||
break;
|
||||
|
||||
case UnaryExpressionType.BitwiseNot:
|
||||
Result.Append("~");
|
||||
break;
|
||||
}
|
||||
|
||||
EncapsulateNoValue(unary.Expression);
|
||||
}
|
||||
|
||||
public override void Visit(ValueExpression value)
|
||||
{
|
||||
switch (value.Type)
|
||||
{
|
||||
case ValueType.Boolean:
|
||||
Result.Append(value.Value).Append(" ");
|
||||
break;
|
||||
|
||||
case ValueType.DateTime:
|
||||
Result.Append("#").Append(value.Value).Append("#").Append(" ");
|
||||
break;
|
||||
|
||||
case ValueType.Float:
|
||||
Result.Append(decimal.Parse(value.Value.ToString()).ToString(_numberFormatInfo)).Append(" ");
|
||||
break;
|
||||
|
||||
case ValueType.Integer:
|
||||
Result.Append(value.Value).Append(" ");
|
||||
break;
|
||||
|
||||
case ValueType.String:
|
||||
Result.Append("'").Append(value.Value).Append("'").Append(" ");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Visit(FunctionExpression function)
|
||||
{
|
||||
Result.Append(function.Identifier.Name);
|
||||
|
||||
Result.Append("(");
|
||||
|
||||
for (var i = 0; i < function.Expressions.Length; i++)
|
||||
{
|
||||
function.Expressions[i].Accept(this);
|
||||
|
||||
if (i < function.Expressions.Length - 1)
|
||||
{
|
||||
Result.Remove(Result.Length - 1, 1);
|
||||
Result.Append(", ");
|
||||
}
|
||||
}
|
||||
|
||||
// Trim spaces before adding a closing parenthesis
|
||||
while (Result[Result.Length - 1] == ' ')
|
||||
{
|
||||
Result.Remove(Result.Length - 1, 1);
|
||||
}
|
||||
|
||||
Result.Append(") ");
|
||||
}
|
||||
|
||||
public override void Visit(IdentifierExpression identifier)
|
||||
{
|
||||
Result.Append("[").Append(identifier.Name).Append("] ");
|
||||
}
|
||||
|
||||
protected void EncapsulateNoValue(LogicalExpression expression)
|
||||
{
|
||||
if (expression is ValueExpression)
|
||||
{
|
||||
expression.Accept(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
Result.Append("(");
|
||||
expression.Accept(this);
|
||||
|
||||
// Trim spaces before adding a closing parenthesis
|
||||
while (Result[Result.Length - 1] == ' ')
|
||||
{
|
||||
Result.Remove(Result.Length - 1, 1);
|
||||
}
|
||||
|
||||
Result.Append(") ");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 207ce2879c26b4ef0a891282aa1dfb27
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,23 @@
|
||||
namespace Unity.VisualScripting.Dependencies.NCalc
|
||||
{
|
||||
public class TernaryExpression : LogicalExpression
|
||||
{
|
||||
public TernaryExpression(LogicalExpression leftExpression, LogicalExpression middleExpression, LogicalExpression rightExpression)
|
||||
{
|
||||
LeftExpression = leftExpression;
|
||||
MiddleExpression = middleExpression;
|
||||
RightExpression = rightExpression;
|
||||
}
|
||||
|
||||
public LogicalExpression LeftExpression { get; set; }
|
||||
|
||||
public LogicalExpression MiddleExpression { get; set; }
|
||||
|
||||
public LogicalExpression RightExpression { get; set; }
|
||||
|
||||
public override void Accept(LogicalExpressionVisitor visitor)
|
||||
{
|
||||
visitor.Visit(this);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1e339c45a25164bda8fb4ef97ff8d67e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,27 @@
|
||||
namespace Unity.VisualScripting.Dependencies.NCalc
|
||||
{
|
||||
public class UnaryExpression : LogicalExpression
|
||||
{
|
||||
public UnaryExpression(UnaryExpressionType type, LogicalExpression expression)
|
||||
{
|
||||
Type = type;
|
||||
Expression = expression;
|
||||
}
|
||||
|
||||
public LogicalExpression Expression { get; set; }
|
||||
|
||||
public UnaryExpressionType Type { get; set; }
|
||||
|
||||
public override void Accept(LogicalExpressionVisitor visitor)
|
||||
{
|
||||
visitor.Visit(this);
|
||||
}
|
||||
}
|
||||
|
||||
public enum UnaryExpressionType
|
||||
{
|
||||
Not,
|
||||
Negate,
|
||||
BitwiseNot
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c614751e0f58c477cb0e9658be0ebdc4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Binary file not shown.
@@ -0,0 +1,33 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f9e773f6742c84fa28f8820bd00cce30
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
Windows Store Apps: WindowsStoreApps
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,100 @@
|
||||
using System;
|
||||
|
||||
namespace Unity.VisualScripting.Dependencies.NCalc
|
||||
{
|
||||
public class ValueExpression : LogicalExpression
|
||||
{
|
||||
public ValueExpression(object value, ValueType type)
|
||||
{
|
||||
Value = value;
|
||||
Type = type;
|
||||
}
|
||||
|
||||
public ValueExpression(object value)
|
||||
{
|
||||
switch (System.Type.GetTypeCode(value.GetType()))
|
||||
{
|
||||
case TypeCode.Boolean:
|
||||
Type = ValueType.Boolean;
|
||||
break;
|
||||
|
||||
case TypeCode.DateTime:
|
||||
Type = ValueType.DateTime;
|
||||
break;
|
||||
|
||||
case TypeCode.Decimal:
|
||||
case TypeCode.Double:
|
||||
case TypeCode.Single:
|
||||
Type = ValueType.Float;
|
||||
break;
|
||||
|
||||
case TypeCode.Byte:
|
||||
case TypeCode.SByte:
|
||||
case TypeCode.Int16:
|
||||
case TypeCode.Int32:
|
||||
case TypeCode.Int64:
|
||||
case TypeCode.UInt16:
|
||||
case TypeCode.UInt32:
|
||||
case TypeCode.UInt64:
|
||||
Type = ValueType.Integer;
|
||||
break;
|
||||
|
||||
case TypeCode.String:
|
||||
Type = ValueType.String;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new EvaluationException("This value could not be handled: " + value);
|
||||
}
|
||||
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public ValueExpression(string value)
|
||||
{
|
||||
Value = value;
|
||||
Type = ValueType.String;
|
||||
}
|
||||
|
||||
public ValueExpression(int value)
|
||||
{
|
||||
Value = value;
|
||||
Type = ValueType.Integer;
|
||||
}
|
||||
|
||||
public ValueExpression(float value)
|
||||
{
|
||||
Value = value;
|
||||
Type = ValueType.Float;
|
||||
}
|
||||
|
||||
public ValueExpression(DateTime value)
|
||||
{
|
||||
Value = value;
|
||||
Type = ValueType.DateTime;
|
||||
}
|
||||
|
||||
public ValueExpression(bool value)
|
||||
{
|
||||
Value = value;
|
||||
Type = ValueType.Boolean;
|
||||
}
|
||||
|
||||
public object Value { get; set; }
|
||||
public ValueType Type { get; set; }
|
||||
|
||||
public override void Accept(LogicalExpressionVisitor visitor)
|
||||
{
|
||||
visitor.Visit(this);
|
||||
}
|
||||
}
|
||||
|
||||
public enum ValueType
|
||||
{
|
||||
Integer,
|
||||
String,
|
||||
DateTime,
|
||||
Float,
|
||||
Boolean
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b7338a5f262ac4ecea97462e8eb78178
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user