From 88a82046b8e8be21fd3b4e149aec18a5e48384b2 Mon Sep 17 00:00:00 2001 From: fengjiayi <12821976+ning_xi@user.noreply.gitee.com> Date: Wed, 16 Jul 2025 16:16:19 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BA=86=E8=84=9A=E6=9C=AC?= =?UTF-8?q?=E8=AF=AD=E8=A8=80=E4=B8=AD=E6=9E=84=E9=80=A0=E5=99=A8=E8=B5=8B?= =?UTF-8?q?=E5=80=BC=E7=9A=84=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Library/Utils/DynamicObjectHelper.cs | 135 ++ NodeFlow/Model/Node/SingleScriptNode.cs | 58 +- Serein.Script/Node/ClassTypeDefinitionNode.cs | 51 +- Serein.Script/Node/CtorAssignmentNode.cs | 46 + Serein.Script/Node/ObjectInstantiationNode.cs | 20 +- Serein.Script/Node/TypeNode.cs | 22 + Serein.Script/SereinScript.cs | 131 ++ Serein.Script/SereinScriptInterpreter.cs | 190 +-- Serein.Script/SereinScriptLexer.cs | 5 + Serein.Script/SereinScriptParser.cs | 1359 +++-------------- Serein.Script/SereinScriptTypeAnalysis.cs | 143 +- Workbench/App.xaml.cs | 18 + Workbench/Node/View/ScriptNodeControl.xaml | 13 +- Workbench/Node/View/ScriptNodeControl.xaml.cs | 6 + Workbench/Serein.WorkBench.csproj | 1 + Workbench/Views/MainView.xaml.cs | 3 + 16 files changed, 825 insertions(+), 1376 deletions(-) create mode 100644 Serein.Script/Node/CtorAssignmentNode.cs create mode 100644 Serein.Script/Node/TypeNode.cs create mode 100644 Serein.Script/SereinScript.cs diff --git a/Library/Utils/DynamicObjectHelper.cs b/Library/Utils/DynamicObjectHelper.cs index 95a7c42..7d8d8ee 100644 --- a/Library/Utils/DynamicObjectHelper.cs +++ b/Library/Utils/DynamicObjectHelper.cs @@ -5,6 +5,7 @@ using System.Reflection.Emit; using System.Reflection; using System.Text; using System.Threading.Tasks; +using System.ComponentModel; namespace Serein.Library.Utils { @@ -188,8 +189,142 @@ namespace Serein.Library.Utils return dynamicType; } + /// + /// 创建继承通知接口、具有属性的类型 + /// + /// + /// + /// + /// + /// + public static Type CreateTypeWithINotifyPropertyChanged(IDictionary properties, string typeName, bool isOverlay = false) + { + if (typeCache.ContainsKey(typeName) && !isOverlay) + return typeCache[typeName]; + var typeBuilder = ModuleBuilder.DefineType(typeName, TypeAttributes.Public | TypeAttributes.Class); + typeBuilder.AddInterfaceImplementation(typeof(INotifyPropertyChanged)); + // 添加 PropertyChanged 字段 + var eventHandlerType = typeof(PropertyChangedEventHandler); + var propertyChangedField = typeBuilder.DefineField("PropertyChanged", eventHandlerType, FieldAttributes.Private); + + // 添加 PropertyChanged 事件 + var eventBuilder = typeBuilder.DefineEvent("PropertyChanged", EventAttributes.None, eventHandlerType); + + // add_PropertyChanged + var addMethod = typeBuilder.DefineMethod("add_PropertyChanged", MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.Virtual | MethodAttributes.HideBySig, null, new[] { eventHandlerType }); + { + + var il = addMethod.GetILGenerator(); + var combine = typeof(Delegate).GetMethod("Combine", new[] { typeof(Delegate), typeof(Delegate) }); + + // this.PropertyChanged = (PropertyChangedEventHandler)Delegate.Combine(this.PropertyChanged, value); + il.Emit(OpCodes.Ldarg_0); // 加载 this(当前实例)到栈 + il.Emit(OpCodes.Ldarg_0); // 再次加载 this,用于访问字段 + il.Emit(OpCodes.Ldfld, propertyChangedField); // 加载 this.PropertyChanged 字段值 + il.Emit(OpCodes.Ldarg_1); // 加载方法参数 value(订阅者委托) + il.Emit(OpCodes.Call, combine); // 调用 Delegate.Combine(a, b) + il.Emit(OpCodes.Castclass, eventHandlerType); // 强转回 PropertyChangedEventHandler 类型 + il.Emit(OpCodes.Stfld, propertyChangedField); // 赋值给 this.PropertyChanged + il.Emit(OpCodes.Ret); // return + } + + // remove_PropertyChanged + var removeMethod = typeBuilder.DefineMethod("remove_PropertyChanged", MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.Virtual | MethodAttributes.HideBySig, null, new[] { eventHandlerType }); + { + var il = removeMethod.GetILGenerator(); + var remove = typeof(Delegate).GetMethod("Remove", new[] { typeof(Delegate), typeof(Delegate) }); + + // this.PropertyChanged = (PropertyChangedEventHandler)Delegate.Remove(this.PropertyChanged, value); + il.Emit(OpCodes.Ldarg_0); // 加载 this + il.Emit(OpCodes.Ldarg_0); // 再次加载 this + il.Emit(OpCodes.Ldfld, propertyChangedField); // 加载字段 this.PropertyChanged + il.Emit(OpCodes.Ldarg_1); // 加载 value(要移除的委托) + il.Emit(OpCodes.Call, remove); // 调用 Delegate.Remove(a, b) + il.Emit(OpCodes.Castclass, eventHandlerType); // 转换为 PropertyChangedEventHandler + il.Emit(OpCodes.Stfld, propertyChangedField); // 设置 this.PropertyChanged = 结果 + il.Emit(OpCodes.Ret); // return + } + + eventBuilder.SetAddOnMethod(addMethod); + eventBuilder.SetRemoveOnMethod(removeMethod); + + // 定义 OnPropertyChanged 方法 + var onPropertyChangedMethod = typeBuilder.DefineMethod( + "OnPropertyChanged", + MethodAttributes.Private, + null, + new[] { typeof(string) }); + + { + var il = onPropertyChangedMethod.GetILGenerator(); + var label = il.DefineLabel(); + + // if (PropertyChanged == null) return; + il.Emit(OpCodes.Ldarg_0); // 加载 this + il.Emit(OpCodes.Ldfld, propertyChangedField); // 加载 this.PropertyChanged + il.Emit(OpCodes.Brfalse_S, label); // 如果为空(null),跳转到 label,跳过通知调用 + + // PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName)); + il.Emit(OpCodes.Ldarg_0); // 加载 this(委托调用目标) + il.Emit(OpCodes.Ldfld, propertyChangedField); // 加载 PropertyChanged 委托 + il.Emit(OpCodes.Ldarg_0); // 加载 this 作为 sender 参数 + il.Emit(OpCodes.Ldarg_1); // 加载 propertyName 参数(string) + il.Emit(OpCodes.Newobj, typeof(PropertyChangedEventArgs).GetConstructor(new[] { typeof(string) })); // 构造 new PropertyChangedEventArgs(propertyName) + il.Emit(OpCodes.Callvirt, typeof(PropertyChangedEventHandler).GetMethod("Invoke")); // 调用委托 Invoke(sender, args) + il.MarkLabel(label); // 跳转目标(如果委托为 null 则跳转至此) + il.Emit(OpCodes.Ret); // return + } + + // 为每个属性生成字段 + get/set + OnPropertyChanged 调用 + foreach (var kv in properties) + { + string propName = kv.Key; + Type propType = kv.Value ?? typeof(object); + + var fieldBuilder = typeBuilder.DefineField("_" + propName, propType, FieldAttributes.Private); + + var propertyBuilder = typeBuilder.DefineProperty(propName, PropertyAttributes.HasDefault, propType, null); + + var getter = typeBuilder.DefineMethod("get_" + propName, + MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, + propType, Type.EmptyTypes); + + { + // get_PropertyName() + var il = getter.GetILGenerator(); + il.Emit(OpCodes.Ldarg_0); // 加载 this + il.Emit(OpCodes.Ldfld, fieldBuilder); // 读取私有字段 _PropertyName + il.Emit(OpCodes.Ret); // 返回字段值 + } + + var setter = typeBuilder.DefineMethod("set_" + propName, + MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, + null, new[] { propType }); + + { + // set_PropertyName(value) + var il = setter.GetILGenerator(); + il.Emit(OpCodes.Ldarg_0); // 加载 this + il.Emit(OpCodes.Ldarg_1); // 加载 value 参数 + il.Emit(OpCodes.Stfld, fieldBuilder); // 设置字段 _PropertyName = value + + il.Emit(OpCodes.Ldarg_0); // 加载 this + il.Emit(OpCodes.Ldstr, propName); // 加载属性名字符串作为通知参数 + il.Emit(OpCodes.Call, onPropertyChangedMethod); // 调用 OnPropertyChanged(propName) + + il.Emit(OpCodes.Ret); // return + } + + propertyBuilder.SetGetMethod(getter); + propertyBuilder.SetSetMethod(setter); + } + + var dynamicType = typeBuilder.CreateType(); + typeCache[typeName] = dynamicType; + return dynamicType; + } #region 动态创建对象并赋值 // 方法 1: 创建动态类型及其对象实例 diff --git a/NodeFlow/Model/Node/SingleScriptNode.cs b/NodeFlow/Model/Node/SingleScriptNode.cs index 0336c3b..66bec73 100644 --- a/NodeFlow/Model/Node/SingleScriptNode.cs +++ b/NodeFlow/Model/Node/SingleScriptNode.cs @@ -33,19 +33,20 @@ namespace Serein.NodeFlow.Model /// public override bool IsBase => true; - private IScriptFlowApi ScriptFlowApi; - private ProgramNode programNode; - private readonly SereinScriptInterpreter scriptInterpreter; private bool IsScriptChanged = false; + /// + /// 脚本解释器 + /// + private readonly SereinScript sereinScript; + /// /// 构建流程脚本节点 /// /// - public SingleScriptNode(IFlowEnvironment environment):base(environment) + public SingleScriptNode(IFlowEnvironment environment) : base(environment) { - ScriptFlowApi = new ScriptFlowApi(environment, this); - scriptInterpreter = new SereinScriptInterpreter(); + sereinScript = new SereinScript(); } static SingleScriptNode() @@ -60,7 +61,7 @@ namespace Serein.NodeFlow.Model // 加载基础方法 foreach ((string name, MethodInfo method) item in tempMethods) { - SereinScriptInterpreter.AddStaticFunction(item.name, item.method); + SereinScript.AddStaticFunction(item.name, item.method); } } @@ -157,24 +158,10 @@ namespace Serein.NodeFlow.Model varNames.Add(pd.Name); } - /*var sb = new StringBuilder(); - foreach (var pd in MethodDetails.ParameterDetailss) - { - sb.AppendLine($"let {pd.Name};"); // 提前声明这些变量 - } - sb.Append(Script); - var script = sb.ToString();*/ - var parser = new SereinScriptParser(); // 准备解析器 - var typeAnalysis = new SereinScriptTypeAnalysis(); // 准备分析器 - programNode = parser.Parse(Script); // 开始解析获取程序主节点 + Dictionary dict = MethodDetails.ParameterDetailss.ToDictionary(pd => pd.Name, pd => pd.DataType); // 准备预定义类型 - var dict = MethodDetails.ParameterDetailss.ToDictionary(pd => pd.Name, pd => pd.DataType); - typeAnalysis.NodeSymbolInfos.Clear(); // 清空符号表 - typeAnalysis.LoadSymbol(dict); // 提前加载脚本节点定义的符号 - typeAnalysis.AnalysisProgramNode(programNode); // 分析节点类型 - var returnType = typeAnalysis.NodeSymbolInfos[programNode]; // 获取返回类型 + var returnType = sereinScript.ParserScript(dict, Script); // 开始解析获取程序主节点 MethodDetails.ReturnType = returnType; - //scriptInterpreter.SetTypeAnalysis(typeAnalysis); // 设置类型分析器 } catch (Exception ex) @@ -244,8 +231,7 @@ namespace Serein.NodeFlow.Model if (token.IsCancellationRequested) return null; - - var result = await scriptInterpreter.InterpretAsync(scriptContext, programNode); // 从入口节点执行 + var result = await sereinScript.InterpreterAsync(scriptContext); // 从入口节点执行 envEvent.FlowRunComplete -= onFlowStop; return new FlowResult(this.Guid, context, result); } @@ -259,12 +245,7 @@ namespace Serein.NodeFlow.Model private static class ScriptBaseFunc { - public static DateTime GetNow() => DateTime.Now; - - public static int Add(int Left, int Right) - { - return Left + Right; - } + public static DateTime now() => DateTime.Now; #region 常用的类型转换 public static bool @bool(object value) @@ -321,6 +302,21 @@ namespace Serein.NodeFlow.Model } } + public static void regType(Type type, string name = "") + { + SereinScript.AddClassType(type, name); + } + + public static string str(object obj) + { + return obj?.ToString() ?? string.Empty; + } + + public static object obj(Type type) + { + return Activator.CreateInstance(type); + } + public static Type type(object type) { return type.GetType(); diff --git a/Serein.Script/Node/ClassTypeDefinitionNode.cs b/Serein.Script/Node/ClassTypeDefinitionNode.cs index 543ec07..ab2e39c 100644 --- a/Serein.Script/Node/ClassTypeDefinitionNode.cs +++ b/Serein.Script/Node/ClassTypeDefinitionNode.cs @@ -15,41 +15,40 @@ namespace Serein.Script.Node public bool IsOverlay { get; set; } /// - /// 类名称 + /// 类型名称 /// - public string ClassName { get; } + public TypeNode ClassType { get; } /// - /// 字段名称及字段类型 + /// 类型中的属性 /// - [Obsolete("此属性已经过时,将会改为Dictionary", false)] - public Dictionary Fields { get; } - - /// - /// 字段名称及字段类型(Kvp[fididName:fidleTypeName]) - /// - public Dictionary FieldInfos { get; } + public Dictionary Propertys { get; } - public ClassTypeDefinitionNode(Dictionary fields, string className) + public ClassTypeDefinitionNode(Dictionary propertys, TypeNode className) { - this.FieldInfos = fields; - this.ClassName = className; + this.Propertys = propertys; + this.ClassType = className; } - [Obsolete("此构造方法已经过时,可能在下一个版本中移除", false)] - public ClassTypeDefinitionNode(Dictionary fields, string className) - { - this.Fields = fields; - this.ClassName = className; - } - [Obsolete("此构造方法已经过时,可能在下一个版本中移除", false)] - public ClassTypeDefinitionNode(Dictionary fields, string className, bool isOverlay) - { - this.Fields = fields; - this.ClassName = className; - IsOverlay = isOverlay; - } + + + /* /// + /// 字段名称及字段类型 + /// + [Obsolete("此属性已经过时,将会改为Dictionary", false)] + public Dictionary Fields { get; } + + */ + + + /* /// + /// 字段名称及字段类型(Kvp[fididName:fidleTypeName]) + /// + public Dictionary FieldInfos { get; } + */ + //[Obsolete("此构造方法已经过时,可能在下一个版本中移除", false)] + } } diff --git a/Serein.Script/Node/CtorAssignmentNode.cs b/Serein.Script/Node/CtorAssignmentNode.cs new file mode 100644 index 0000000..b8d8c52 --- /dev/null +++ b/Serein.Script/Node/CtorAssignmentNode.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Serein.Script.Node +{ + + + /// + /// 构造器对对象成员赋值 + /// + public class CtorAssignmentNode : ASTNode + { + /// + /// 成员来源类型 + /// + public TypeNode Class { get; } + + /// + /// 成员名称 + /// + public string MemberName { get; } + + /// + /// 值来源 + /// + public ASTNode Value { get; } + + /// + /// 构造器赋值 + /// + /// 成员来源类型 + /// 成员名称 + /// 成员值来源 + public CtorAssignmentNode(TypeNode typeNode, string memberName, ASTNode value) + { + Class = typeNode; + MemberName = memberName; + Value = value; + } + + + } +} diff --git a/Serein.Script/Node/ObjectInstantiationNode.cs b/Serein.Script/Node/ObjectInstantiationNode.cs index bd5e301..1ee4dd0 100644 --- a/Serein.Script/Node/ObjectInstantiationNode.cs +++ b/Serein.Script/Node/ObjectInstantiationNode.cs @@ -12,19 +12,31 @@ namespace Serein.Script.Node public class ObjectInstantiationNode : ASTNode { /// - /// 类型名称 + /// 类型来源 /// - public string TypeName { get; } + public TypeNode Type { get; } /// /// 构造方法的参数来源 /// public List Arguments { get; } - public ObjectInstantiationNode(string typeName, List arguments) + + /// + /// 构造器赋值 + /// + public List CtorAssignments { get; private set; } = []; + + public ObjectInstantiationNode(TypeNode type, List arguments) { - this.TypeName = typeName; + this.Type = type; this.Arguments = arguments; } + + public ObjectInstantiationNode SetCtorAssignments(List ctorAssignments) + { + CtorAssignments = ctorAssignments; + return this; + } } } diff --git a/Serein.Script/Node/TypeNode.cs b/Serein.Script/Node/TypeNode.cs new file mode 100644 index 0000000..bb12ed4 --- /dev/null +++ b/Serein.Script/Node/TypeNode.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Serein.Script.Node +{ + /// + /// 类型节点 + /// + public class TypeNode : ASTNode + { + public string TypeName { get; } + + public TypeNode(string typeName) + { + TypeName = typeName; + } + + } +} diff --git a/Serein.Script/SereinScript.cs b/Serein.Script/SereinScript.cs new file mode 100644 index 0000000..352c9c4 --- /dev/null +++ b/Serein.Script/SereinScript.cs @@ -0,0 +1,131 @@ +using Serein.Library; +using Serein.Script.Node; +using Serein.Script.Node.FlowControl; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace Serein.Script +{ + public class SereinScript + { + /// + /// 类型分析 + /// + public SereinScriptTypeAnalysis TypeAnalysis { get; set; } = new SereinScriptTypeAnalysis(); + + + + private ProgramNode? programNode; + + public Type ParserScript(Dictionary argTypes, string script) + { + SereinScriptParser parser = new SereinScriptParser(); + var programNode = parser.Parse(script); + TypeAnalysis.NodeSymbolInfos.Clear(); // 清空符号表 + TypeAnalysis.LoadSymbol(argTypes); // 提前加载脚本节点定义的符号 + TypeAnalysis.Analysis(programNode); // 分析节点类型 + var returnType = TypeAnalysis.NodeSymbolInfos[programNode]; // 获取返回类型 + this.programNode = programNode; + return returnType; // 脚本返回类型 + } + + public async Task InterpreterAsync(IScriptInvokeContext context) + { + if(programNode is null) + { + throw new ArgumentNullException(nameof(programNode)); + } + Dictionary symbolInfos = TypeAnalysis.NodeSymbolInfos.ToDictionary(); + SereinScriptInterpreter Interpreter = new SereinScriptInterpreter(symbolInfos); + return await Interpreter.InterpretAsync(context, programNode); + } + + + + + + + + /// + /// 挂载的函数 + /// + public static Dictionary FunctionDelegates { get; private set; } = []; + + /// + /// 挂载方法的信息 + /// + public static Dictionary FunctionInfos { get; private set; } = []; + + /// + /// 挂载的类型 + /// + public static Dictionary MountType = new Dictionary(); + + /// + /// 挂载的函数调用的对象(用于解决函数需要实例才能调用的场景) + /// + public static Dictionary> DelegateInstances = new Dictionary>(); + + /// + /// 挂载静态函数 + /// + /// + /// + public static void AddStaticFunction(string functionName, MethodInfo methodInfo) + { + FunctionDelegates[functionName] = new DelegateDetails(methodInfo); + FunctionInfos[functionName] = methodInfo; + } + + + /// + /// 挂载函数 + /// + /// 函数名称 + /// 方法信息 + public static void AddFunction(string functionName, MethodInfo methodInfo, Func? callObj = null) + { + if (!methodInfo.IsStatic && callObj is null) + { + SereinEnv.WriteLine(InfoType.WARN, "函数挂载失败:试图挂载非静态的函数,但没有传入相应的获取实例的方法。"); + return; + } + + if (!methodInfo.IsStatic && callObj is not null && !DelegateInstances.ContainsKey(functionName)) + { + // 非静态函数需要给定类型 + DelegateInstances.Add(functionName, callObj); + } + if (!FunctionDelegates.ContainsKey(functionName)) + { + FunctionDelegates[functionName] = new DelegateDetails(methodInfo); + } + } + + /// + /// 挂载类型 + /// + /// 函数名称 + /// 指定类型名称 + public static void AddClassType(Type type, string typeName = "") + { + if (string.IsNullOrEmpty(typeName)) + { + typeName = type.Name; + } + if (!MountType.ContainsKey(typeName)) + { + MountType[typeName] = type; + } + } + + + + + + } +} diff --git a/Serein.Script/SereinScriptInterpreter.cs b/Serein.Script/SereinScriptInterpreter.cs index 347ef53..03ab98c 100644 --- a/Serein.Script/SereinScriptInterpreter.cs +++ b/Serein.Script/SereinScriptInterpreter.cs @@ -18,98 +18,15 @@ namespace Serein.Script /// public class SereinScriptInterpreter { - - /// - /// 挂载的函数 - /// - private static Dictionary _functionTable = new Dictionary(); - private static Dictionary _functionInfoTable = new Dictionary(); + private readonly Dictionary symbolInfos; - public static Dictionary FunctionInfoTable { get { return _functionInfoTable; } } - - /// - /// 挂载的函数调用的对象(用于函数需要实例才能调用的场景) - /// - private Dictionary> _callFuncOfGetObjects = new Dictionary>(); - - /// - /// 定义的类型 - /// - private Dictionary _classDefinition = new Dictionary(); - - - /// - /// 类型分析器 - /// - private SereinScriptTypeAnalysis typeAnalysis; - - /// - /// 挂载静态函数 - /// - /// - /// - public static void AddStaticFunction(string functionName, MethodInfo methodInfo) + public SereinScriptInterpreter(Dictionary symbolInfos) { - _functionTable[functionName] = new DelegateDetails(methodInfo); - _functionInfoTable[functionName] = methodInfo; + this.symbolInfos = symbolInfos; } + - /// - /// 挂载函数 - /// - /// 函数名称 - /// 方法信息 - public void AddFunction(string functionName, MethodInfo methodInfo, Func? callObj = null) - { - //if (!_functionTable.ContainsKey(functionName)) - //{ - // _functionTable[functionName] = new DelegateDetails(methodInfo); - //} - if(!methodInfo.IsStatic && callObj is null) - { - SereinEnv.WriteLine(InfoType.WARN, "函数挂载失败:试图挂载非静态的函数,但没有传入相应的获取实例的方法。"); - return; - } - - - if(!methodInfo.IsStatic && callObj is not null && !_callFuncOfGetObjects.ContainsKey(functionName)) - { - // 静态函数不需要 - _callFuncOfGetObjects.Add(functionName, callObj); - } - if (!_functionTable.ContainsKey(functionName)) - { - _functionTable[functionName] = new DelegateDetails(methodInfo); - } - //_functionTable[functionName] = new DelegateDetails(methodInfo); - } - - /// - /// 挂载类型 - /// - /// 函数名称 - /// 方法信息 - public void AddClassType(Type type , string typeName = "") - { - if (string.IsNullOrEmpty(typeName)) - { - typeName = type.Name; - } - if (!_classDefinition.ContainsKey(typeName)) - { - _classDefinition[typeName] = type; - } - } - - /// - /// 设置类型分析器 - /// - /// - public void SetTypeAnalysis(SereinScriptTypeAnalysis typeAnalysis) - { - this.typeAnalysis = typeAnalysis; - } /// /// 入口节点 @@ -159,17 +76,19 @@ namespace Serein.Script /// private void ExecutionClassTypeDefinitionNode(ClassTypeDefinitionNode classTypeDefinitionNode) { - if (_classDefinition.ContainsKey(classTypeDefinitionNode.ClassName) && !classTypeDefinitionNode.IsOverlay) + var className = classTypeDefinitionNode.ClassType.TypeName; + if (SereinScript.MountType.ContainsKey(className) && !classTypeDefinitionNode.IsOverlay) { //SereinEnv.WriteLine(InfoType.WARN, $"异常信息 : 类型重复定义,代码在第{classTypeDefinitionNode.Row}行: {classTypeDefinitionNode.Code.Trim()}"); return; } - - //var isOverlay = true; // classTypeDefinitionNode.IsOverlay; - - var type = DynamicObjectHelper.CreateTypeWithProperties(classTypeDefinitionNode.Fields, classTypeDefinitionNode.ClassName); // 覆盖 - //classTypeDefinitionNode.IsOverlay = false; // 已经加载过,则不再覆盖 - _classDefinition[classTypeDefinitionNode.ClassName] = type; // 定义对象 + if(DynamicObjectHelper.GetCacheType(className) == null) + { + var propertyTypes = classTypeDefinitionNode.Propertys.ToDictionary(p => p.Key, p => symbolInfos[p.Value]); + var type = DynamicObjectHelper.CreateTypeWithProperties(propertyTypes, className); // 覆盖 + SereinScript.MountType[className] = type; // 定义对象 + } + } /// @@ -305,11 +224,11 @@ namespace Serein.Script // 查找并执行对应的函数 - if (_functionTable.TryGetValue(funcName, out DelegateDetails? function)) + if (SereinScript.FunctionDelegates .TryGetValue(funcName, out DelegateDetails? function)) { if (!function.EmitMethodInfo.IsStatic) { - if(_callFuncOfGetObjects.TryGetValue(funcName, out var action)) + if(SereinScript.DelegateInstances.TryGetValue(funcName, out var action)) { instance = action.Invoke();// 非静态的方法需要获取相应的实例 @@ -429,27 +348,34 @@ namespace Serein.Script //if (right == null) throw new SereinSciptException(binOpNode.Right, "右值尝试使用计算 null"); return EvaluateBinaryOperation(left, binOpNode.Operator, right); case ObjectInstantiationNode objectInstantiationNode: // 对象实例化 - if (_classDefinition.TryGetValue(objectInstantiationNode.TypeName,out var type )) + if (!SereinScript.MountType.TryGetValue(objectInstantiationNode.Type.TypeName, out var type)) { - object?[] args = new object[objectInstantiationNode.Arguments.Count]; - for (int i = 0; i < objectInstantiationNode.Arguments.Count; i++) + type = symbolInfos[objectInstantiationNode.Type]; + if (type is null) { - var argNode = objectInstantiationNode.Arguments[i]; - args[i] = await EvaluateAsync(context, argNode); + throw new SereinSciptException(objectInstantiationNode, $"使用了未定义的类型\"{objectInstantiationNode.Type.TypeName}\""); } - var obj = Activator.CreateInstance(type,args: args);// 创建对象 - if (obj == null) - { - throw new SereinSciptException(objectInstantiationNode, $"类型创建失败\"{objectInstantiationNode.TypeName}\""); - } - return obj; } - else + object?[] args = new object[objectInstantiationNode.Arguments.Count]; + for (int i = 0; i < objectInstantiationNode.Arguments.Count; i++) { - - throw new SereinSciptException(objectInstantiationNode, $"使用了未定义的类型\"{objectInstantiationNode.TypeName}\""); + var argNode = objectInstantiationNode.Arguments[i]; + args[i] = await EvaluateAsync(context, argNode); + } + var obj = Activator.CreateInstance(type, args: args);// 创建对象 + if (obj == null) + { + throw new SereinSciptException(objectInstantiationNode, $"类型创建失败\"{objectInstantiationNode.Type.TypeName}\""); + } + for (int i = 0; i < objectInstantiationNode.CtorAssignments.Count; i++) + { + var ctorAssignmentNode = objectInstantiationNode.CtorAssignments[i]; + var propertyName = ctorAssignmentNode.MemberName; + var value = await EvaluateAsync(context, ctorAssignmentNode.Value); + SetPropertyValue(obj, propertyName, value); + } - } + return obj; case FunctionCallNode callNode: // 调用方法 return await InterpretFunctionCallAsync(context, callNode); // 调用方法返回函数的返回值 case MemberFunctionCallNode memberFunctionCallNode: // 对象方法调用 @@ -570,6 +496,48 @@ namespace Serein.Script } } + public void SetPropertyValue(object target, string memberName, object? value) + { + var targetType = target?.GetType(); + if (targetType is null) return; + var propertyInfo = targetType.GetProperty(memberName); + if (propertyInfo is null) + { + var fieldInfo = target?.GetType().GetRuntimeField(memberName); + if (fieldInfo is null) + { + throw new Exception($"类型 {targetType} 对象没有成员\"{memberName}\""); + } + else + { + var convertedValue = Convert.ChangeType(value, fieldInfo.FieldType); + fieldInfo.SetValue(target, convertedValue); + } + } + else + { + if (value is null) + { + propertyInfo.SetValue(target, null); + return; + } + var valueTtpe = value.GetType(); + if (propertyInfo.PropertyType.IsAssignableFrom(valueTtpe)) + { + propertyInfo.SetValue(target, value); + } + else if (propertyInfo.PropertyType.FullName == valueTtpe.FullName) + { + propertyInfo.SetValue(target, value); + } + else + { + throw new Exception($"类型 {targetType} 对象成员\"{memberName}\" 赋值时异常"); + } + //var convertedValue = Convert.ChangeType(value, ); + } + } + /// /// 获取对象成员 /// diff --git a/Serein.Script/SereinScriptLexer.cs b/Serein.Script/SereinScriptLexer.cs index 153bb04..9a5a2a7 100644 --- a/Serein.Script/SereinScriptLexer.cs +++ b/Serein.Script/SereinScriptLexer.cs @@ -126,6 +126,11 @@ namespace Serein.Script Type = type; Value = value; } + + public override string ToString() + { + return $"token in {Row} row, type is \"{Type}\", value is \"{Value}\"."; + } } diff --git a/Serein.Script/SereinScriptParser.cs b/Serein.Script/SereinScriptParser.cs index 1a98a4b..2250bbc 100644 --- a/Serein.Script/SereinScriptParser.cs +++ b/Serein.Script/SereinScriptParser.cs @@ -1,4 +1,5 @@ -using Newtonsoft.Json.Linq; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Newtonsoft.Json.Linq; using Serein.Library; using Serein.Library.Utils; using Serein.Script.Node; @@ -50,9 +51,7 @@ namespace Serein.Script Statements.Clear(); while (_currentToken.Type != TokenType.EOF) { - - //var astNode = Statement(); // 解析单个语句 - var astNode = Statement2(); // 解析单个语句 + var astNode = Statement(); // 解析单个语句 if (astNode == null) { continue; @@ -74,10 +73,14 @@ namespace Serein.Script }*/ } - private ASTNode Statement2() + private ASTNode Statement() { + if (_currentToken.Type == TokenType.Semicolon) + { + NextToken(); // 消耗 ";" + return null; + } - //_currentToken = _lexer.NextToken(); // 获取新的Token if (_currentToken.Type == TokenType.Identifier) { /* 赋值语句与一般语句的表达形式 @@ -117,7 +120,10 @@ namespace Serein.Script isAssignment = true; break; } - //if (peekToken.StartIndex >= _lexer.CodeLength) throw new Exception(); + if(peekCount > 19999) + { + throw new Exception("解析异常,peek次数过多,请减少脚本代码"); + } } #endregion #region 生成 ASTNode @@ -155,15 +161,17 @@ namespace Serein.Script 1. if()...else... 2. while(){...} */ - return null; + if (JudgmentKeyword("if")) + { + return ParseIf(); + } + else if (JudgmentKeyword("while")) + { + return ParseWhile(); + } } - if(_currentToken.Type == TokenType.Semicolon) - { - NextToken(); // 消耗 ";" - return null; - } - throw new Exception("解析异常"); + throw new Exception($"解析异常。{_currentToken.ToString()}"); /*else { // 为避免解析异常,除了 Statement() 方法以外,其它地方不需要对 TokenType.Semicolon 进行处理 @@ -209,12 +217,16 @@ namespace Serein.Script //var tempPeekToken = _lexer.PeekToken(); var backupToken = _currentToken; var targetNode = new IdentifierNode(_currentToken.Value).SetTokenInfo(_currentToken); // 生成 Tagget 标记节点 - NextToken(); // 消耗当前标识符的定义 + List nodes = [targetNode]; - ASTNode? source = null; - if (!JudgmentOperator(_currentToken, "=")) + ASTNode? source; + var peekToken2 = _lexer.PeekToken(); // 消耗 第一个标识符 + if (JudgmentOperator(peekToken2, "=")) { - var peekToken2 = _lexer.PeekToken(); // 消耗 第一个标识符 + NextToken(); + } + else + { if (peekToken2.Type == TokenType.ParenthesisLeft) { // 解析调用挂载方法 @@ -237,7 +249,12 @@ namespace Serein.Script } targetNode = collectionIndexNode; } + else if (peekToken2.Type == TokenType.Dot) + { + NextToken(); + } + nodes = [targetNode]; // 开始解析 while (true) { @@ -301,7 +318,6 @@ namespace Serein.Script throw new Exception($"在 Expression().Factor() 遇到意外的 TokenType ,{_currentToken.Type} {_currentToken.Value} "); }*/ } - } targetNode = nodes[^1]; if (targetNode is FunctionCallNode or MemberFunctionCallNode) @@ -486,9 +502,9 @@ namespace Serein.Script var peekToken = _lexer.PeekToken(); if (peekToken.Type == TokenType.Dot) { + NextToken(); NextToken(TokenType.Identifier); fieldTypeName = $"{fieldTypeName}.{_currentToken.Value}"; // 向后扩充 - NextToken(); continue; } else if (peekToken.Type == TokenType.Identifier) @@ -520,8 +536,12 @@ namespace Serein.Script DynamicObjectHelper.CreateTypeWithProperties(classFields, className); } - var classTypeDefinitionNode = new ClassTypeDefinitionNode(classFields, className); - + + TypeNode classTypeNode = new TypeNode(className); + Dictionary propertyTypes = classFields.ToDictionary(f => f.Key, f => new TypeNode(f.Value.FullName)); + + var classTypeDefinitionNode = new ClassTypeDefinitionNode(propertyTypes, classTypeNode); + classTypeDefinitionNode.SetTokenInfo(classToken); return classTypeDefinitionNode; } @@ -533,7 +553,7 @@ namespace Serein.Script public ReturnNode ParseReturnNode() { var returnToken = _currentToken; - if (JudgmentKeyword("return")) throw new Exception($"解析返回节点时,当前Token不为关键字“return”。"); + if (!JudgmentKeyword("return")) throw new Exception($"解析返回节点时,当前Token不为关键字“return”。"); NextToken(); // 消耗关键字 ReturnNode returnNode; if (_currentToken.Type == TokenType.Semicolon) @@ -572,17 +592,18 @@ namespace Serein.Script var instantiationToken = _currentToken; // 第一次进入循环时,会消耗 new 关键字 NextToken(TokenType.Identifier); + var typeToken = _currentToken; string typeName = _currentToken.Value; // 类名 List ctorArguments = []; // 构造入参 + while (true) { - var peekToken = _lexer.PeekToken(); if (peekToken.Type == TokenType.Dot) { - + NextToken(); + NextToken(); typeName = $"{typeName}.{_currentToken.Value}"; // 向后扩充 - NextToken(); continue; } else if (peekToken.Type == TokenType.ParenthesisLeft) @@ -603,12 +624,146 @@ namespace Serein.Script break; } } - // NextToken(TokenType.Semicolon); // 消耗字段名称,如果下一个Token如果不为分号,说明词法异常 - ObjectInstantiationNode objectInstantiationNode = new ObjectInstantiationNode(typeName, ctorArguments); + TypeNode typeNode = new TypeNode(typeName); + typeNode.SetTokenInfo(typeToken); + ObjectInstantiationNode objectInstantiationNode = new ObjectInstantiationNode(typeNode, ctorArguments); + List ctorAssignmentNodes = new List(); // 构造器赋值 + + /* 类型构造器 + new Type { + Value1 = [Exp] , + Value2 = [Exp] , + } + */ + if (_currentToken.Type == TokenType.BraceLeft) + { + NextToken(); // 消耗 "{" + string propertyName = ""; + Token propertyToken = _currentToken; + while( _currentToken.Type != TokenType.BraceRight) + { + if (_currentToken.Type == TokenType.Identifier) + { + propertyToken = _currentToken; + propertyName = _currentToken.Value; + NextToken(); + continue; + } + else if (JudgmentOperator(_currentToken,"=")) + { + NextToken(); + ASTNode value = ParserExpression(); + CtorAssignmentNode ctorAssignmentNode = new CtorAssignmentNode(typeNode, propertyName, value); + ctorAssignmentNode.SetTokenInfo(propertyToken); + ctorAssignmentNodes.Add(ctorAssignmentNode); + if(_currentToken .Type == TokenType.Comma) + { + NextToken(); // 消耗 "," + continue; + } + else if (_currentToken.Type == TokenType.BraceRight) + { + break; + } + } + else + { + throw new Exception("类型构造器词法分析异常"); + } + } + NextToken(); // 消耗 "}" + objectInstantiationNode.SetCtorAssignments(ctorAssignmentNodes); + } + objectInstantiationNode.SetTokenInfo(instantiationToken); - return objectInstantiationNode; + return objectInstantiationNode; } + + #region 控制流语句解析 + + /// + /// 解析 if 语句。 + /// + /// + /// + private ASTNode ParseIf() + { + NextToken(TokenType.ParenthesisLeft); // 消耗 "if" + NextToken(); // 消耗 "(" + ASTNode condition = BooleanExpression(); + NextToken(TokenType.BraceLeft); // 消耗 ")" + NextToken(); // 消耗 "{" + // 解析大括号中的语句 + List trueBranch = new List(); + List falseBranch = new List(); + while (_currentToken.Type != TokenType.BraceRight) + { + var astNode = Statement(); // 解析 true 分支中的语句 + if (astNode != null) + { + trueBranch.Add(astNode); + } + } + // 确保匹配右大括号 } + if (_currentToken.Type != TokenType.BraceRight) + { + throw new Exception("非预期的标识符 '}' "); + } + NextToken(); // 消耗 "}" + if (_currentToken.Type == TokenType.Keyword && _currentToken.Value == "else") + { + NextToken(TokenType.BraceLeft); // 消耗 "else" + NextToken(); // 消耗 "{" + while (_currentToken.Type != TokenType.BraceRight) + { + var astNode = Statement(); // 解析 else 分支中的语句 + if (astNode != null) + { + falseBranch.Add(astNode); // 将 else 分支的语句添加到 falseBranch 中 + } + } + // 确保匹配右大括号 } + if (_currentToken.Type != TokenType.BraceRight) + { + throw new Exception("非预期的标识符 '}' "); + } + NextToken(); // 消耗 "}" + } + + return new IfNode(condition, trueBranch, falseBranch).SetTokenInfo(_currentToken); + } + + /// + /// 解析 while 循环语句。 + /// + /// + private ASTNode ParseWhile() + { + + NextToken(TokenType.ParenthesisLeft); // 消耗 "while" + NextToken(); // 消耗 "(" + ASTNode condition = BooleanExpression(); + NextToken(TokenType.BraceLeft); // 消耗 ")" + NextToken(); // 消耗 "{" + List body = new List(); + while (_currentToken.Type != TokenType.BraceRight) + { + var node = Statement(); + if (node is not null) + { + body.Add(node); // 解析循环体中的语句 + } + } + _currentToken = _lexer.NextToken(); // 消耗 "}" + return new WhileNode(condition, body).SetTokenInfo(_currentToken); + } + + + + + #endregion + #region 表达式解析:BooleanExpression -> ComparisonExpression -> Expression -> Term -> Factor /// /// 解析表达式 @@ -769,7 +924,7 @@ namespace Serein.Script // ... = variable()()(); // 暂时不支持柯里化调用... = variable()()(); var functionCallNode = ParseFunctionCallNode(); - if(_currentToken.Type == TokenType.Semicolon) + if(_currentToken.Type == TokenType.Semicolon || _currentToken.Type == TokenType.Operator) { return functionCallNode; } @@ -779,7 +934,7 @@ namespace Serein.Script { // 解析集合获取 var collectionIndexNode = ParseCollectionIndexNode(targetNode); - if (_currentToken.Type == TokenType.Semicolon) + if (_currentToken.Type == TokenType.Semicolon || _currentToken.Type == TokenType.Operator) { return collectionIndexNode; } @@ -807,12 +962,13 @@ namespace Serein.Script var peekToken3 = _lexer.PeekToken(); ASTNode tempNode = peekToken3.Type switch { + TokenType.Operator => ParseMemberAccessNode(source), // 获取对象中的成员 source.Value... TokenType.Dot => ParseMemberAccessNode(source), // 获取对象中的成员 source.Value... TokenType.Semicolon => ParseMemberAccessNode(source), // 获取对象中的成员 source.Value... TokenType.ParenthesisRight => ParseMemberAccessNode(source), // 获取对象中的成员 source.Value... TokenType.SquareBracketsLeft => ParseCollectionIndexNode(source), // 获取集合中的元素 source[index].... TokenType.ParenthesisLeft => ParseMemberFunctionCallNode(source), // 获取需要调用的方法 source(arg1,arg2...)... - _ => throw new Exception($"无法从对象获取成员,当前Token类型为 {peekToken.Type}。") + _ => throw new Exception($"无法从对象获取成员,当前Token : {peekToken.ToString()}。") }; nodes.Add(tempNode); continue; // 结束当前轮次的token判断 @@ -839,6 +995,7 @@ namespace Serein.Script { if(peekToken.Type == TokenType.ParenthesisRight // 可能解析完了方法参数 || peekToken.Type == TokenType.Comma // 可能解析完了方法参数 + || peekToken.Type == TokenType.Operator // 可能解析完了方法参数 || peekToken.Type == TokenType.ParenthesisRight) // 可能解析完了下标索引 { return source; @@ -854,7 +1011,6 @@ namespace Serein.Script else if (_currentToken.Type == TokenType.ParenthesisLeft) // 嵌套表达式 { NextToken(); // 消耗 "(" - _currentToken = _lexer.NextToken(); // 消耗 "(" var expNode = BooleanExpression(); if (_currentToken.Type != TokenType.ParenthesisRight) throw new Exception($"解析嵌套表达式时遇到非预期的符号 \"{_currentToken.Type}\",预期符号为\")\"。"); @@ -997,1143 +1153,6 @@ namespace Serein.Script #endregion - - - #region 废弃的解析方法 - /* - - - /// - /// 解析单个语句。 - /// - /// - /// - private ASTNode Statement() - { - - while (_currentToken.Type == TokenType.Semicolon) - { - _currentToken = _lexer.NextToken(); - } - if (_currentToken.Type == TokenType.EOF) - { - return null; - } - if (_currentToken.Type == TokenType.Identifier) - { - // 处理标识符,可能是函数调用、变量赋值或对象成员访问等行为 - return ParseIdentifier(); - } - - if (_currentToken.Type == TokenType.Keyword && _currentToken.Value == "let") - { - // 处理 let 变量赋值语句 - return ParseLetAssignment(); - } - if (_currentToken.Type == TokenType.Keyword && _currentToken.Value == "class") - { - - // 加载类定义 - return ParseClassDefinition(); // 加载类,如果已经加载过,则忽略 - } - if (_currentToken.Type == TokenType.Keyword && _currentToken.Value == "new") - { - var _peekToken = _lexer.PeekToken(); - if (_peekToken.Type == TokenType.Keyword && _peekToken.Value == "class") - { - // 重新加载类定义 - return ParseClassDefinition(); // 重新加载类 - } - } - - if (_currentToken.Type == TokenType.Keyword && _currentToken.Value == "if") - { - // 处理 if 语句 - return ParseIf(); - } - if (_currentToken.Type == TokenType.Keyword && _currentToken.Value == "while") - { - // 处理 while 循环语句 - return ParseWhile(); - } - if (_currentToken.Type == TokenType.Keyword && _currentToken.Value == "return") - { - // 处理 return 语句 - return ParseReturn(); - } - - if (_currentToken.Type == TokenType.Null) - { - // 处理 null 语句 - return BooleanExpression(); - } - - *//**//* - // 处理其他语句(如表达式语句等) - if (_currentToken.Type == TokenType.Semicolon) - { - return null; // 表示空语句 - } - - - throw new Exception("Unexpected statement: " + _currentToken.Value.ToString()); - } - - - /// - /// 从标识符解析方法调用、变量赋值、获取对象成员行为。 - /// (非符号、关键字) - /// - /// - private ASTNode ParseIdentifier() - { - *//* - localFunc(); - obj.Func(); - obj.Value = ...; - value = ...; - *//* - var backupToken = _currentToken; - var tokenCount = 1; - var int_type = 0; - int_type = GetFlowType(_lexer, ref tokenCount); - if (int_type == 1) // 赋值 MemberAssignmentNode - { - //_lexer.SetToken(backupToken); - var objectName = _currentToken.Value; - var objectNode = new IdentifierNode(objectName).SetTokenInfo(_currentToken); // 首先定义对象变量节点 - var peekToken = _lexer.PeekToken(); - if (peekToken.Type == TokenType.Operator && peekToken.Value == "=") - { - // 变量赋值 - _currentToken = _lexer.NextToken(); // 消耗 变量名 - _currentToken = _lexer.NextToken(); // 消耗 “=” - - var valueNode = BooleanExpression(); - var assignmentNode = new AssignmentNode(objectNode, valueNode).SetTokenInfo(_currentToken); - return assignmentNode; - } - - _currentToken = _lexer.NextToken(); // 消耗对象名称 - //_lexer.SetToken(backupToken); - - List nodes = new List(); // 表达对象成员路径的节点 - while (true) - { - if (_currentToken.Type != TokenType.Dot) - { - _currentToken = _lexer.NextToken(); - continue; - } - - _currentToken = _lexer.NextToken(); // 消耗 "." 获取下一个成员 - if (_currentToken.Type != TokenType.Identifier) - { - continue; - //_lexer.SetToken(peekToken); // 重置lexer - } - var temp2token = _lexer.PeekToken(); - var sourceNode = nodes.Count == 0 ? objectNode : nodes[^1]; - if (temp2token.Type == TokenType.ParenthesisLeft) - { - // 解析方法调用 obj.func() - ASTNode functionNode = ParseMemberFunctionCall(sourceNode).SetTokenInfo(_currentToken); - nodes.Add(functionNode); - } - else if (temp2token.Type == TokenType.SquareBracketsLeft) - { - // 成员数组 obj.dict[key] / obj.array[index] - if (_currentToken.Type == TokenType.Identifier) - { - var memberAccessNode = new MemberAccessNode(sourceNode, _currentToken.Value).SetTokenInfo(_currentToken); - sourceNode = memberAccessNode; - } - var coolectionNode = ParseCollectionIndex(sourceNode).SetTokenInfo(_currentToken); - nodes.Add(coolectionNode); - } - else if (temp2token.Type is TokenType.Dot *//* or TokenType.ParenthesisRight*//*) - { - // 成员获取 obj.value - var memberAccessNode = new MemberAccessNode(sourceNode, _currentToken.Value).SetTokenInfo(_currentToken); - nodes.Add(memberAccessNode); - } - else if (temp2token.Type == TokenType.Operator && temp2token.Value == "=") - { - // 左值结束, 成员获取 obj.value - *//* var memberAccessNode = new MemberAccessNode(sourceNode, _currentToken.Value).SetTokenInfo(_currentToken); - nodes.Add(memberAccessNode);*//* - var memberName = _currentToken.Value; // 成员名称 - _currentToken = _lexer.NextToken(); // 消耗 成员 token - _currentToken = _lexer.NextToken(); // 消耗“=” 等号 - var rightNode = BooleanExpression(); // 判断token - MemberAssignmentNode assignmentNode = new MemberAssignmentNode(sourceNode, memberName, rightNode); - assignmentNode.SetTokenInfo(_currentToken); - - return assignmentNode; // 返回节点 - } - } - } - else if (int_type == 2) // 变量数组赋值 - { - var objectName = _currentToken.Value; - var objectNode = new IdentifierNode(objectName).SetTokenInfo(_currentToken); // 首先定义对象变量节点 - _currentToken = _lexer.NextToken(); // 消耗 变量名称 - if (_currentToken.Type != TokenType.SquareBracketsLeft) - throw new Exception("数组需要 '[' 符号"); - _currentToken = _lexer.NextToken(); // 消耗 "[" - ASTNode indexValue = BooleanExpression(); // 获取表达数组下标的节点 - - _currentToken = _lexer.NextToken(); // 消耗 "]" - var collectionNode = new CollectionIndexNode(objectNode, indexValue); - collectionNode.SetTokenInfo(_currentToken); // 集合节点 - - if (!(_currentToken.Type == TokenType.Operator && _currentToken.Value == "=")) - throw new Exception("数组赋值需要 '=' 符号"); - _currentToken = _lexer.NextToken(); // 消耗 "=" - - var valueNode = BooleanExpression(); // 获取右值表达式 - - var assignmentNode = new CollectionAssignmentNode(collectionNode, valueNode).SetTokenInfo(_currentToken); // 集合节点; - return assignmentNode; - var tempToken1 = _lexer.PeekToken(1); - var tempToken2 = _lexer.PeekToken(2); - var tempToken3 = _lexer.PeekToken(3); - _currentToken = _lexer.NextToken(); - // object[1] = ""; - var taretNode = ""; - } - *//* else if (int_type == 3) // 方法调用 - { - var taretNode = ""; - }*//* - else if (int_type == 4) // 方法调用 - { - // 可能是挂载函数调用 - var functionCallNode = ParseFunctionCall(); - return functionCallNode; - } - else - { - - } - - - int GetFlowType(SereinScriptLexer _lexer, ref int tokenCount) - { - int int_type; - while (true) - { - var tempToken = _lexer.PeekToken(tokenCount++); - - if (tempToken.Type == TokenType.Operator && tempToken.Value == "=") - { - var tempToken2 = _lexer.PeekToken(tokenCount - 2); - if (tempToken2.Type == TokenType.SquareBracketsRight) - { - int_type = 2; // 变量数组赋值 - break; - } - else // if (tempToken2.Type == TokenType.SquareBracketsRight) - { - int_type = 1; // 变量赋值 - break; - } - } - *//* if (tempToken.Type == TokenType.Semicolon) - { - var tempToken2 = _lexer.PeekToken(tokenCount); - if(tempToken2.Type == TokenType.ParenthesisRight) - { - int_type = 3; // 方法调用 - break; - } - }*//* - if (tempToken.Type == TokenType.ParenthesisLeft) // 本地函数调用 - { - int_type = 4; // 本地方法调用 - break; - } - - } - - return int_type; - } - - return null; - #region MyRegion - *//*return null; - var _identifierPeekToken = _lexer.PeekToken(); - if (_identifierPeekToken.Type == TokenType.Operator && _identifierPeekToken.Value == "=") - { - // 如果是操作符 = ,则是直接赋值变量 - var leftValueNode = new IdentifierNode(_currentToken.Value).SetTokenInfo(_currentToken); - var rightValueNode = BooleanExpression(); - return new AssignmentNode(leftValueNode, rightValueNode).SetTokenInfo(_currentToken); - - //return new IdentifierNode(_currentToken.Value).SetTokenInfo(_currentToken); // 获取变量 - } - if (_identifierPeekToken.Type == TokenType.ParenthesisLeft) - { - // 可能是挂载函数调用 - var functionCallNode = ParseFunctionCall(); - return functionCallNode; - } - var objToken = _currentToken; // 对象Token - ASTNode? objectNode = new IdentifierNode(objToken.Value).SetTokenInfo(objToken); // 对象节点 - var identifier = _currentToken.Value; // 标识符字面量 - List nodes = new List(); - while (true) - { - if (_currentToken.Type == TokenType.Dot) - { - _currentToken = _lexer.NextToken(); - if (_currentToken.Type == TokenType.Identifier) - { - var temp2token = _lexer.PeekToken(); - var sourceNode = (nodes.Count == 0 ? objectNode : nodes[^1]); - if(temp2token.Type == TokenType.Operator && temp2token.Value == "=") - { - // 成员获取 obj.value = - var memberAccessNode = new MemberAccessNode(sourceNode, _currentToken.Value).SetTokenInfo(_currentToken); - nodes.Add(memberAccessNode); - //break; - // 赋值行为 - *//*var assignmentNode = ParseAssignment(); - nodes.Add(assignmentNode);*//* - } - else if (temp2token.Type == TokenType.ParenthesisLeft) - { - // 解析方法调用 obj.func() - ASTNode functionNode = ParseMemberFunctionCall(sourceNode).SetTokenInfo(_currentToken); - nodes.Add(functionNode); - } - else if (temp2token.Type == TokenType.SquareBracketsLeft) - { - // 成员数组 obj.dict[key] / obj.array[index] - if (_currentToken.Type == TokenType.Identifier) - { - var memberAccessNode = new MemberAccessNode(sourceNode, _currentToken.Value).SetTokenInfo(_currentToken); - sourceNode = memberAccessNode; - } - var coolectionNode = ParseCollectionIndex(sourceNode).SetTokenInfo(_currentToken); - nodes.Add(coolectionNode); - } - else if (temp2token.Type is TokenType.Dot or TokenType.Semicolon or TokenType.ParenthesisRight ) - { - // 成员获取 obj.value - var memberAccessNode = new MemberAccessNode(sourceNode, _currentToken.Value).SetTokenInfo(_currentToken); - nodes.Add(memberAccessNode); - } - //_lexer.SetToken(peekToken); // 重置lexer - } - } - else - { - _currentToken = _lexer.NextToken(); - } - if (nodes.Count > 0 && _currentToken.Type == TokenType.Operator && _currentToken.Value == "=") - { - _currentToken = _lexer.NextToken(); // 消耗操作符 - // 分号意味着语句结束 - var rightValueNode = BooleanExpression(); - if (nodes.Count == 1) - { - //_currentToken = _lexer.NextToken(); // 右值 - var assignmentNode = new AssignmentNode(nodes[0], rightValueNode); - //var node = nodes[^1]; - return assignmentNode; - } - else - { - var objNode = new ObjectMemberExpressionNode(objectNode, nodes).SetTokenInfo(objToken); - var assignmentNode = new AssignmentNode(objNode, rightValueNode); - return objNode; - } - //AssignmentNode assignmentNode = new AssignmentNode(rightValueNode); - break; - } - if (_currentToken.Type is TokenType.Semicolon) - { - // 分号意味着语句结束 - break; - } - } - if (nodes.Count == 0) - { - return objectNode; - } - if (nodes.Count == 1) - { - var t = new AssignmentNode(objectNode, nodes[^1]); - var node = nodes[^1]; - return node; - } - else - { - var objNode = new ObjectMemberExpressionNode(objectNode, nodes).SetTokenInfo(objToken); - return objNode; - }*//* - #endregion - - // 检查标识符后是否跟有左圆括号 - var _tempToken = _lexer.PeekToken(); - if (_tempToken.Type == TokenType.ParenthesisLeft) - { - // 解析函数调用 - return ParseFunctionCall(); - } - else if (_tempToken.Type == TokenType.Dot) - { - // 对象成员的获取 - - return ParseMemberAccessOrAssignment(); - } - else if (_tempToken.Type == TokenType.SquareBracketsLeft) - { - // 数组 index; 字典 key obj.Member[xxx]; - return ParseCollectionIndex(); - - } - else - { - // 不是函数调用,是变量赋值或其他 - return ParseAssignment(); - } - - } - - - /// - /// 解析赋值行为 - /// - /// - /// - private ASTNode ParseAssignment() - { - string variableName = _currentToken.Value.ToString(); - - var _peekToken = _lexer.PeekToken(); - if (_peekToken.Type == TokenType.ParenthesisRight) - { - _currentToken = _lexer.NextToken(); // 消耗标识符 - - return new IdentifierNode(variableName).SetTokenInfo(_currentToken); - } - - if(_peekToken.Type == TokenType.Operator && _peekToken.Value == "=") - { - // 赋值行为 - _currentToken = _lexer.NextToken(); // 消耗标识符 - _currentToken = _lexer.NextToken(); // 消耗 "=" - var _tempToken = _lexer.PeekToken(); - ASTNode valueNode; - - if(_tempToken.Type == TokenType.Operator && _tempToken.Value != "=") - { - //_currentToken = _lexer.NextToken(); // 消耗操作符 - //_currentToken = _lexer.NextToken(); // 消耗操作符 - valueNode = BooleanExpression(); - //valueNode = Expression(); - } - else if (_tempToken.Type == TokenType.ParenthesisLeft) - { - // 解析赋值右边的表达式 - // 是函数调用,解析函数调用 - valueNode = ParseFunctionCall(); - } - else - { - // 解析赋值右边的字面量表达式 - valueNode = BooleanExpression(); - //valueNode = Expression(); - } - var variableNode = new IdentifierNode(variableName).SetTokenInfo(_currentToken); - return new AssignmentNode(variableNode, valueNode).SetTokenInfo(_currentToken); - } - if (_peekToken.Type == TokenType.Dot) - { - // 可能是方法调用 - return ParseMemberAccessOrAssignment(); - } - - if(_peekToken.Type == TokenType.Operator) - { - return new IdentifierNode(variableName).SetTokenInfo(_currentToken); - } - - - throw new Exception($"Expected '{_currentToken.Value}' after variable name"); - - } - - /// - /// 解析 let 变量赋值行为 - /// - /// - /// - private ASTNode ParseLetAssignment() - { - - _currentToken = _lexer.NextToken(); // Consume "let" - string variableName = _currentToken.Value.ToString(); // 变量名称 - _currentToken = _lexer.NextToken(); // Consume identifier - ASTNode value; - AssignmentNode assignmentNode; - if (_currentToken.Type == TokenType.Semicolon) - { - // 定义一个变量,初始值为 null - value = new NullNode(); - var variableNode = new IdentifierNode(variableName).SetTokenInfo(_currentToken); - assignmentNode = new AssignmentNode(variableNode, value); // 生成node - assignmentNode.SetTokenInfo(_currentToken); // 设置token信息 - } - else - { - // 如果定义了变量,后面紧跟着操作符,且操作符不是“=”话视为异常 - // let value = obj; - if (_currentToken.Type != TokenType.Operator || _currentToken.Value != "=") - throw new Exception("Expected '=' after variable name"); - _currentToken = _lexer.NextToken(); // 消耗操作符(“=”) - var nodeToken = _currentToken; - value = BooleanExpression(); // 解析获取赋值表达式 - //value = Expression(); // 解析获取赋值表达式 - var variableNode = new IdentifierNode(variableName).SetTokenInfo(_currentToken); - assignmentNode = new AssignmentNode(variableNode, value); // 生成node - assignmentNode.SetTokenInfo(nodeToken); // 设置token信息 - _currentToken = _lexer.NextToken(); // 消耗分号 - } - return assignmentNode; - - - - } - - /// - /// 解析类定义 - /// - /// - /// - private ASTNode ParseClassDefinition() - { - var sb = new StringBuilder(); // 收集代码信息 - *//* - * 有两种定义类型的方式: - * 1. class MyClass{} - * 2. new class MyClass{} - * 解析执行时,第二种方式定义的类,会顶掉其他地方创建的“MyClass”同名类型; - *//* - var coreStartRangeIndex = _lexer.GetIndex() - "class".Length; // 从“class”开始锚定代码范围 - bool isOverlay = false; // 指示是否覆盖缓存中创建过的同名其它类型 - - if (_currentToken.Value == "new") - { - isOverlay = true; // 重新加载类 - _currentToken = _lexer.NextToken(); // 消耗 new 关键字 - } - _currentToken = _lexer.NextToken(); // 消耗 class 关键字 - var className = _currentToken.Value.ToString(); // 获取定义的类名 - _currentToken = _lexer.NextToken(); // 消耗类名 - if (_currentToken.Type != TokenType.BraceLeft || _currentToken.Value != "{") - throw new Exception("Expected '{' after class definition"); - var classFields = new Dictionary(); - _currentToken = _lexer.NextToken(); // 消耗括号 - - while (_currentToken.Type != TokenType.BraceRight) - { - // 获取类字段定义 - var fieldTypeName = _currentToken.Value.ToString(); - var dynamicType = DynamicObjectHelper.GetCacheType(fieldTypeName); - - var fieldType = dynamicType ?? _currentToken.Value.ToString().ToTypeOfString(); // 获取字段的类型 - _currentToken = _lexer.NextToken(); // 消耗类型 - var fieldName = _currentToken.Value.ToString(); // 获取定义的类名 - _currentToken = _lexer.NextToken(); // 消耗字段名称 - classFields.Add(fieldName,fieldType); // 添加字段 - if (_currentToken.Type == TokenType.Semicolon - && _lexer.PeekToken().Type == TokenType.BraceRight) - { - // 如果遇到分号、大括号,退出字段定义。 - break; - } - else - { - _currentToken = _lexer.NextToken(); - } - - } - _currentToken = _lexer.NextToken(); // 消耗类型定义 } 括号 - var typeDefinitionCode = _lexer.GetCoreContent(coreStartRangeIndex); // 收集类型定义的代码。 - - DynamicObjectHelper.CreateTypeWithProperties(classFields, className, isOverlay); // 解析时缓存类型 - var node = new ClassTypeDefinitionNode(classFields, className, isOverlay); - _currentToken.Code = typeDefinitionCode; - node.SetTokenInfo(_currentToken); - // _currentToken = _lexer.NextToken(); - _currentToken = _lexer.NextToken(); - return node; - } - - /// - /// 解析对象实例化行为 - /// - /// - /// - public ASTNode ParseObjectInstantiation() - { - _currentToken = _lexer.NextToken(); // 消耗 new 关键字 - string typeName = _currentToken.Value.ToString(); // 获取类型名称 - _currentToken = _lexer.NextToken(); - if (_currentToken.Type != TokenType.ParenthesisLeft) - throw new Exception("Expected '(' after function name"); - - _currentToken = _lexer.NextToken(); // 消耗 "(" - - var arguments = new List(); - while (_currentToken.Type != TokenType.ParenthesisRight) - { - //arguments.Add(Expression()); // 获取参数表达式 - arguments.Add(BooleanExpression()); // 获取参数表达式 - if (_currentToken.Type == TokenType.Comma) - { - _currentToken = _lexer.NextToken(); // consume "," - } - } - - _currentToken = _lexer.NextToken(); // 消耗 ")" - return new ObjectInstantiationNode(typeName, arguments).SetTokenInfo(_currentToken); - } - - /// - /// 解析集合索引行为(数组或字典) - /// - /// - /// - public ASTNode ParseCollectionIndex() - { - var identifierNode = new IdentifierNode(_currentToken.Value.ToString()).SetTokenInfo(_currentToken); - - string collectionName = _currentToken.Value.ToString(); - //_lexer.NextToken(); // consume "[" - _currentToken = _lexer.NextToken(); // 消耗数组名称 identifier - // ParenthesisLeft - if (_currentToken.Type != TokenType.SquareBracketsLeft) - throw new Exception("数组操作需要 '[' 符号"); - - _currentToken = _lexer.NextToken(); // 消耗 "[" - - //ASTNode indexValue = Expression(); // 获取表达数组下标的节点 - ASTNode indexValue = BooleanExpression(); // 获取表达数组下标的节点 - - _currentToken = _lexer.NextToken(); // 消耗 "]" - return new CollectionIndexNode(identifierNode, indexValue).SetTokenInfo(_currentToken); - } - - /// - /// 指定对象解析集合索引行为(数组或字典) - /// - /// - /// - public ASTNode ParseCollectionIndex(ASTNode ObjectNode) - { - string collectionName = _currentToken.Value.ToString(); - _currentToken = _lexer.NextToken(); // 消耗数组名称 identifier - // ParenthesisLeft - if (_currentToken.Type != TokenType.SquareBracketsLeft) - throw new Exception("Expected '[' after function name"); - - _currentToken = _lexer.NextToken(); // 消耗 "[" - - //ASTNode indexValue = Expression(); // 获取表达数组下标的节点 - ASTNode indexValue = BooleanExpression(); // 获取表达数组下标的节点 - - _currentToken = _lexer.NextToken(); // 消耗 "]" - return new CollectionIndexNode(ObjectNode, indexValue).SetTokenInfo(_currentToken); - } - - /// - /// 获取对象成员 - /// - /// - /// - private ASTNode ParseMemberAccessOrAssignment() - { - var identifierNode = new IdentifierNode(_currentToken.Value).SetTokenInfo(_currentToken); - _currentToken = _lexer.NextToken(); // 消耗当前标识符 - - - // 处理成员访问:identifier.member - if (_currentToken.Type == TokenType.Dot) - { - _currentToken = _lexer.NextToken(); // 消耗 "." - if (_currentToken.Type != TokenType.Identifier) - { - throw new Exception("Expected member name after dot."); - } - - var memberName = _currentToken.Value; - //_currentToken = _lexer.NextToken(); // 消耗成员名 - - var _peekToken = _lexer.PeekToken(); - if (_peekToken.Type == TokenType.Operator && _peekToken.Value == "=") - { - // 成员赋值 obj.Member = xxx; - _currentToken = _lexer.NextToken(); // 消耗 "=" - _currentToken = _lexer.NextToken(); // 消耗 "=" - //var valueNode = Expression(); // 解析右值 - var valueNode = BooleanExpression(); // 解析右值 - _currentToken = _lexer.NextToken(); // 消耗 变量 - //_currentToken = _lexer.NextToken(); // 消耗 ; - return new MemberAssignmentNode(identifierNode, memberName, valueNode).SetTokenInfo(_peekToken); - } - else - { - - if(_peekToken.Type == TokenType.ParenthesisLeft) - { - // 成员方法调用 obj.Member(xxx); - return ParseMemberFunctionCall(identifierNode); - } - else if (_peekToken.Type == TokenType.SquareBracketsLeft) - { - // 数组 index; 字典 key obj.Member[xxx]; - return ParseCollectionIndex(); - } - else - { - - _currentToken = _lexer.NextToken(); // 消耗 成员名称 - // 成员获取 - return new MemberAccessNode(identifierNode, memberName).SetTokenInfo(_currentToken); - } - - } - } - - return identifierNode; - } - - - /// - /// 解析成员函数调用行为 - /// - /// - /// - /// - private ASTNode ParseMemberFunctionCall(ASTNode targetNode) - { - string functionName = _currentToken.Value.ToString(); // 函数名称 - _currentToken = _lexer.NextToken(); // 消耗函数名称 - - if (_currentToken.Type != TokenType.ParenthesisLeft) - throw new Exception("Expected '(' after function name"); - - _currentToken = _lexer.NextToken(); // 消耗 "(" - - var arguments = new List(); - while (_currentToken.Type != TokenType.ParenthesisRight) - { - // 获取参数表达式 - //var arg = Expression(); - var arg = BooleanExpression(); - _currentToken = _lexer.NextToken(); // 消耗参数 arg - arguments.Add(arg); // 添加到参数列表 - if (_currentToken.Type == TokenType.Comma) - { - _currentToken = _lexer.NextToken(); // 消耗参数分隔符 "," - } - if (_currentToken.Type == TokenType.Semicolon) - { - break; // 消耗 ";" - } - } - - //_currentToken = _lexer.NextToken(); // consume ")" - - return new MemberFunctionCallNode(targetNode, functionName, arguments).SetTokenInfo(_currentToken); - } - - - /// - /// 解析函数调用行为 - /// - /// - /// - private ASTNode ParseFunctionCall() - { - string functionName = _currentToken.Value.ToString(); - _currentToken = _lexer.NextToken(); // consume identifier - - if (_currentToken.Type != TokenType.ParenthesisLeft) - throw new Exception("Expected '(' after function name"); - - _currentToken = _lexer.NextToken(); // consume "(" - - bool isBreak = false; - var arguments = new List(); - // 获取参数 - while (true)// _currentToken.Type != TokenType.ParenthesisRight - { - if (_currentToken.Type == TokenType.ParenthesisRight) - { - break; - } - //var arg = Expression(); // 获取参数表达式 - var arg = BooleanExpression(); // 获取参数表达式 - arguments.Add(arg); - if (_currentToken.Type == TokenType.Comma) - { - _currentToken = _lexer.NextToken(); // 消耗参数分隔符 "," - } - if (_currentToken.Type == TokenType.ParenthesisRight ) - { - _currentToken = _lexer.NextToken(); // 消耗方法结束括号 ")" - } - if (_currentToken.Type == TokenType.Semicolon ) - { - //isBreak = true; - break; // consume ";" - } - *//*if (_currentToken.Type == TokenType.Semicolon) // 提前结束 - { - arguments.Add(arg); - isBreak = true; - break; // consume ";" - }*//* - //_currentToken = _lexer.NextToken(); // consume arg - } - //if(!isBreak) - // _currentToken = _lexer.NextToken(); // consume ")" - - - //var node = Statements[^1]; - //if (node is MemberAccessNode memberAccessNode) - //{ - // // 上一个是对象 - // return new MemberFunctionCallNode(memberAccessNode, functionName, arguments).SetTokenInfo(_currentToken); - //} - //if (node is IdentifierNode identifierNode) - //{ - // return new MemberFunctionCallNode(identifierNode, functionName, arguments).SetTokenInfo(_currentToken); - //} - - // 从挂载的函数表寻找对应的函数,尝试调用 - return new FunctionCallNode(functionName, arguments).SetTokenInfo(_currentToken); - - - } - - /// - /// 解析 return 语句。 - /// - /// - public ASTNode ParseReturn() - { - _currentToken = _lexer.NextToken(); - if(_currentToken.Type == TokenType.Semicolon) - { - return new ReturnNode().SetTokenInfo(_currentToken); // 返回空的 ReturnNode - } - var resultValue = BooleanExpression(); // 获取返回值表达式 - //var resultValue = Expression(); // 获取返回值表达式 - _currentToken = _lexer.NextToken(); - return new ReturnNode(resultValue).SetTokenInfo(_currentToken); - } - - - /// - /// 解析 if 语句。 - /// - /// - /// - private ASTNode ParseIf() - { - _currentToken = _lexer.NextToken(); // Consume "if" - _currentToken = _lexer.NextToken(); // Consume "(" - ASTNode condition = BooleanExpression(); - //ASTNode condition = Expression(); - _currentToken = _lexer.NextToken(); // Consume ")" - - // 确保遇到左大括号 { 后进入代码块解析 - if (_currentToken.Type != TokenType.BraceLeft) - { - throw new Exception("Expected '{' after if condition"); - } - _currentToken = _lexer.NextToken(); // Consume "{" - - // 解析大括号中的语句 - List trueBranch = new List(); - List falseBranch = new List(); - while (_currentToken.Type != TokenType.BraceRight && _currentToken.Type != TokenType.EOF) - { - var astNode = Statement(); // 解析 if 分支中的语句 - while (_currentToken.Type == TokenType.Semicolon) - { - _currentToken = _lexer.NextToken(); - } - if (astNode != null) - { - trueBranch.Add(astNode); // 将 if 分支的语句添加到 trueBranch 中 - } - } - // 确保匹配右大括号 } - if (_currentToken.Type != TokenType.BraceRight) - { - throw new Exception("Expected '}' after if block"); - } - _currentToken = _lexer.NextToken(); // Consume "}" - if (_currentToken.Type == TokenType.Keyword && _currentToken.Value == "else") - { - _currentToken = _lexer.NextToken(); // Consume "{" - _currentToken = _lexer.NextToken(); // Consume "{" - while (_currentToken.Type != TokenType.BraceRight && _currentToken.Type != TokenType.EOF) - { - var astNode = Statement(); // 解析 else 分支中的语句 - while (_currentToken.Type == TokenType.Semicolon) - { - _currentToken = _lexer.NextToken(); - } - if (astNode != null) - { - falseBranch.Add(astNode); // 将 else 分支的语句添加到 falseBranch 中 - } - } - // 确保匹配右大括号 } - if (_currentToken.Type != TokenType.BraceRight) - { - throw new Exception("Expected '}' after if block"); - } - _currentToken = _lexer.NextToken(); // Consume "}" - } - - - return new IfNode(condition, trueBranch, falseBranch).SetTokenInfo(_currentToken); - } - - /// - /// 解析 while 循环语句。 - /// - /// - private ASTNode ParseWhile() - { - _currentToken = _lexer.NextToken(); // Consume "while" - _currentToken = _lexer.NextToken(); // Consume "(" - ASTNode condition = BooleanExpression(); - //ASTNode condition = Expression(); - _currentToken = _lexer.NextToken(); // Consume ")" - _currentToken = _lexer.NextToken(); // Consume "{" - List body = new List(); - while (_currentToken.Type != TokenType.BraceRight) - { - var node = Statement(); - if(node is not null) - { - body.Add(node); // 解析循环体中的语句 - } - if (_currentToken.Type == TokenType.Semicolon) - { - _currentToken = _lexer.NextToken(); // Consume ";" - } - - - } - _currentToken = _lexer.NextToken(); // Consume "}" - return new WhileNode(condition, body).SetTokenInfo(_currentToken); - } - - - - - - - /// - /// 解析因子(Factor),用于处理基本的字面量、标识符、括号表达式等。 - /// - /// - /// - private ASTNode FactorTemp() - { - // 标识符节点 - if (_currentToken.Type == TokenType.Identifier) - { - var _identifierPeekToken = _lexer.PeekToken(); - if (_identifierPeekToken.Type is (TokenType.Dot and TokenType.ParenthesisLeft) - or TokenType.Semicolon - or TokenType.Comma - or TokenType.SquareBracketsRight) // 数组下标的"]",应该是正在获取数组索引 - { - // 不是 "." 号,也不是 "(" , 或是";",则是获取变量 - var node = new IdentifierNode(_currentToken.Value).SetTokenInfo(_currentToken); // 获取变量 - _currentToken = _lexer.NextToken(); // 消耗变量 - return node; - } - - if (_identifierPeekToken.Type == TokenType.SquareBracketsLeft) - { - // 数组下标语法 - //var functionCallNode = ParseFunctionCall(); - var sourceNode = new IdentifierNode(_currentToken.Value).SetTokenInfo(_currentToken); // 获取变量 - var coolectionNode = ParseCollectionIndex(sourceNode).SetTokenInfo(_currentToken); - return coolectionNode; - } - if (_identifierPeekToken.Type == TokenType.ParenthesisLeft) - { - // 可能是挂载函数调用 - var functionCallNode = ParseFunctionCall(); - return functionCallNode; - } - var objToken = _currentToken; // 对象Token - ASTNode? objectNode = new IdentifierNode(objToken.Value).SetTokenInfo(objToken); // 对象节点 - var identifier = _currentToken.Value; // 标识符字面量 - List nodes = new List(); - while (true) - { - if (_currentToken.Type == TokenType.Dot) - { - _currentToken = _lexer.NextToken(); - if (_currentToken.Type == TokenType.Identifier) - { - var temp2token = _lexer.PeekToken(); - var sourceNode = (nodes.Count == 0 ? objectNode : nodes[^1]); - if (temp2token.Type == TokenType.ParenthesisLeft) - { - // 解析方法调用 obj.func() - ASTNode functionNode = ParseMemberFunctionCall(sourceNode).SetTokenInfo(_currentToken); - nodes.Add(functionNode); - } - else if (temp2token.Type == TokenType.SquareBracketsLeft) - { - // 成员数组 obj.dict[key] / obj.array[index] - if (_currentToken.Type == TokenType.Identifier) - { - sourceNode = new MemberAccessNode(sourceNode, _currentToken.Value).SetTokenInfo(_currentToken); - } - var coolectionNode = ParseCollectionIndex(sourceNode).SetTokenInfo(_currentToken); - nodes.Add(coolectionNode); - } - else if (temp2token.Type is TokenType.Operator or TokenType.Dot or TokenType.Semicolon or TokenType.ParenthesisRight) - { - // 成员获取 obj.value - var memberAccessNode = new MemberAccessNode(sourceNode, _currentToken.Value).SetTokenInfo(_currentToken); - nodes.Add(memberAccessNode); - } - //_lexer.SetToken(peekToken); // 重置lexer - } - } - else - { - _currentToken = _lexer.NextToken(); - } - if (_currentToken.Type is TokenType.Operator) - { - // 分号意味着语句结束 - break; - }if (_currentToken.Type is TokenType.Semicolon) - { - // 分号意味着语句结束 - break; - } - } - if (nodes.Count == 0) - { - return objectNode; - } - else - { - var node = nodes[^1]; - var objNode = new ExpressionNode(node).SetTokenInfo(objToken); - return objNode; - } - } - - // 嵌套表达式 - if (_currentToken.Type == TokenType.ParenthesisLeft) - { - _currentToken = _lexer.NextToken(); // 消耗 "(" - var expr = BooleanExpression(); - //var expr = Expression(); - if (_currentToken.Type != TokenType.ParenthesisRight) - throw new Exception("非预期的符号,预期符号为\")\"。"); - _currentToken = _lexer.NextToken(); // 消耗 ")" - return expr; - } - - // 创建对象 - if (_currentToken.Type == TokenType.Keyword && _currentToken.Value == "new") - { - // 可能是对象实例化 - return ParseObjectInstantiation(); - } - - #region 返回字面量 - if (_currentToken.Type == TokenType.Null) - { - _currentToken = _lexer.NextToken(); // 消耗 null - return new NullNode().SetTokenInfo(_currentToken); - } - if (_currentToken.Type == TokenType.Boolean) - { - var value = bool.Parse(_currentToken.Value); - _currentToken = _lexer.NextToken(); // 消耗布尔量 - return new BooleanNode(value).SetTokenInfo(_currentToken); - } - if (_currentToken.Type == TokenType.String) - { - var text = _currentToken.Value; - var node = new StringNode(text).SetTokenInfo(_currentToken); - _currentToken = _lexer.NextToken(); // 消耗字符串 - return node; - } - if (_currentToken.Type == TokenType.Char) - { - var text = _currentToken.Value; - _currentToken = _lexer.NextToken(); // 消耗Char - return new CharNode(text).SetTokenInfo(_currentToken); - } - if (_currentToken.Type == TokenType.InterpolatedString) - { - // 暂未实现插值字符串 - // 可能是插值字符串; - // let context = $"a{A}b{B}c"; - // let context = "a" + A + "b" + B + c; - _currentToken = _lexer.NextToken(); // 消耗字符串 - while (_currentToken.Type == TokenType.String) - { - } - } - - if (_currentToken.Type == TokenType.NumberInt) - { - var value = int.Parse(_currentToken.Value); - _currentToken = _lexer.NextToken(); // 消耗 int 整型 - return new NumberIntNode(value).SetTokenInfo(_currentToken); - } - - if (_currentToken.Type == TokenType.NumberLong) - { - var value = long.Parse(_currentToken.Value); - _currentToken = _lexer.NextToken(); // 消耗 - return new NumberLongNode(value).SetTokenInfo(_currentToken); - } - - if (_currentToken.Type == TokenType.NumberFloat) - { - var value = float.Parse(_currentToken.Value); - _currentToken = _lexer.NextToken(); // 消耗数字 - return new NumberFloatNode(value).SetTokenInfo(_currentToken); - } - - if (_currentToken.Type == TokenType.NumberDouble) - { - var value = float.Parse(_currentToken.Value); - _currentToken = _lexer.NextToken(); // 消耗数字 - return new NumberDoubleNode(value).SetTokenInfo(_currentToken); - } - #endregion - - - throw new Exception($"在Expression().Factor()遇到意外的 Token Type ,{_currentToken.Type} {_currentToken.Value} " ); - }*/ - #endregion } } diff --git a/Serein.Script/SereinScriptTypeAnalysis.cs b/Serein.Script/SereinScriptTypeAnalysis.cs index efc98bf..d73776f 100644 --- a/Serein.Script/SereinScriptTypeAnalysis.cs +++ b/Serein.Script/SereinScriptTypeAnalysis.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.Linq; using System.Reactive; using System.Reflection; +using System.Reflection.Emit; using System.Text; using System.Threading.Tasks; using System.Xml.Linq; @@ -26,11 +27,6 @@ namespace Serein.Script /// public Dictionary NodeSymbolInfos { get; } = new Dictionary(); - public SereinScriptTypeAnalysis() - { - - } - public void LoadSymbol(Dictionary identifierNodes) { foreach(var kvp in identifierNodes) @@ -43,7 +39,7 @@ namespace Serein.Script } - public void AnalysisProgramNode(ProgramNode astNode) + public void Analysis(ProgramNode astNode) { //NodeSymbolInfos.Clear(); for (int i = 0; i < astNode.Statements.Count; i++) @@ -52,8 +48,8 @@ namespace Serein.Script Analysis(node); } - - var returnNodes = astNode.Statements.Where(node => node is ReturnNode).ToArray(); + + var returnNodes = NodeSymbolInfos.Keys.Where(node => node is ReturnNode).ToArray(); if (returnNodes.Length == 0) { NodeSymbolInfos[astNode] = typeof(void); // 程序无返回值 @@ -66,7 +62,15 @@ namespace Serein.Script } else { - + var firstReturnType = NodeSymbolInfos[returnNodes[0]]; // 第一个返回值 + foreach(var item in returnNodes) + { + if(NodeSymbolInfos[item] != firstReturnType) + { + throw new Exception("类型检查异常,存在不同分支返回值类型不一致"); + } + } + NodeSymbolInfos[astNode] = NodeSymbolInfos[returnNodes[0]]; // 确定的返回值 } } @@ -235,32 +239,61 @@ namespace Serein.Script case ClassTypeDefinitionNode classTypeDefinitionNode: // 类型定义 Type AnalysisClassTypeDefinitionNode(ClassTypeDefinitionNode classTypeDefinitionNode) { - var classType = DynamicObjectHelper.GetCacheType(classTypeDefinitionNode.ClassName); - if (classType is null) - classType = DynamicObjectHelper.CreateTypeWithProperties(classTypeDefinitionNode.Fields, classTypeDefinitionNode.ClassName); + + var classType = Analysis(classTypeDefinitionNode.ClassType); // 查询类型 + NodeSymbolInfos[classTypeDefinitionNode] = classType; + + foreach (var kvp in classTypeDefinitionNode.Propertys) + { + TypeNode propertyNode = kvp.Value; + var propertyType = Analysis(propertyNode); // 查询属性类型 + NodeSymbolInfos[propertyNode] = propertyType; + } + NodeSymbolInfos[classTypeDefinitionNode] = classType; return classType; } return AnalysisClassTypeDefinitionNode(classTypeDefinitionNode); + case TypeNode typeNode: + Type AnalysisTypeNode(TypeNode typeNode) + { + // 类型搜寻优先级: 挂载类型 > 脚本中定义类型 > C#类型 + Type resultType = GetTypeOfString(typeNode.TypeName); // 从自定义类型查询类型 + NodeSymbolInfos[typeNode] = resultType; + return resultType; + } + return AnalysisTypeNode(typeNode); case ObjectInstantiationNode objectInstantiationNode: // 类型实例化 Type AnalysisObjectInstantiationNode(ObjectInstantiationNode objectInstantiationNode) { - Type? resultType = null; - try + Type resultType = Analysis(objectInstantiationNode.Type); + foreach(var item in objectInstantiationNode.CtorAssignments) { - resultType = Type.GetType(objectInstantiationNode.TypeName); // 从命名空间查询类型 - } - finally - { - if (resultType is null) - { - resultType = DynamicObjectHelper.GetCacheType(objectInstantiationNode.TypeName); // 从自定义类型查询类型 - } + Analysis(item); } NodeSymbolInfos[objectInstantiationNode] = resultType; return resultType; } return AnalysisObjectInstantiationNode(objectInstantiationNode); + case CtorAssignmentNode ctorAssignmentNode: // 构造器赋值 + Type AnalysisCtorAssignmentNode(CtorAssignmentNode ctorAssignmentNode) + { + Type classType = Analysis(ctorAssignmentNode.Class); + Type valueType = Analysis(ctorAssignmentNode.Value); + //ctorAssignmentNode.MemberName + var property = classType.GetProperty(ctorAssignmentNode.MemberName); + if (property is null) + throw new Exception($"类型 {classType} 没有成员 {ctorAssignmentNode.MemberName}"); + var propertyType = property.PropertyType; + if (!propertyType.IsAssignableFrom(valueType)) + throw new Exception($"类型异常:构造器赋值需要 {propertyType},实际为 {valueType}"); + + NodeSymbolInfos[ctorAssignmentNode.Class] = classType; + NodeSymbolInfos[ctorAssignmentNode.Value] = valueType; + NodeSymbolInfos[ctorAssignmentNode] = propertyType; + return valueType; + } + return AnalysisCtorAssignmentNode(ctorAssignmentNode); case ExpressionNode expressionNode: // 类型表达式(链式调用) Type AnalysisObjectMemberExpressionNode(ExpressionNode expressionNode) { @@ -289,16 +322,33 @@ namespace Serein.Script Type AnalysisMemberAssignmentNode(MemberAssignmentNode memberAssignmentNode) { var objectType = Analysis(memberAssignmentNode.Object); - var property = objectType.GetProperty(memberAssignmentNode.MemberName); - if(property is null) - throw new Exception($"类型异常:类型 {objectType} 没有成员 {memberAssignmentNode.MemberName}"); - var propertyType = property.PropertyType; - var valueType = Analysis(memberAssignmentNode.Value); - if (!propertyType.IsAssignableFrom(valueType)) - throw new Exception($"类型异常:赋值需要 {propertyType},实际为 {valueType}"); - NodeSymbolInfos[memberAssignmentNode.Object] = propertyType; - NodeSymbolInfos[memberAssignmentNode.Value] = valueType; - NodeSymbolInfos[memberAssignmentNode] = typeof(void); + if(objectType == typeof(object)) + { + /*var property = objectType.GetProperty(memberAssignmentNode.MemberName); + if (property is null) + throw new Exception($"类型异常:类型 {objectType} 没有成员 {memberAssignmentNode.MemberName}"); + var propertyType = property.PropertyType; + var valueType = Analysis(memberAssignmentNode.Value); + if (!propertyType.IsAssignableFrom(valueType)) + throw new Exception($"类型异常:赋值需要 {propertyType},实际为 {valueType}");*/ + NodeSymbolInfos[memberAssignmentNode.Object] = typeof(object); + NodeSymbolInfos[memberAssignmentNode.Value] = typeof(object); + NodeSymbolInfos[memberAssignmentNode] = typeof(void); + } + else + { + var property = objectType.GetProperty(memberAssignmentNode.MemberName); + if (property is null) + throw new Exception($"类型异常:类型 {objectType} 没有成员 {memberAssignmentNode.MemberName}"); + var propertyType = property.PropertyType; + var valueType = Analysis(memberAssignmentNode.Value); + if (!propertyType.IsAssignableFrom(valueType)) + throw new Exception($"类型异常:赋值需要 {propertyType},实际为 {valueType}"); + NodeSymbolInfos[memberAssignmentNode.Object] = propertyType; + NodeSymbolInfos[memberAssignmentNode.Value] = valueType; + NodeSymbolInfos[memberAssignmentNode] = typeof(void); + } + return typeof(void); // 对象成员赋值语句不产生类型 } return AnalysisMemberAssignmentNode(memberAssignmentNode); @@ -319,12 +369,14 @@ namespace Serein.Script NodeSymbolInfos[memberFunctionCallNode.Object] = objectType; NodeSymbolInfos[memberFunctionCallNode] = methodInfo.ReturnType; return methodInfo.ReturnType; + + } return AnalysisMemberFunctionCallNode(memberFunctionCallNode); case FunctionCallNode functionCallNode: // 外部挂载的函数调用 Type AnalysisFunctionCallNode(FunctionCallNode functionCallNode) { - if(!SereinScriptInterpreter.FunctionInfoTable.TryGetValue(functionCallNode.FunctionName, out var methodInfo)) + if(!SereinScript.FunctionInfos.TryGetValue(functionCallNode.FunctionName, out var methodInfo)) { throw new Exception($"脚本没有挂载方法 {functionCallNode.FunctionName}"); } @@ -486,6 +538,8 @@ namespace Serein.Script break; case ClassTypeDefinitionNode classTypeDefinitionNode: // 类型定义 break; + case TypeNode typeNode: // 类型 + break; case ObjectInstantiationNode objectInstantiationNode: // 类型实例化 break; case ExpressionNode expressionNode: // 类型表达式(链式调用) @@ -504,6 +558,29 @@ namespace Serein.Script } + public static Type GetTypeOfString(string typeName) + { + Type? resultType = null; + resultType = DynamicObjectHelper.GetCacheType(typeName); // 从自定义类型查询类型 + if (resultType != null) + { + return resultType; + } + try + { + resultType = Type.GetType(typeName); // 从命名空间查询类型 + if (resultType != null) + { + return resultType; + } + throw new InvalidOperationException($"无法匹配类型 {typeName}"); + } + catch (Exception ex) + { + throw; + } + } + diff --git a/Workbench/App.xaml.cs b/Workbench/App.xaml.cs index ce1654c..af530fc 100644 --- a/Workbench/App.xaml.cs +++ b/Workbench/App.xaml.cs @@ -8,6 +8,7 @@ using Serein.NodeFlow.Services; using Serein.Workbench.Api; using Serein.Workbench.Services; using Serein.Workbench.ViewModels; +using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Runtime.CompilerServices; @@ -55,6 +56,23 @@ namespace Serein.Workbench // 这里是测试代码,可以删除 private async Task LoadLocalProjectAsync() { + var properties = new Dictionary + { + { "Id", typeof(int) }, + { "Name", typeof(string) }, + { "CreateTime", typeof(DateTime) } + }; + + var type = DynamicObjectHelper.CreateTypeWithINotifyPropertyChanged(properties, "MyDynamicClass"); + dynamic? obj = Activator.CreateInstance(type); + if(obj is null) return; + if (obj is INotifyPropertyChanged npc) + { + npc.PropertyChanged += (s, e) => Debug.WriteLine($"属性改变: {e.PropertyName}"); + } + obj.Name = "下北泽"; + obj.Id = 114514; + if (1 == 11) { diff --git a/Workbench/Node/View/ScriptNodeControl.xaml b/Workbench/Node/View/ScriptNodeControl.xaml index 8d44b3c..7cf3d20 100644 --- a/Workbench/Node/View/ScriptNodeControl.xaml +++ b/Workbench/Node/View/ScriptNodeControl.xaml @@ -6,6 +6,7 @@ xmlns:local="clr-namespace:Serein.Workbench.Node.View" xmlns:vm="clr-namespace:Serein.Workbench.Node.ViewModel" xmlns:themes="clr-namespace:Serein.Workbench.Themes" + xmlns:avalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit" d:DataContext="{d:DesignInstance vm:ScriptNodeControlViewModel}" mc:Ignorable="d" MinWidth="50"> @@ -56,7 +57,17 @@ - + + + + diff --git a/Workbench/Node/View/ScriptNodeControl.xaml.cs b/Workbench/Node/View/ScriptNodeControl.xaml.cs index 5fb0ae7..f6b0e0a 100644 --- a/Workbench/Node/View/ScriptNodeControl.xaml.cs +++ b/Workbench/Node/View/ScriptNodeControl.xaml.cs @@ -43,6 +43,7 @@ namespace Serein.Workbench.Node.View DataContext = viewModel; viewModel.NodeModel.DisplayName = "[脚本节点]"; InitializeComponent(); + codeEditor.Text = viewModel.Script ?? string.Empty; // 更新代码编辑器内容 } @@ -96,6 +97,11 @@ namespace Serein.Workbench.Node.View return []; } + private void codeEditor_TextChanged(object sender, EventArgs e) + { + viewModel.Script = codeEditor.Text; + } + diff --git a/Workbench/Serein.WorkBench.csproj b/Workbench/Serein.WorkBench.csproj index 88ec9f3..75c0752 100644 --- a/Workbench/Serein.WorkBench.csproj +++ b/Workbench/Serein.WorkBench.csproj @@ -76,6 +76,7 @@ + diff --git a/Workbench/Views/MainView.xaml.cs b/Workbench/Views/MainView.xaml.cs index 88c51d7..c04422c 100644 --- a/Workbench/Views/MainView.xaml.cs +++ b/Workbench/Views/MainView.xaml.cs @@ -25,6 +25,9 @@ namespace Serein.Workbench.Views { this.DataContext = App.GetService().MainViewModel; InitializeComponent(); + + Window window = new System.Windows.Window(); + window.Show(); } } }