为Serein.Script增加类型分析,增加了更加详细的Number类型节点,优化了对象节点的链式表达式,修复了Lexer分析词法时,部分Token代码属性错误的问题。

This commit is contained in:
fengjiayi
2025-07-11 20:52:21 +08:00
parent 70f674ca1b
commit ec764c5675
27 changed files with 1724 additions and 334 deletions

View File

@@ -14,7 +14,17 @@ namespace Serein.Library.Utils
public class DynamicObjectHelper public class DynamicObjectHelper
{ {
// 类型缓存,键为类型的唯一名称(可以根据实际需求调整生成方式) // 类型缓存,键为类型的唯一名称(可以根据实际需求调整生成方式)
static Dictionary<string, Type> typeCache = new Dictionary<string, Type>(); private static Dictionary<string, Type> typeCache = new Dictionary<string, Type>();
private static readonly AssemblyBuilder AssemblyBuilder;
private static readonly ModuleBuilder ModuleBuilder;
static DynamicObjectHelper() // 静态构造函数
{
var assemblyName = new AssemblyName("DynamicAssembly");
AssemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
ModuleBuilder = AssemblyBuilder.DefineDynamicModule("MainModule");
}
/// <summary> /// <summary>
/// 获取运行时创建过的类型 /// 获取运行时创建过的类型
@@ -82,6 +92,8 @@ namespace Serein.Library.Utils
} }
} }
/// <summary> /// <summary>
/// 创建具有属性的类型 /// 创建具有属性的类型
/// </summary> /// </summary>
@@ -99,12 +111,12 @@ namespace Serein.Library.Utils
} }
// 定义动态程序集和模块 // 定义动态程序集和模块
var assemblyName = new AssemblyName("DynamicAssembly"); /*var assemblyName = new AssemblyName("DynamicAssembly");
var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
var moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule"); var moduleBuilder = AssemblyBuilder.DefineDynamicModule("MainModule");
*/
// 定义动态类型 // 定义动态类型
var typeBuilder = moduleBuilder.DefineType(typeName, TypeAttributes.Public); var typeBuilder = ModuleBuilder.DefineType(typeName, TypeAttributes.Public);
// 为每个属性名和值添加相应的属性到动态类型中 // 为每个属性名和值添加相应的属性到动态类型中
foreach (var kvp in properties) foreach (var kvp in properties)

View File

@@ -35,7 +35,7 @@ namespace Serein.NodeFlow.Model
public override bool IsBase => true; public override bool IsBase => true;
private IScriptFlowApi ScriptFlowApi; private IScriptFlowApi ScriptFlowApi;
private ASTNode mainNode; private ProgramNode programNode;
private SereinScriptInterpreter ScriptInterpreter; private SereinScriptInterpreter ScriptInterpreter;
private bool IsScriptChanged = false; private bool IsScriptChanged = false;
@@ -167,8 +167,10 @@ namespace Serein.NodeFlow.Model
var script = sb.ToString(); var script = sb.ToString();
var p = new SereinScriptParser(script); var p = new SereinScriptParser(script);
//var p = new SereinScriptParser(Script); //var p = new SereinScriptParser(Script);
mainNode = p.Parse(); // 开始解析 programNode = p.Parse(); // 开始解析
var typeAnalysis = new SereinScriptTypeAnalysis();
ScriptInterpreter.SetTypeAnalysis(typeAnalysis);
typeAnalysis.AnalysisProgramNode(programNode);
} }
catch (Exception ex) catch (Exception ex)
@@ -185,7 +187,8 @@ namespace Serein.NodeFlow.Model
/// <returns></returns> /// <returns></returns>
public override async Task<FlowResult> ExecutingAsync(IDynamicContext context, CancellationToken token) public override async Task<FlowResult> ExecutingAsync(IDynamicContext context, CancellationToken token)
{ {
return await ExecutingAsync(this, context, token); var result = await ExecutingAsync(this, context, token);
return result;
} }
/// <summary> /// <summary>
@@ -237,7 +240,8 @@ namespace Serein.NodeFlow.Model
if (token.IsCancellationRequested) return null; if (token.IsCancellationRequested) return null;
var result = await ScriptInterpreter.InterpretAsync(scriptContext, mainNode); // 从入口节点执行
var result = await ScriptInterpreter.InterpretAsync(scriptContext, programNode); // 从入口节点执行
envEvent.FlowRunComplete -= onFlowStop; envEvent.FlowRunComplete -= onFlowStop;
return new FlowResult(this.Guid, context, result); return new FlowResult(this.Guid, context, result);
} }
@@ -253,6 +257,10 @@ namespace Serein.NodeFlow.Model
{ {
public static DateTime GetNow() => DateTime.Now; public static DateTime GetNow() => DateTime.Now;
public static int Add(int Left, int Right)
{
return Left + Right;
}
#region #region
public static bool BoolOf(object value) public static bool BoolOf(object value)

View File

@@ -87,9 +87,11 @@ namespace Serein.Script
public static Type EvaluateType(Type leftType, string op, Type rightType) public static Type EvaluateType(Type leftType, string op, Type rightType)
{ {
if (leftType == null || rightType == null) if (leftType == null || rightType == null)
throw new ArgumentNullException("操作数类型不能为 null"); throw new ArgumentNullException("操作数类型不能为 null");
// 字符串拼接 // 字符串拼接
if (op == "+" && (leftType == typeof(string) || rightType == typeof(string))) if (op == "+" && (leftType == typeof(string) || rightType == typeof(string)))
return typeof(string); return typeof(string);

View File

@@ -0,0 +1,51 @@
using Serein.Library.Api;
namespace Serein.Script
{
/// <summary>
/// 脚本运行上下文
/// </summary>
public interface IScriptInvokeContext
{
/// <summary>
/// 脚本运行的流程上下文,包含了流程上下文和变量等信息
/// </summary>
IDynamicContext FlowContext { get; }
/// <summary>
/// 是否该退出了(由外部发出停止信号)
/// </summary>
bool IsReturn { get; }
/// <summary>
/// 是否需要提前返回(用于脚本中提前结束)
/// </summary>
bool IsNeedReturn { get; set; }
/// <summary>
/// 是否严格检查 Null 值 (禁止使用 Null
/// </summary>
bool IsCheckNullValue { get; set; }
/// <summary>
/// 获取变量的值
/// </summary>
/// <param name="varName"></param>
/// <returns></returns>
object GetVarValue(string varName);
/// <summary>
/// 设置变量的值
/// </summary>
/// <param name="varName"></param>
/// <param name="value"></param>
/// <returns></returns>
bool SetVarValue(string varName, object value);
/// <summary>
/// 结束调用
/// </summary>
/// <returns></returns>
void OnExit();
}
}

View File

@@ -15,13 +15,14 @@ namespace Serein.Script.Node
/// <summary> /// <summary>
/// 变量名称 /// 变量名称
/// </summary> /// </summary>
public string Variable { get; } //public string Variable { get; }
public ASTNode Target { get; }
/// <summary> /// <summary>
/// 对应的节点 /// 对应的节点
/// </summary> /// </summary>
public ASTNode Value { get; } public ASTNode Value { get; }
public AssignmentNode(string variable, ASTNode value) => (Variable, Value) = (variable, value); public AssignmentNode(ASTNode targetObject, ASTNode value) => (Target, Value) = (targetObject, value);
} }

View File

@@ -12,8 +12,19 @@ namespace Serein.Script.Node
public class BinaryOperationNode : ASTNode public class BinaryOperationNode : ASTNode
{ {
/// <summary>
/// 左元
/// </summary>
public ASTNode Left { get; } public ASTNode Left { get; }
/// <summary>
/// 操作符(布尔运算符 > 比较运算符 > 加减乘除
/// </summary>
public string Operator { get; } public string Operator { get; }
/// <summary>
/// 右元
/// </summary>
public ASTNode Right { get; } public ASTNode Right { get; }
public BinaryOperationNode(ASTNode left, string op, ASTNode right) public BinaryOperationNode(ASTNode left, string op, ASTNode right)

View File

@@ -11,8 +11,17 @@ namespace Serein.Script.Node
/// </summary> /// </summary>
public class ClassTypeDefinitionNode : ASTNode public class ClassTypeDefinitionNode : ASTNode
{ {
[Obsolete("此属性已经过时,可能在下一个版本中移除", false)]
public bool IsOverlay { get; set; } public bool IsOverlay { get; set; }
/// <summary>
/// 类名称
/// </summary>
public string ClassName { get; } public string ClassName { get; }
/// <summary>
/// 字段名称及字段类型
/// </summary>
public Dictionary<string, Type> Fields { get; } public Dictionary<string, Type> Fields { get; }
public ClassTypeDefinitionNode(Dictionary<string, Type> fields, string className, bool isOverlay) public ClassTypeDefinitionNode(Dictionary<string, Type> fields, string className, bool isOverlay)

View File

@@ -11,12 +11,19 @@ namespace Serein.Script.Node
/// </summary> /// </summary>
public class CollectionIndexNode : ASTNode public class CollectionIndexNode : ASTNode
{ {
public ASTNode TargetValue { get; } /// <summary>
public ASTNode IndexValue { get; } /// 集合来源
public CollectionIndexNode(ASTNode collectionValue,ASTNode indexValue) /// </summary>
public ASTNode Collection { get; }
/// <summary>
/// 索引来源
/// </summary>
public ASTNode Index { get; }
public CollectionIndexNode(ASTNode TargetValue,ASTNode indexValue)
{ {
this.TargetValue = collectionValue; this.Collection = TargetValue;
this.IndexValue = indexValue; this.Index = indexValue;
} }
} }
} }

View File

@@ -11,7 +11,14 @@ namespace Serein.Script.Node
/// </summary> /// </summary>
public class FunctionCallNode : ASTNode public class FunctionCallNode : ASTNode
{ {
/// <summary>
/// 方法名称
/// </summary>
public string FunctionName { get; } public string FunctionName { get; }
/// <summary>
/// 参数来源
/// </summary>
public List<ASTNode> Arguments { get; } public List<ASTNode> Arguments { get; }
public FunctionCallNode(string functionName, List<ASTNode> arguments) public FunctionCallNode(string functionName, List<ASTNode> arguments)

View File

@@ -11,6 +11,9 @@ namespace Serein.Script.Node
/// </summary> /// </summary>
public class IdentifierNode : ASTNode public class IdentifierNode : ASTNode
{ {
/// <summary>
/// 定义的名称
/// </summary>
public string Name { get; } public string Name { get; }
public IdentifierNode(string name) => Name = name; public IdentifierNode(string name) => Name = name;
} }

View File

@@ -11,8 +11,19 @@ namespace Serein.Script.Node
/// </summary> /// </summary>
public class IfNode : ASTNode public class IfNode : ASTNode
{ {
/// <summary>
/// 条件来源
/// </summary>
public ASTNode Condition { get; } public ASTNode Condition { get; }
/// <summary>
/// 条件为 true 时所执行的语句
/// </summary>
public List<ASTNode> TrueBranch { get; } public List<ASTNode> TrueBranch { get; }
/// <summary>
/// 条件为 false 时所执行的语句
/// </summary>
public List<ASTNode> FalseBranch { get; } public List<ASTNode> FalseBranch { get; }
public IfNode(ASTNode condition, List<ASTNode> trueBranch, List<ASTNode> falseBranch) public IfNode(ASTNode condition, List<ASTNode> trueBranch, List<ASTNode> falseBranch)
=> (Condition, TrueBranch, FalseBranch) = (condition, trueBranch, falseBranch); => (Condition, TrueBranch, FalseBranch) = (condition, trueBranch, falseBranch);

View File

@@ -12,12 +12,12 @@ namespace Serein.Script.Node
public class MemberAccessNode : ASTNode public class MemberAccessNode : ASTNode
{ {
/// <summary> /// <summary>
/// 对象token /// 对象来源
/// </summary> /// </summary>
public ASTNode Object { get; } public ASTNode Object { get; }
/// <summary> /// <summary>
/// 成员名称 /// 对象中要获取的成员名称
/// </summary> /// </summary>
public string MemberName { get; } public string MemberName { get; }

View File

@@ -12,11 +12,12 @@ namespace Serein.Script.Node
public class MemberAssignmentNode : ASTNode public class MemberAssignmentNode : ASTNode
{ {
/// <summary> /// <summary>
/// 作用的对象 /// 对象来源
/// </summary> /// </summary>
public ASTNode Object { get; } public ASTNode Object { get; }
/// <summary> /// <summary>
/// 赋值的成员(属性/字段)名称 /// 对象中要赋值的成员名称
/// </summary> /// </summary>
public string MemberName { get; } public string MemberName { get; }
/// <summary> /// <summary>

View File

@@ -12,17 +12,17 @@ namespace Serein.Script.Node
public class MemberFunctionCallNode : ASTNode public class MemberFunctionCallNode : ASTNode
{ {
/// <summary> /// <summary>
/// 需要被调用的对象 /// 对象来源
/// </summary> /// </summary>
public ASTNode Object { get; } public ASTNode Object { get; }
/// <summary> /// <summary>
/// 调用的方法名称 /// 对象中要调用的方法名称
/// </summary> /// </summary>
public string FunctionName { get; } public string FunctionName { get; }
/// <summary> /// <summary>
/// 方法参数 /// 方法参数来源
/// </summary> /// </summary>
public List<ASTNode> Arguments { get; } public List<ASTNode> Arguments { get; }

View File

@@ -11,7 +11,14 @@ namespace Serein.Script.Node
/// </summary> /// </summary>
public class ObjectInstantiationNode : ASTNode public class ObjectInstantiationNode : ASTNode
{ {
/// <summary>
/// 类型名称
/// </summary>
public string TypeName { get; } public string TypeName { get; }
/// <summary>
/// 构造方法的参数来源
/// </summary>
public List<ASTNode> Arguments { get; } public List<ASTNode> Arguments { get; }
public ObjectInstantiationNode(string typeName, List<ASTNode> arguments) public ObjectInstantiationNode(string typeName, List<ASTNode> arguments)
{ {

View File

@@ -0,0 +1,15 @@
namespace Serein.Script.Node
{
public class ObjectMemberExpressionNode : ASTNode
{
/// <summary>
/// 对象成员(嵌套获取)
/// </summary>
public ASTNode Value { get; }
public ObjectMemberExpressionNode(ASTNode value)
{
this.Value = value;
}
}
}

View File

@@ -11,6 +11,9 @@ namespace Serein.Script.Node
/// </summary> /// </summary>
public class ProgramNode : ASTNode public class ProgramNode : ASTNode
{ {
/// <summary>
/// 程序可执行的语句
/// </summary>
public List<ASTNode> Statements { get; } public List<ASTNode> Statements { get; }
public ProgramNode(List<ASTNode> statements) public ProgramNode(List<ASTNode> statements)

View File

@@ -11,6 +11,9 @@ namespace Serein.Script.Node
/// </summary> /// </summary>
public class ReturnNode : ASTNode public class ReturnNode : ASTNode
{ {
/// <summary>
/// 返回值来源
/// </summary>
public ASTNode Value { get; } public ASTNode Value { get; }
public ReturnNode(ASTNode returnNode) public ReturnNode(ASTNode returnNode)

View File

@@ -11,7 +11,14 @@ namespace Serein.Script.Node
/// </summary> /// </summary>
public class WhileNode : ASTNode public class WhileNode : ASTNode
{ {
/// <summary>
/// 循环条件值来源
/// </summary>
public ASTNode Condition { get; } public ASTNode Condition { get; }
/// <summary>
/// 循环中语句块
/// </summary>
public List<ASTNode> Body { get; } public List<ASTNode> Body { get; }
public WhileNode(ASTNode condition, List<ASTNode> body) => (Condition, Body) = (condition, body); public WhileNode(ASTNode condition, List<ASTNode> body) => (Condition, Body) = (condition, body);
} }

View File

@@ -0,0 +1,19 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Serein.Library.Api;
using Serein.Script.Node;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Serein.Script
{
internal static class NodeInterpreterExtension
{
/*public Task Execution(this MemberAccessNode MemberAccessNode, IScriptFlowApi scriptFlowApi)
{
}*/
}
}

View File

@@ -0,0 +1,79 @@
using Serein.Library.Api;
namespace Serein.Script
{
public class ScriptInvokeContext : IScriptInvokeContext
{
public ScriptInvokeContext(IDynamicContext dynamicContext)
{
FlowContext = dynamicContext;
}
public IDynamicContext FlowContext{ get; }
/// <summary>
/// 定义的变量
/// </summary>
private Dictionary<string, object> _variables = new Dictionary<string, object>();
/// <summary>
/// 取消令牌源,用于控制脚本的执行
/// </summary>
private CancellationTokenSource _tokenSource = new CancellationTokenSource();
/// <summary>
/// 是否该退出了
/// </summary>
public bool IsReturn => _tokenSource.IsCancellationRequested;
/// <summary>
/// 是否严格检查 Null 值 (禁止使用 Null
/// </summary>
public bool IsCheckNullValue { get; set; }
/// <summary>
/// 是否需要提前返回(用于脚本中提前结束)
/// </summary>
public bool IsNeedReturn { get; set; }
object IScriptInvokeContext.GetVarValue(string varName)
{
_variables.TryGetValue(varName, out var value);
return value;
}
bool IScriptInvokeContext.SetVarValue(string varName, object? value)
{
if (!_variables.TryAdd(varName, value))
{
_variables[varName] = value;
}
return true;
}
void IScriptInvokeContext.OnExit()
{
// 清理脚本中加载的非托管资源
foreach (var nodeObj in _variables.Values)
{
if (nodeObj is not null)
{
if (typeof(IDisposable).IsAssignableFrom(nodeObj?.GetType()) && nodeObj is IDisposable disposable)
{
disposable?.Dispose();
}
}
else
{
}
}
_tokenSource.Cancel();
_variables.Clear();
}
}
}

View File

@@ -0,0 +1,16 @@
using Serein.Script.Node;
namespace Serein.Script
{
public sealed class SereinSciptException : Exception
{
//public ASTNode Node { get; }
public override string Message { get; }
public SereinSciptException(ASTNode node, string message)
{
//this.Node = node;
Message = $"异常信息 : {message} ,代码在第{node.Row}行: {node.Code.Trim()}";
}
}
}

View File

@@ -1,6 +1,5 @@
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Serein.Library; using Serein.Library;
using Serein.Library.Api;
using Serein.Library.Utils; using Serein.Library.Utils;
using Serein.Script.Node; using Serein.Script.Node;
using System.ComponentModel.Design; using System.ComponentModel.Design;
@@ -11,131 +10,6 @@ using System.Xml.Linq;
namespace Serein.Script namespace Serein.Script
{ {
public sealed class SereinSciptException : Exception
{
//public ASTNode Node { get; }
public override string Message { get; }
public SereinSciptException(ASTNode node, string message)
{
//this.Node = node;
Message = $"异常信息 : {message} ,代码在第{node.Row}行: {node.Code.Trim()}";
}
}
/// <summary>
/// 脚本运行上下文
/// </summary>
public interface IScriptInvokeContext
{
/// <summary>
/// 脚本运行的流程上下文,包含了流程上下文和变量等信息
/// </summary>
IDynamicContext FlowContext { get; }
/// <summary>
/// 是否该退出了
/// </summary>
bool IsReturn { get; }
/// <summary>
/// 是否严格检查 Null 值 (禁止使用 Null
/// </summary>
bool IsCheckNullValue { get; set; }
/// <summary>
/// 获取变量的值
/// </summary>
/// <param name="varName"></param>
/// <returns></returns>
object GetVarValue(string varName);
/// <summary>
/// 设置变量的值
/// </summary>
/// <param name="varName"></param>
/// <param name="value"></param>
/// <returns></returns>
bool SetVarValue(string varName, object value);
/// <summary>
/// 结束调用
/// </summary>
/// <returns></returns>
void OnExit();
}
public class ScriptInvokeContext : IScriptInvokeContext
{
public ScriptInvokeContext(IDynamicContext dynamicContext)
{
FlowContext = dynamicContext;
}
public IDynamicContext FlowContext{ get; }
/// <summary>
/// 定义的变量
/// </summary>
private Dictionary<string, object> _variables = new Dictionary<string, object>();
/// <summary>
/// 取消令牌源,用于控制脚本的执行
/// </summary>
private CancellationTokenSource _tokenSource = new CancellationTokenSource();
/// <summary>
/// 是否该退出了
/// </summary>
public bool IsReturn => _tokenSource.IsCancellationRequested;
/// <summary>
/// 是否严格检查 Null 值 (禁止使用 Null
/// </summary>
public bool IsCheckNullValue { get; set; }
object IScriptInvokeContext.GetVarValue(string varName)
{
_variables.TryGetValue(varName, out var value);
return value;
}
bool IScriptInvokeContext.SetVarValue(string varName, object? value)
{
if (!_variables.TryAdd(varName, value))
{
_variables[varName] = value;
}
return true;
}
void IScriptInvokeContext.OnExit()
{
// 清理脚本中加载的非托管资源
foreach (var nodeObj in _variables.Values)
{
if (nodeObj is not null)
{
if (typeof(IDisposable).IsAssignableFrom(nodeObj?.GetType()) && nodeObj is IDisposable disposable)
{
disposable?.Dispose();
}
}
else
{
}
}
_tokenSource.Cancel();
_variables.Clear();
}
}
/// <summary> /// <summary>
/// 脚本解释器,负责解析和执行 Serein 脚本 /// 脚本解释器,负责解析和执行 Serein 脚本
@@ -147,6 +21,9 @@ namespace Serein.Script
/// 挂载的函数 /// 挂载的函数
/// </summary> /// </summary>
private static Dictionary<string, DelegateDetails> _functionTable = new Dictionary<string, DelegateDetails>(); private static Dictionary<string, DelegateDetails> _functionTable = new Dictionary<string, DelegateDetails>();
private static Dictionary<string, MethodInfo> _functionInfoTable = new Dictionary<string, MethodInfo>();
public static Dictionary<string, MethodInfo> FunctionInfoTable { get { return _functionInfoTable; } }
/// <summary> /// <summary>
/// 挂载的函数调用的对象(用于函数需要实例才能调用的场景) /// 挂载的函数调用的对象(用于函数需要实例才能调用的场景)
@@ -158,6 +35,12 @@ namespace Serein.Script
/// </summary> /// </summary>
private Dictionary<string, Type> _classDefinition = new Dictionary<string, Type>(); private Dictionary<string, Type> _classDefinition = new Dictionary<string, Type>();
/// <summary>
/// 类型分析器
/// </summary>
private SereinScriptTypeAnalysis typeAnalysis;
/// <summary> /// <summary>
/// 挂载静态函数 /// 挂载静态函数
/// </summary> /// </summary>
@@ -166,6 +49,7 @@ namespace Serein.Script
public static void AddStaticFunction(string functionName, MethodInfo methodInfo) public static void AddStaticFunction(string functionName, MethodInfo methodInfo)
{ {
_functionTable[functionName] = new DelegateDetails(methodInfo); _functionTable[functionName] = new DelegateDetails(methodInfo);
_functionInfoTable[functionName] = methodInfo;
} }
@@ -216,19 +100,26 @@ namespace Serein.Script
} }
} }
/// <summary>
/// 设置类型分析器
/// </summary>
/// <param name="typeAnalysis"></param>
public void SetTypeAnalysis(SereinScriptTypeAnalysis typeAnalysis)
{
this.typeAnalysis = typeAnalysis;
}
/// <summary> /// <summary>
/// 入口节点 /// 入口节点
/// </summary> /// </summary>
/// <param name="programNode"></param> /// <param name="programNode"></param>
/// <returns></returns> /// <returns></returns>
private async Task<object?> ExecutionProgramNodeAsync(IScriptInvokeContext context, ProgramNode programNode) private async Task<object?> ExecutionProgramNodeAsync(IScriptInvokeContext context,ProgramNode programNode)
{ {
// 加载变量 // 加载变量
ASTNode statement = null; ASTNode statement = null;
try try
{ {
// 遍历 ProgramNode 中的所有语句并执行它们 // 遍历 ProgramNode 中的所有语句并执行它们
for (int index = 0; index < programNode.Statements.Count; index++) for (int index = 0; index < programNode.Statements.Count; index++)
{ {
@@ -240,7 +131,11 @@ namespace Serein.Script
} }
else else
{ {
await InterpretAsync(context, statement); var result = await InterpretAsync(context, statement);
if (context.IsNeedReturn)
{
return result;
}
} }
} }
return null; return null;
@@ -268,10 +163,10 @@ namespace Serein.Script
return; return;
} }
var isOverlay = true; // classTypeDefinitionNode.IsOverlay; //var isOverlay = true; // classTypeDefinitionNode.IsOverlay;
var type = DynamicObjectHelper.CreateTypeWithProperties(classTypeDefinitionNode.Fields, classTypeDefinitionNode.ClassName, isOverlay); // 覆盖 var type = DynamicObjectHelper.CreateTypeWithProperties(classTypeDefinitionNode.Fields, classTypeDefinitionNode.ClassName); // 覆盖
classTypeDefinitionNode.IsOverlay = false; // 已经加载过,则不再覆盖 //classTypeDefinitionNode.IsOverlay = false; // 已经加载过,则不再覆盖
_classDefinition[classTypeDefinitionNode.ClassName] = type; // 定义对象 _classDefinition[classTypeDefinitionNode.ClassName] = type; // 定义对象
} }
@@ -281,7 +176,7 @@ namespace Serein.Script
/// <param name="ifNode"></param> /// <param name="ifNode"></param>
/// <returns></returns> /// <returns></returns>
/// <exception cref="Exception"></exception> /// <exception cref="Exception"></exception>
private async Task ExecutionIfNodeAsync(IScriptInvokeContext context, IfNode ifNode) private async Task<object?> ExecutionIfNodeAsync(IScriptInvokeContext context, IfNode ifNode)
{ {
var result = await EvaluateAsync(context, ifNode.Condition) ?? throw new SereinSciptException(ifNode, $"条件语句返回了 null"); var result = await EvaluateAsync(context, ifNode.Condition) ?? throw new SereinSciptException(ifNode, $"条件语句返回了 null");
@@ -290,20 +185,30 @@ namespace Serein.Script
throw new SereinSciptException(ifNode, "条件语句返回值不为 bool 类型"); throw new SereinSciptException(ifNode, "条件语句返回值不为 bool 类型");
} }
if (condition) var branchNodes = condition ? ifNode.TrueBranch : ifNode.FalseBranch;
if(branchNodes is null || branchNodes.Count < 1)
{ {
foreach (var trueNode in ifNode.TrueBranch) return null;
{
await InterpretAsync(context, trueNode);
}
} }
else else
{ {
foreach (var falseNode in ifNode.FalseBranch)
foreach (var branchNode in branchNodes)
{ {
await InterpretAsync(context,falseNode); if (branchNode is ReturnNode) // 遇到 Return 语句 提前退出
{
var reulst = await EvaluateAsync(context, branchNode);
context.IsNeedReturn = true;
return reulst;
}
else
{
await InterpretAsync(context, branchNode);
}
} }
return null;
} }
} }
/// <summary> /// <summary>
@@ -312,14 +217,14 @@ namespace Serein.Script
/// <param name="whileNode"></param> /// <param name="whileNode"></param>
/// <returns></returns> /// <returns></returns>
/// <exception cref="Exception"></exception> /// <exception cref="Exception"></exception>
private async Task ExectutionWhileNodeAsync(IScriptInvokeContext context, WhileNode whileNode) private async Task<object?> ExectutionWhileNodeAsync(IScriptInvokeContext context, WhileNode whileNode)
{ {
while (true) while (true)
{ {
if (context.IsReturn) // 停止流程 if (context.IsReturn) // 停止流程
{ {
return; throw new SereinSciptException(whileNode, $"while循环已由外部主动停止");
} }
var result = await EvaluateAsync(context, whileNode.Condition) ?? throw new SereinSciptException(whileNode, $"条件语句返回了 null"); var result = await EvaluateAsync(context, whileNode.Condition) ?? throw new SereinSciptException(whileNode, $"条件语句返回了 null");
if (result is not bool condition) if (result is not bool condition)
@@ -330,11 +235,22 @@ namespace Serein.Script
{ {
break; break;
} }
foreach(var node in whileNode.Body) foreach(var branchNode in whileNode.Body)
{ {
await InterpretAsync(context, node); if (branchNode is ReturnNode) // 遇到 Return 语句 提前退出
{
var reulst = await EvaluateAsync(context, branchNode);
context.IsNeedReturn = true;
return reulst;
}
else
{
await InterpretAsync(context, branchNode);
}
//await InterpretAsync(context, node);
} }
} }
return null;
} }
/// <summary> /// <summary>
@@ -344,13 +260,28 @@ namespace Serein.Script
/// <returns></returns> /// <returns></returns>
private async Task ExecutionAssignmentNodeAsync(IScriptInvokeContext context, AssignmentNode assignmentNode) private async Task ExecutionAssignmentNodeAsync(IScriptInvokeContext context, AssignmentNode assignmentNode)
{ {
var tmp = await EvaluateAsync(context, assignmentNode.Value); if(assignmentNode.Target is IdentifierNode identifierNode)
if(tmp is not null) {
var value = await EvaluateAsync(context, assignmentNode.Value);
if (value is not null)
{
context.SetVarValue(identifierNode.Name, value);
}
}
else
{ {
context.SetVarValue(assignmentNode.Variable, tmp);
} }
/*var targetObject = await EvaluateAsync(context, assignmentNode.TargetNode);
var value = await EvaluateAsync(context, assignmentNode.Value);
if(value is not null)
{
context.SetVarValue(targetObject, value);
}*/
} }
private async Task<object> InterpretFunctionCallAsync(IScriptInvokeContext context, FunctionCallNode functionCallNode) private async Task<object> InterpretFunctionCallAsync(IScriptInvokeContext context, FunctionCallNode functionCallNode)
{ {
if (functionCallNode.FunctionName.Equals("GetFlowContext", StringComparison.OrdinalIgnoreCase)) if (functionCallNode.FunctionName.Equals("GetFlowContext", StringComparison.OrdinalIgnoreCase))
@@ -427,16 +358,18 @@ namespace Serein.Script
case AssignmentNode assignment: // 出现在 = 右侧的表达式 case AssignmentNode assignment: // 出现在 = 右侧的表达式
await ExecutionAssignmentNodeAsync(context, assignment); await ExecutionAssignmentNodeAsync(context, assignment);
break; break;
case ObjectMemberExpressionNode objectMemberExpressionNode:
break;
case MemberAssignmentNode memberAssignmentNode: // 设置对象属性 case MemberAssignmentNode memberAssignmentNode: // 设置对象属性
await SetMemberValue(context, memberAssignmentNode); await SetMemberValue(context, memberAssignmentNode);
break; break;
case MemberFunctionCallNode memberFunctionCallNode: // 对象方法调用 case MemberFunctionCallNode memberFunctionCallNode: // 对象方法调用
return await CallMemberFunction(context, memberFunctionCallNode); return await CallMemberFunction(context, memberFunctionCallNode);
case IfNode ifNode: // 执行 if...else... 语句块 case IfNode ifNode: // 执行 if...else... 语句块
await ExecutionIfNodeAsync(context, ifNode); return await ExecutionIfNodeAsync(context, ifNode);
break; break;
case WhileNode whileNode: // 循环语句块 case WhileNode whileNode: // 循环语句块
await ExectutionWhileNodeAsync(context, whileNode); return await ExectutionWhileNodeAsync(context, whileNode);
break; break;
case FunctionCallNode functionCallNode: // 方法调用节点 case FunctionCallNode functionCallNode: // 方法调用节点
return await InterpretFunctionCallAsync(context, functionCallNode); return await InterpretFunctionCallAsync(context, functionCallNode);
@@ -517,13 +450,13 @@ namespace Serein.Script
case MemberFunctionCallNode memberFunctionCallNode: // 对象方法调用 case MemberFunctionCallNode memberFunctionCallNode: // 对象方法调用
return await CallMemberFunction(context, memberFunctionCallNode); return await CallMemberFunction(context, memberFunctionCallNode);
case MemberAccessNode memberAccessNode: // 对象成员访问 case MemberAccessNode memberAccessNode: // 对象成员访问
return await GetValue(context, memberAccessNode); return await GetMemberValue(context, memberAccessNode);
case CollectionIndexNode collectionIndexNode: case CollectionIndexNode collectionIndexNode:
return await GetCollectionValue(context, collectionIndexNode); return await GetCollectionValue(context, collectionIndexNode);
case ReturnNode returnNode: // 返回内容 case ReturnNode returnNode: // 返回内容
return await EvaluateAsync(context, returnNode.Value); // 直接返回响应的内容 return await EvaluateAsync(context, returnNode.Value); // 直接返回响应的内容
//case ObjectInstantiationNode objectInstantiationNode: // 返回内容 case ObjectMemberExpressionNode objectMemberExpressionNode: // 对象链式表达式
return await EvaluateAsync(context, objectMemberExpressionNode.Value);
default: default:
throw new SereinSciptException(node, $"解释器 EvaluateAsync() 未实现{node}节点行为"); throw new SereinSciptException(node, $"解释器 EvaluateAsync() 未实现{node}节点行为");
} }
@@ -611,8 +544,24 @@ namespace Serein.Script
} }
else else
{ {
var convertedValue = Convert.ChangeType(value, lastProperty.PropertyType); if(value is null)
lastProperty.SetValue(target, convertedValue); {
lastProperty.SetValue(target, null);
return;
}
var valueTtpe = value.GetType();
if (lastProperty.PropertyType.IsAssignableFrom(valueTtpe))
{
lastProperty.SetValue(target, value);
}
else if (lastProperty.PropertyType.FullName == valueTtpe.FullName)
{
lastProperty.SetValue(target, value);
}
else {
throw new SereinSciptException(memberAssignmentNode, $"对象成员赋值时类型异常:\"{memberAssignmentNode.MemberName}\"");
}
//var convertedValue = Convert.ChangeType(value, );
} }
} }
@@ -622,7 +571,7 @@ namespace Serein.Script
/// <param name="memberAccessNode"></param> /// <param name="memberAccessNode"></param>
/// <returns></returns> /// <returns></returns>
/// <exception cref="SereinSciptException"></exception> /// <exception cref="SereinSciptException"></exception>
public async Task<object?> GetValue(IScriptInvokeContext context, MemberAccessNode memberAccessNode) public async Task<object?> GetMemberValue(IScriptInvokeContext context, MemberAccessNode memberAccessNode)
{ {
var target = await EvaluateAsync(context, memberAccessNode.Object); var target = await EvaluateAsync(context, memberAccessNode.Object);
var lastMember = memberAccessNode.MemberName; var lastMember = memberAccessNode.MemberName;
@@ -654,7 +603,7 @@ namespace Serein.Script
/// <exception cref="SereinSciptException"></exception> /// <exception cref="SereinSciptException"></exception>
public async Task<object?> GetCollectionValue(IScriptInvokeContext context, CollectionIndexNode collectionIndexNode) public async Task<object?> GetCollectionValue(IScriptInvokeContext context, CollectionIndexNode collectionIndexNode)
{ {
var target = await EvaluateAsync(context, collectionIndexNode.TargetValue); // 获取对象 var target = await EvaluateAsync(context, collectionIndexNode.Collection); // 获取对象
if (target is null) if (target is null)
{ {
throw new ArgumentNullException($"解析{collectionIndexNode}节点时TargetValue返回空。"); throw new ArgumentNullException($"解析{collectionIndexNode}节点时TargetValue返回空。");
@@ -669,7 +618,7 @@ namespace Serein.Script
var method = targetType.GetMethod("get_Item", BindingFlags.Public | BindingFlags.Instance); var method = targetType.GetMethod("get_Item", BindingFlags.Public | BindingFlags.Instance);
if (method is not null) if (method is not null)
{ {
var key = await EvaluateAsync(context, collectionIndexNode.IndexValue); // 获取索引值; var key = await EvaluateAsync(context, collectionIndexNode.Index); // 获取索引值;
var result = method.Invoke(target, new object[] { key }); var result = method.Invoke(target, new object[] { key });
return result; return result;
} }
@@ -678,7 +627,7 @@ namespace Serein.Script
#region #region
else else
{ {
var indexValue = await EvaluateAsync(context, collectionIndexNode.IndexValue); // 获取索引值 var indexValue = await EvaluateAsync(context, collectionIndexNode.Index); // 获取索引值
object? result; object? result;
if (indexValue is int index) if (indexValue is int index)
{ {
@@ -702,6 +651,10 @@ namespace Serein.Script
result = list[index]; result = list[index];
return result; return result;
} }
else if (target is string chars)
{
return chars[index];
}
else else
{ {
throw new ArgumentException($"解析{collectionIndexNode}节点时,左值并非有效集合。"); throw new ArgumentException($"解析{collectionIndexNode}节点时,左值并非有效集合。");
@@ -717,30 +670,58 @@ namespace Serein.Script
/// <summary> /// <summary>
/// 缓存method委托 /// 缓存method委托
/// </summary> /// </summary>
private Dictionary<string, DelegateDetails> MethodToDelegateCaches { get; } = new Dictionary<string, DelegateDetails>(); private Dictionary<long, DelegateDetails> MethodToDelegateCaches { get; } = new Dictionary<long, DelegateDetails>();
public async Task<object?> CallMemberFunction(IScriptInvokeContext context, MemberFunctionCallNode memberFunctionCallNode) public async Task<object?> CallMemberFunction(IScriptInvokeContext context, MemberFunctionCallNode memberFunctionCallNode)
{ {
var target = await EvaluateAsync(context, memberFunctionCallNode.Object); var target = await EvaluateAsync(context, memberFunctionCallNode.Object);
var lastMember = memberFunctionCallNode.FunctionName; var lastMember = memberFunctionCallNode.FunctionName;
if(lastMember == "ToUpper")
{
var methodInfo = target?.GetType().GetMethod(lastMember) ?? throw new SereinSciptException(memberFunctionCallNode, $"对象没有方法\"{memberFunctionCallNode.FunctionName}\""); }
if(!MethodToDelegateCaches.TryGetValue(methodInfo.Name, out DelegateDetails? delegateDetails)) MethodInfo? methodInfo = null;
if (memberFunctionCallNode.Arguments.Count == 0)
{
// 查询无参方法
methodInfo = target?.GetType().GetMethod(lastMember, []) ?? throw new SereinSciptException(memberFunctionCallNode, $"对象没有方法\"{memberFunctionCallNode.FunctionName}\"");
}
else
{
// 获取参数列表的类型
methodInfo = target?.GetType().GetMethod(lastMember) ?? throw new SereinSciptException(memberFunctionCallNode, $"对象没有方法\"{memberFunctionCallNode.FunctionName}\"");
}
/*Type[] paramTypes = new
{
}*/
if (!MethodToDelegateCaches.TryGetValue(methodInfo.MetadataToken, out DelegateDetails? delegateDetails))
{ {
delegateDetails = new DelegateDetails(methodInfo); delegateDetails = new DelegateDetails(methodInfo);
MethodToDelegateCaches[methodInfo.Name] = delegateDetails; MethodToDelegateCaches[methodInfo.MetadataToken] = delegateDetails;
} }
if(memberFunctionCallNode.Arguments.Count == 0)
var arguments = new object?[memberFunctionCallNode.Arguments.Count];
for (int i = 0; i < memberFunctionCallNode.Arguments.Count; i++)
{ {
ASTNode? arg = memberFunctionCallNode.Arguments[i]; var reuslt = await delegateDetails.InvokeAsync(target, []);
arguments[i] = await EvaluateAsync(context, arg); // 评估每个参数 return reuslt;
}
else
{
var arguments = new object?[memberFunctionCallNode.Arguments.Count];
for (int i = 0; i < memberFunctionCallNode.Arguments.Count; i++)
{
ASTNode? arg = memberFunctionCallNode.Arguments[i];
arguments[i] = await EvaluateAsync(context, arg); // 评估每个参数
}
var reuslt = await delegateDetails.InvokeAsync(target, arguments);
return reuslt;
} }
return await delegateDetails.InvokeAsync(target, arguments);
} }

View File

@@ -1,4 +1,5 @@
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using System.Net.Http.Headers;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Xml.Linq; using System.Xml.Linq;
using static System.Net.Mime.MediaTypeNames; using static System.Net.Mime.MediaTypeNames;
@@ -137,8 +138,6 @@ namespace Serein.Script
private int _index; private int _index;
private int _row ; private int _row ;
private int coreRangeStartIndex = 0;
/// <summary> /// <summary>
/// 关键字,防止声明为变量 /// 关键字,防止声明为变量
/// </summary> /// </summary>
@@ -160,16 +159,31 @@ namespace Serein.Script
} }
internal Token PeekToken() internal Token PeekToken(int count = 1)
{ {
if (count < 0) throw new Exception() ;
int currentIndex = _index; // 保存当前索引 int currentIndex = _index; // 保存当前索引
var currentRow = _row; // 保存当前行数 var currentRow = _row; // 保存当前行数
Token nextToken = NextToken(); // 获取下一个 token Token nextToken = new Token(); ;
for (var i = 0; i < count; i++)
{
nextToken = NextToken(); // 获取下一个 token
}
_index = currentIndex; // 恢复索引到当前位置 _index = currentIndex; // 恢复索引到当前位置
_row = currentRow; // 恢复到当前行数 _row = currentRow; // 恢复到当前行数
return nextToken; // 返回下一个 token return nextToken; // 返回下一个 token
} }
/// <summary>
/// 根据 token 重置Lexer
/// </summary>
/// <param name="token"></param>
public void SetToken(Token token)
{
this._row = token.Row;
this._index = token.StartIndex;
}
internal Token NextToken() internal Token NextToken()
{ {
@@ -194,6 +208,7 @@ namespace Serein.Script
{ {
return ReadString(); return ReadString();
} }
if (currentChar == '\'') if (currentChar == '\'')
{ {

View File

@@ -3,9 +3,11 @@ using Serein.Library;
using Serein.Library.Utils; using Serein.Library.Utils;
using Serein.Script.Node; using Serein.Script.Node;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions; using System.Linq.Expressions;
using System.Reflection; using System.Reflection;
using System.Text; using System.Text;
using System.Xml.Linq;
namespace Serein.Script namespace Serein.Script
{ {
@@ -30,8 +32,9 @@ namespace Serein.Script
/// 解析脚本并返回 AST抽象语法树根节点。 /// 解析脚本并返回 AST抽象语法树根节点。
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public ASTNode Parse() public ProgramNode Parse()
{ {
return Program(); return Program();
} }
@@ -43,7 +46,7 @@ namespace Serein.Script
/// 解析整个程序直到遇到文件结尾EOF为止。 /// 解析整个程序直到遇到文件结尾EOF为止。
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
private ASTNode Program() private ProgramNode Program()
{ {
Statements.Clear(); Statements.Clear();
while (_currentToken.Type != TokenType.EOF) while (_currentToken.Type != TokenType.EOF)
@@ -59,7 +62,6 @@ namespace Serein.Script
var programNode = new ProgramNode(Statements); var programNode = new ProgramNode(Statements);
programNode.SetTokenInfo(_currentToken); // 程序节点,包含所有解析的语句列表 programNode.SetTokenInfo(_currentToken); // 程序节点,包含所有解析的语句列表
SereinScriptTypeAnalysis typeAnalysis = new SereinScriptTypeAnalysis(programNode);
return programNode; return programNode;
/*if (astNode is ClassTypeDefinitionNode) /*if (astNode is ClassTypeDefinitionNode)
@@ -135,6 +137,7 @@ namespace Serein.Script
if (_currentToken.Type == TokenType.Null) if (_currentToken.Type == TokenType.Null)
{ {
// 处理 null 语句 // 处理 null 语句
return BooleanExpression();
return Expression(); return Expression();
} }
@@ -157,7 +160,254 @@ namespace Serein.Script
/// <returns></returns> /// <returns></returns>
private ASTNode ParseIdentifier() private ASTNode ParseIdentifier()
{ {
/*
localFunc();
obj.Func();
obj.Value = ...;
value = ...;
*/
var backupToken = _currentToken;
var tokenCount = 1;
var int_type = 0;
while (true)
{
var tempToken = _lexer.PeekToken(tokenCount++);
if (tempToken.Type == TokenType.Operator && tempToken.Value == "=")
{
var tempToken2 = _lexer.PeekToken(tokenCount);
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(int_type == 1) // 赋值 MemberAssignmentNode
{
var objectName = _currentToken.Value;
var objectNode = new IdentifierNode(objectName).SetTokenInfo(_currentToken); // 首先定义对象变量节点
var peekToken = _lexer.PeekToken();
if(peekToken.Type == TokenType.Operator && peekToken.Value == "=")
{
// 变量赋值
var valueNode = BooleanExpression();
var assignmentNode = new AssignmentNode(objectNode, valueNode).SetTokenInfo(_currentToken);
return assignmentNode;
}
else
{
_currentToken = _lexer.NextToken(); // 消耗对象名称
// 对象成员赋值
List<ASTNode> nodes = new List<ASTNode>(); // 表达对象成员路径的节点
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)
{
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; // 返回节点
break;
}
//_lexer.SetToken(peekToken); // 重置lexer
}
}
else
{
_currentToken = _lexer.NextToken();
}
/*if (_currentToken.Type == TokenType.Operator && _currentToken.Value == "=")
{
// 等号意味着左值语句结束
break;
}*/
}
/* var leftValueNodes = nodes;
List<ASTNode> rightValueNode = new List<ASTNode>(); // 表达对象成员路径的节点*/
}
}
else if (int_type == 2) // 方法调用
{
var taretNode = "";
}
else
{
}
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<ASTNode> nodes = new List<ASTNode>();
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(); var _tempToken = _lexer.PeekToken();
if (_tempToken.Type == TokenType.ParenthesisLeft) if (_tempToken.Type == TokenType.ParenthesisLeft)
@@ -168,6 +418,7 @@ namespace Serein.Script
else if (_tempToken.Type == TokenType.Dot) else if (_tempToken.Type == TokenType.Dot)
{ {
// 对象成员的获取 // 对象成员的获取
return ParseMemberAccessOrAssignment(); return ParseMemberAccessOrAssignment();
} }
else if (_tempToken.Type == TokenType.SquareBracketsLeft) else if (_tempToken.Type == TokenType.SquareBracketsLeft)
@@ -213,7 +464,8 @@ namespace Serein.Script
{ {
//_currentToken = _lexer.NextToken(); // 消耗操作符 //_currentToken = _lexer.NextToken(); // 消耗操作符
//_currentToken = _lexer.NextToken(); // 消耗操作符 //_currentToken = _lexer.NextToken(); // 消耗操作符
valueNode = Expression(); valueNode = BooleanExpression();
//valueNode = Expression();
} }
else if (_tempToken.Type == TokenType.ParenthesisLeft) else if (_tempToken.Type == TokenType.ParenthesisLeft)
{ {
@@ -224,9 +476,11 @@ namespace Serein.Script
else else
{ {
// 解析赋值右边的字面量表达式 // 解析赋值右边的字面量表达式
valueNode = Expression(); valueNode = BooleanExpression();
//valueNode = Expression();
} }
return new AssignmentNode(variableName, valueNode).SetTokenInfo(_currentToken); var variableNode = new IdentifierNode(variableName).SetTokenInfo(_currentToken);
return new AssignmentNode(variableNode, valueNode).SetTokenInfo(_currentToken);
} }
if (_peekToken.Type == TokenType.Dot) if (_peekToken.Type == TokenType.Dot)
{ {
@@ -253,7 +507,7 @@ namespace Serein.Script
{ {
_currentToken = _lexer.NextToken(); // Consume "let" _currentToken = _lexer.NextToken(); // Consume "let"
string variable = _currentToken.Value.ToString(); // 变量名称 string variableName = _currentToken.Value.ToString(); // 变量名称
_currentToken = _lexer.NextToken(); // Consume identifier _currentToken = _lexer.NextToken(); // Consume identifier
ASTNode value; ASTNode value;
AssignmentNode assignmentNode; AssignmentNode assignmentNode;
@@ -261,7 +515,8 @@ namespace Serein.Script
{ {
// 定义一个变量,初始值为 null // 定义一个变量,初始值为 null
value = new NullNode(); value = new NullNode();
assignmentNode = new AssignmentNode(variable, value); // 生成node var variableNode = new IdentifierNode(variableName).SetTokenInfo(_currentToken);
assignmentNode = new AssignmentNode(variableNode, value); // 生成node
assignmentNode.SetTokenInfo(_currentToken); // 设置token信息 assignmentNode.SetTokenInfo(_currentToken); // 设置token信息
} }
else else
@@ -272,8 +527,10 @@ namespace Serein.Script
throw new Exception("Expected '=' after variable name"); throw new Exception("Expected '=' after variable name");
_currentToken = _lexer.NextToken(); // 消耗操作符(“=”) _currentToken = _lexer.NextToken(); // 消耗操作符(“=”)
var nodeToken = _currentToken; var nodeToken = _currentToken;
value = Expression(); // 解析获取赋值表达式 value = BooleanExpression(); // 解析获取赋值表达式
assignmentNode = new AssignmentNode(variable, value); // 生成node //value = Expression(); // 解析获取赋值表达式
var variableNode = new IdentifierNode(variableName).SetTokenInfo(_currentToken);
assignmentNode = new AssignmentNode(variableNode, value); // 生成node
assignmentNode.SetTokenInfo(nodeToken); // 设置token信息 assignmentNode.SetTokenInfo(nodeToken); // 设置token信息
_currentToken = _lexer.NextToken(); // 消耗分号 _currentToken = _lexer.NextToken(); // 消耗分号
} }
@@ -316,7 +573,10 @@ namespace Serein.Script
while (_currentToken.Type != TokenType.BraceRight) while (_currentToken.Type != TokenType.BraceRight)
{ {
// 获取类字段定义 // 获取类字段定义
var fieldType = _currentToken.Value.ToString().ToTypeOfString(); // 获取字段的类型 var fieldTypeName = _currentToken.Value.ToString();
var dynamicType = DynamicObjectHelper.GetCacheType(fieldTypeName);
var fieldType = dynamicType ?? _currentToken.Value.ToString().ToTypeOfString(); // 获取字段的类型
_currentToken = _lexer.NextToken(); // 消耗类型 _currentToken = _lexer.NextToken(); // 消耗类型
var fieldName = _currentToken.Value.ToString(); // 获取定义的类名 var fieldName = _currentToken.Value.ToString(); // 获取定义的类名
_currentToken = _lexer.NextToken(); // 消耗字段名称 _currentToken = _lexer.NextToken(); // 消耗字段名称
@@ -334,7 +594,9 @@ namespace Serein.Script
} }
_currentToken = _lexer.NextToken(); // 消耗类型定义 } 括号 _currentToken = _lexer.NextToken(); // 消耗类型定义 } 括号
var typeDefinitionCode = _lexer.GetCoreContent(coreStartRangeIndex); // 收集类型定义的代码。在Statement方法中开始收集的 var typeDefinitionCode = _lexer.GetCoreContent(coreStartRangeIndex); // 收集类型定义的代码。
DynamicObjectHelper.CreateTypeWithProperties(classFields, className, isOverlay); // 解析时缓存类型
var node = new ClassTypeDefinitionNode(classFields, className, isOverlay); var node = new ClassTypeDefinitionNode(classFields, className, isOverlay);
_currentToken.Code = typeDefinitionCode; _currentToken.Code = typeDefinitionCode;
node.SetTokenInfo(_currentToken); node.SetTokenInfo(_currentToken);
@@ -361,7 +623,8 @@ namespace Serein.Script
var arguments = new List<ASTNode>(); var arguments = new List<ASTNode>();
while (_currentToken.Type != TokenType.ParenthesisRight) while (_currentToken.Type != TokenType.ParenthesisRight)
{ {
arguments.Add(Expression()); // 获取参数表达式 //arguments.Add(Expression()); // 获取参数表达式
arguments.Add(BooleanExpression()); // 获取参数表达式
if (_currentToken.Type == TokenType.Comma) if (_currentToken.Type == TokenType.Comma)
{ {
_currentToken = _lexer.NextToken(); // consume "," _currentToken = _lexer.NextToken(); // consume ","
@@ -383,17 +646,40 @@ namespace Serein.Script
string collectionName = _currentToken.Value.ToString(); string collectionName = _currentToken.Value.ToString();
//_lexer.NextToken(); // consume "[" //_lexer.NextToken(); // consume "["
_currentToken = _lexer.NextToken(); // consume identifier _currentToken = _lexer.NextToken(); // 消耗数组名称 identifier
// ParenthesisLeft // ParenthesisLeft
if (_currentToken.Type != TokenType.SquareBracketsLeft) if (_currentToken.Type != TokenType.SquareBracketsLeft)
throw new Exception("Expected '[' after function name"); throw new Exception("Expected '[' after function name");
_currentToken = _lexer.NextToken(); // consume "[" _currentToken = _lexer.NextToken(); // 消耗 "["
ASTNode indexValue = Expression(); // get index value //ASTNode indexValue = Expression(); // 获取表达数组下标的节点
ASTNode indexValue = BooleanExpression(); // 获取表达数组下标的节点
_currentToken = _lexer.NextToken(); // consume "]" _currentToken = _lexer.NextToken(); // 消耗 "]"
return new CollectionIndexNode(identifierNode,indexValue).SetTokenInfo(_currentToken); return new CollectionIndexNode(identifierNode, indexValue).SetTokenInfo(_currentToken);
}
/// <summary>
/// 指定对象解析集合索引行为(数组或字典)
/// </summary>
/// <returns></returns>
/// <exception cref="Exception"></exception>
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);
} }
/// <summary> /// <summary>
@@ -425,7 +711,10 @@ namespace Serein.Script
// 成员赋值 obj.Member = xxx; // 成员赋值 obj.Member = xxx;
_currentToken = _lexer.NextToken(); // 消耗 "=" _currentToken = _lexer.NextToken(); // 消耗 "="
_currentToken = _lexer.NextToken(); // 消耗 "=" _currentToken = _lexer.NextToken(); // 消耗 "="
var valueNode = Expression(); // 解析右值 //var valueNode = Expression(); // 解析右值
var valueNode = BooleanExpression(); // 解析右值
_currentToken = _lexer.NextToken(); // 消耗 变量
//_currentToken = _lexer.NextToken(); // 消耗 ;
return new MemberAssignmentNode(identifierNode, memberName, valueNode).SetTokenInfo(_peekToken); return new MemberAssignmentNode(identifierNode, memberName, valueNode).SetTokenInfo(_peekToken);
} }
else else
@@ -465,27 +754,28 @@ namespace Serein.Script
private ASTNode ParseMemberFunctionCall(ASTNode targetNode) private ASTNode ParseMemberFunctionCall(ASTNode targetNode)
{ {
string functionName = _currentToken.Value.ToString(); // 函数名称 string functionName = _currentToken.Value.ToString(); // 函数名称
_currentToken = _lexer.NextToken(); // consume identifier _currentToken = _lexer.NextToken(); // 消耗函数名称
if (_currentToken.Type != TokenType.ParenthesisLeft) if (_currentToken.Type != TokenType.ParenthesisLeft)
throw new Exception("Expected '(' after function name"); throw new Exception("Expected '(' after function name");
_currentToken = _lexer.NextToken(); // consume "(" _currentToken = _lexer.NextToken(); // 消耗 "("
var arguments = new List<ASTNode>(); var arguments = new List<ASTNode>();
while (_currentToken.Type != TokenType.ParenthesisRight) while (_currentToken.Type != TokenType.ParenthesisRight)
{ {
// 获取参数表达式 // 获取参数表达式
var arg = Expression(); //var arg = Expression();
_currentToken = _lexer.NextToken(); // consume arg var arg = BooleanExpression();
_currentToken = _lexer.NextToken(); // 消耗参数 arg
arguments.Add(arg); // 添加到参数列表 arguments.Add(arg); // 添加到参数列表
if (_currentToken.Type == TokenType.Comma) if (_currentToken.Type == TokenType.Comma)
{ {
_currentToken = _lexer.NextToken(); // consume "," _currentToken = _lexer.NextToken(); // 消耗参数分隔符 ","
} }
if (_currentToken.Type == TokenType.Semicolon) if (_currentToken.Type == TokenType.Semicolon)
{ {
break; // consume ";" break; // 消耗 ";"
} }
} }
@@ -510,25 +800,37 @@ namespace Serein.Script
_currentToken = _lexer.NextToken(); // consume "(" _currentToken = _lexer.NextToken(); // consume "("
var arguments = new List<ASTNode>();
bool isBreak = false; bool isBreak = false;
while (_currentToken.Type != TokenType.ParenthesisRight) var arguments = new List<ASTNode>();
// 获取参数
while (true)// _currentToken.Type != TokenType.ParenthesisRight
{ {
var arg = Expression(); // 获取参数表达式 //var arg = Expression(); // 获取参数表达式
_currentToken = _lexer.NextToken(); // consume arg var arg = BooleanExpression(); // 获取参数表达式
arguments.Add(arg); arguments.Add(arg);
if (_currentToken.Type == TokenType.Comma) if (_currentToken.Type == TokenType.Comma)
{ {
_currentToken = _lexer.NextToken(); // consume "," _currentToken = _lexer.NextToken(); // 消耗参数分隔符 ","
} }
if (_currentToken.Type == TokenType.Semicolon) if (_currentToken.Type == TokenType.ParenthesisRight )
{ {
isBreak = true; _currentToken = _lexer.NextToken(); // 消耗方法结束括号 ""
}
if (_currentToken.Type == TokenType.Semicolon )
{
//isBreak = true;
break; // consume ";" break; // consume ";"
} }
/*if (_currentToken.Type == TokenType.Semicolon) // 提前结束
{
arguments.Add(arg);
isBreak = true;
break; // consume ";"
}*/
//_currentToken = _lexer.NextToken(); // consume arg
} }
if(!isBreak) //if(!isBreak)
_currentToken = _lexer.NextToken(); // consume ")" // _currentToken = _lexer.NextToken(); // consume ")"
//var node = Statements[^1]; //var node = Statements[^1];
@@ -559,7 +861,8 @@ namespace Serein.Script
{ {
return new ReturnNode().SetTokenInfo(_currentToken); // 返回空的 ReturnNode return new ReturnNode().SetTokenInfo(_currentToken); // 返回空的 ReturnNode
} }
var resultValue = Expression(); // 获取返回值表达式 var resultValue = BooleanExpression(); // 获取返回值表达式
//var resultValue = Expression(); // 获取返回值表达式
_currentToken = _lexer.NextToken(); _currentToken = _lexer.NextToken();
return new ReturnNode(resultValue).SetTokenInfo(_currentToken); return new ReturnNode(resultValue).SetTokenInfo(_currentToken);
} }
@@ -574,7 +877,8 @@ namespace Serein.Script
{ {
_currentToken = _lexer.NextToken(); // Consume "if" _currentToken = _lexer.NextToken(); // Consume "if"
_currentToken = _lexer.NextToken(); // Consume "(" _currentToken = _lexer.NextToken(); // Consume "("
ASTNode condition = Expression(); ASTNode condition = BooleanExpression();
//ASTNode condition = Expression();
_currentToken = _lexer.NextToken(); // Consume ")" _currentToken = _lexer.NextToken(); // Consume ")"
// 确保遇到左大括号 { 后进入代码块解析 // 确保遇到左大括号 { 后进入代码块解析
@@ -590,6 +894,10 @@ namespace Serein.Script
while (_currentToken.Type != TokenType.BraceRight && _currentToken.Type != TokenType.EOF) while (_currentToken.Type != TokenType.BraceRight && _currentToken.Type != TokenType.EOF)
{ {
var astNode = Statement(); // 解析 if 分支中的语句 var astNode = Statement(); // 解析 if 分支中的语句
while (_currentToken.Type == TokenType.Semicolon)
{
_currentToken = _lexer.NextToken();
}
if (astNode != null) if (astNode != null)
{ {
trueBranch.Add(astNode); // 将 if 分支的语句添加到 trueBranch 中 trueBranch.Add(astNode); // 将 if 分支的语句添加到 trueBranch 中
@@ -608,6 +916,10 @@ namespace Serein.Script
while (_currentToken.Type != TokenType.BraceRight && _currentToken.Type != TokenType.EOF) while (_currentToken.Type != TokenType.BraceRight && _currentToken.Type != TokenType.EOF)
{ {
var astNode = Statement(); // 解析 else 分支中的语句 var astNode = Statement(); // 解析 else 分支中的语句
while (_currentToken.Type == TokenType.Semicolon)
{
_currentToken = _lexer.NextToken();
}
if (astNode != null) if (astNode != null)
{ {
falseBranch.Add(astNode); // 将 else 分支的语句添加到 falseBranch 中 falseBranch.Add(astNode); // 将 else 分支的语句添加到 falseBranch 中
@@ -633,7 +945,8 @@ namespace Serein.Script
{ {
_currentToken = _lexer.NextToken(); // Consume "while" _currentToken = _lexer.NextToken(); // Consume "while"
_currentToken = _lexer.NextToken(); // Consume "(" _currentToken = _lexer.NextToken(); // Consume "("
ASTNode condition = Expression(); ASTNode condition = BooleanExpression();
//ASTNode condition = Expression();
_currentToken = _lexer.NextToken(); // Consume ")" _currentToken = _lexer.NextToken(); // Consume ")"
_currentToken = _lexer.NextToken(); // Consume "{" _currentToken = _lexer.NextToken(); // Consume "{"
List<ASTNode> body = new List<ASTNode>(); List<ASTNode> body = new List<ASTNode>();
@@ -645,43 +958,131 @@ namespace Serein.Script
return new WhileNode(condition, body).SetTokenInfo(_currentToken); return new WhileNode(condition, body).SetTokenInfo(_currentToken);
} }
/* /// <summary>
/// 解析表达式。
/// </summary>
/// <returns></returns>
private ASTNode Expression()
{
ASTNode left = Term();
while (_currentToken.Type == TokenType.Operator && (
_currentToken.Value == "+" || _currentToken.Value == "-"))
{
string op = _currentToken.Value.ToString();
_currentToken = _lexer.NextToken();
ASTNode right = Term();
left = new BinaryOperationNode(left, op, right).SetTokenInfo(_currentToken);
}
while (_currentToken.Type == TokenType.Operator && (_currentToken.Value == "*" || _currentToken.Value == "/"))
{
string op = _currentToken.Value.ToString();
_currentToken = _lexer.NextToken();
ASTNode right = Term();
left = new BinaryOperationNode(left, op, right).SetTokenInfo(_currentToken);
}
return left;
}
/// <summary>
/// 解析项Term比较运算符
/// </summary>
/// <returns></returns>
private ASTNode Term()
{
ASTNode left = Factor();
while (_currentToken.Type == TokenType.Operator &&
(_currentToken.Value == "<" || _currentToken.Value == ">" ||
_currentToken.Value == "<=" || _currentToken.Value == ">=" ||
_currentToken.Value == "==" || _currentToken.Value == "!="))
{
string op = _currentToken.Value.ToString();
_currentToken = _lexer.NextToken();
ASTNode right = Factor();
left = new BinaryOperationNode(left, op, right).SetTokenInfo(_currentToken);
}
return left;
}*/
/// <summary> /// <summary>
/// 解析表达式 /// 顶层布尔表达式
/// </summary>
/// <returns></returns>
private ASTNode BooleanExpression()
{
ASTNode left = ComparisonExpression();
while (_currentToken.Type == TokenType.Operator &&
(_currentToken.Value == "&&" || _currentToken.Value == "||"))
{
string op = _currentToken.Value;
_currentToken = _lexer.NextToken();
ASTNode right = ComparisonExpression();
left = new BinaryOperationNode(left, op, right).SetTokenInfo(_currentToken);
}
return left;
}
/// <summary>
/// 比较表达式(==, !=, <, <=, >, >=
/// </summary>
/// <returns></returns>
private ASTNode ComparisonExpression()
{
ASTNode left = Expression();
while (_currentToken.Type == TokenType.Operator &&
(_currentToken.Value == "==" || _currentToken.Value == "!=" ||
_currentToken.Value == "<" || _currentToken.Value == "<=" ||
_currentToken.Value == ">" || _currentToken.Value == ">="))
{
string op = _currentToken.Value;
_currentToken = _lexer.NextToken();
ASTNode right = Expression();
left = new BinaryOperationNode(left, op, right).SetTokenInfo(_currentToken);
}
return left;
}
/// <summary>
/// 加减
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
private ASTNode Expression() private ASTNode Expression()
{ {
ASTNode left = Term(); ASTNode left = Term();
while (_currentToken.Type == TokenType.Operator && (
_currentToken.Value == "+" || _currentToken.Value == "-" || while (_currentToken.Type == TokenType.Operator &&
_currentToken.Value == "*" || _currentToken.Value == "/")) (_currentToken.Value == "+" || _currentToken.Value == "-"))
{ {
string op = _currentToken.Value.ToString(); string op = _currentToken.Value;
_currentToken = _lexer.NextToken(); _currentToken = _lexer.NextToken();
ASTNode right = Term(); ASTNode right = Term();
left = new BinaryOperationNode(left, op, right).SetTokenInfo(_currentToken); left = new BinaryOperationNode(left, op, right).SetTokenInfo(_currentToken);
} }
return left;
return left;
} }
/// <summary> /// <summary>
/// 解析项Term用于处理加减乘除等运算符。 /// 乘除
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
private ASTNode Term() private ASTNode Term()
{ {
ASTNode left = Factor(); ASTNode left = Factor();
while (_currentToken.Type == TokenType.Operator && while (_currentToken.Type == TokenType.Operator &&
(_currentToken.Value == "<" || _currentToken.Value == ">" || (_currentToken.Value == "*" || _currentToken.Value == "/"))
_currentToken.Value == "<=" || _currentToken.Value == ">=" ||
_currentToken.Value == "==" || _currentToken.Value == "!="))
{ {
string op = _currentToken.Value.ToString(); string op = _currentToken.Value;
_currentToken = _lexer.NextToken(); _currentToken = _lexer.NextToken();
ASTNode right = Factor(); ASTNode right = Factor();
left = new BinaryOperationNode(left, op, right).SetTokenInfo(_currentToken); left = new BinaryOperationNode(left, op, right).SetTokenInfo(_currentToken);
} }
return left; return left;
} }
@@ -692,6 +1093,8 @@ namespace Serein.Script
/// <exception cref="Exception"></exception> /// <exception cref="Exception"></exception>
private ASTNode Factor() private ASTNode Factor()
{ {
#region #region
if (_currentToken.Type == TokenType.Null) if (_currentToken.Type == TokenType.Null)
{ {
@@ -757,11 +1160,122 @@ namespace Serein.Script
} }
#endregion #endregion
// 标识符节点
if (_currentToken.Type == TokenType.Identifier)
{
var _identifierPeekToken = _lexer.PeekToken();
if (_identifierPeekToken.Type is (TokenType.Dot and TokenType.ParenthesisLeft) or TokenType.Semicolon or TokenType.Comma)
{
// 不是 "." 号,也不是 "(" , 或是";",则是获取变量
var node = new IdentifierNode(_currentToken.Value).SetTokenInfo(_currentToken); // 获取变量
_currentToken = _lexer.NextToken(); // 消耗变量
return node;
}
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<ASTNode> nodes = new List<ASTNode>();
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 ObjectMemberExpressionNode(node).SetTokenInfo(objToken);
return objNode;
}
/* var _identifierPeekToken = _lexer.PeekToken();
// 该标识符是方法调用
if (_identifierPeekToken.Type == TokenType.ParenthesisLeft)
{
// 可能是函数调用
return ParseFunctionCall();
}
// 需要从该标识符调用另一个标识符
if (_identifierPeekToken.Type == TokenType.Dot)
{
// 可能是成员访问或成员赋值
return ParseMemberAccessOrAssignment(); // 二元操作中获取对象成员
}
// 数组 index; 字典 key obj.Member[xxx];
if (_identifierPeekToken.Type == TokenType.SquareBracketsLeft)
{
return ParseCollectionIndex();
}
_currentToken = _lexer.NextToken(); // 消耗标识符
return new IdentifierNode(identifier.ToString()).SetTokenInfo(_currentToken);*/
}
// 方法调用 // 方法调用
if (_currentToken.Type == TokenType.ParenthesisLeft) if (_currentToken.Type == TokenType.ParenthesisLeft)
{ {
_currentToken = _lexer.NextToken(); // 消耗 "(" _currentToken = _lexer.NextToken(); // 消耗 "("
var expr = Expression(); var expr = BooleanExpression();
//var expr = Expression();
if (_currentToken.Type != TokenType.ParenthesisRight) if (_currentToken.Type != TokenType.ParenthesisRight)
throw new Exception("非预期的符号,预期符号为\")\"。"); throw new Exception("非预期的符号,预期符号为\")\"。");
_currentToken = _lexer.NextToken(); // 消耗 ")" _currentToken = _lexer.NextToken(); // 消耗 ")"
@@ -775,38 +1289,10 @@ namespace Serein.Script
return ParseObjectInstantiation(); return ParseObjectInstantiation();
} }
// 标识符节点
if (_currentToken.Type == TokenType.Identifier)
{
var identifier = _currentToken.Value; // 标识符字面量
var _identifierPeekToken = _lexer.PeekToken();
// 该标识符是方法调用
if (_identifierPeekToken.Type == TokenType.ParenthesisLeft)
{
// 可能是函数调用
return ParseFunctionCall();
}
// 需要从该标识符调用另一个标识符
if (_identifierPeekToken.Type == TokenType.Dot)
{
// 可能是成员访问或成员赋值
return ParseMemberAccessOrAssignment(); // 二元操作中获取对象成员
}
// 数组 index; 字典 key obj.Member[xxx];
if (_identifierPeekToken.Type == TokenType.SquareBracketsLeft)
{
return ParseCollectionIndex();
}
_currentToken = _lexer.NextToken(); // 消耗标识符
return new IdentifierNode(identifier.ToString()).SetTokenInfo(_currentToken);
}
throw new Exception("Unexpected factor: " + _currentToken.Value.ToString()); throw new Exception($"在Expression().Factor()遇到意外的 Token Type ,{_currentToken.Type} {_currentToken.Value} " );
} }
} }

View File

@@ -1,51 +1,630 @@
using Serein.Library.Utils; using Serein.Library;
using Serein.Library.Utils;
using Serein.Script.Node; using Serein.Script.Node;
using Serein.Script.Symbol; using Serein.Script.Symbol;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reactive; using System.Reactive;
using System.Reflection;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Xml.Linq; using System.Xml.Linq;
namespace Serein.Script namespace Serein.Script
{ {
/// <summary>
/// 脚本类型分析
/// </summary>
public class SereinScriptTypeAnalysis public class SereinScriptTypeAnalysis
{ {
private Dictionary<string, SymbolInfo> SymbolInfos = new Dictionary<string, SymbolInfo>();
public SereinScriptTypeAnalysis(ProgramNode programNode) public SereinScriptTypeAnalysis()
{
}
public void AnalysisProgramNode(ProgramNode astNode)
{
NodeSymbolInfos.Clear();
for (int i = 0; i < astNode.Statements.Count; i++)
{
var node = astNode.Statements[i];
Analysis(node);
}
var returnNodes = astNode.Statements.Where(node => node is ReturnNode).ToArray();
if (returnNodes.Length == 0)
{
NodeSymbolInfos[astNode] = typeof(void); // 程序无返回值
}
else if (returnNodes.Length == 1)
{
var ifNodes = astNode.Statements.Where(node => node is IfNode).ToArray();
NodeSymbolInfos[astNode] = NodeSymbolInfos[returnNodes[0]]; // 确定的返回值
}
else
{
}
}
/// <summary>
/// 符号表
/// </summary>
public Dictionary<ASTNode, Type> NodeSymbolInfos { get; } = new Dictionary<ASTNode, Type>();
/// <summary>
/// 类型分析、校验
/// </summary>
/// <param name="node"></param>
/// <exception cref="NotImplementedException"></exception>
private void Analysis(ASTNode node)
{
switch (node)
{
case ProgramNode programNode: // 程序开始节点
break;
case ReturnNode returnNode: // 程序退出节点
Evaluate(returnNode); // 解析变量定义的类型
break;
case NullNode nullNode: // null
case CharNode charNode: // char字面量
case StringNode stringNode: // 字符串字面量
case BooleanNode booleanNode: // 布尔值字面量
case NumberIntNode numberIntNode: // int整型数值字面量
case NumberLongNode numberLongNode: // long整型数值字面量
case NumberFloatNode numberFloatNode: // float浮点数值字面量
case NumberDoubleNode numberDoubleNode: // double浮点数值字面量
Evaluate(node);
break;
case IdentifierNode identifierNode: // 变量定义
void AnalysisIdentifierNode(IdentifierNode identifierNode)
{
Evaluate(identifierNode); // 解析变量定义的类型
}
AnalysisIdentifierNode(identifierNode);
break;
case IfNode ifNode: // if语句结构
void AnalysisIfNode(IfNode ifNode)
{
Evaluate(ifNode);
var conditionType = NodeSymbolInfos[ifNode.Condition]; // 获取条件部分的返回类型
if (conditionType != typeof(bool?) && conditionType != typeof(bool))
{
throw new NotImplementedException("if...else...条件返回值不为布尔类型变量");
}
}
AnalysisIfNode(ifNode);
break;
case WhileNode whileNode: // while语句结构
void AnalysisWhileNode(WhileNode whileNode)
{
Evaluate(whileNode);
var conditionType = NodeSymbolInfos[whileNode.Condition]; // 获取条件部分的返回类型
if (conditionType != typeof(bool?) && conditionType != typeof(bool))
{
throw new NotImplementedException("if...else...条件返回值不为布尔类型变量");
}
}
AnalysisWhileNode(whileNode);
break;
case AssignmentNode assignmentNode: // 对象赋值语句let x;默认赋值null。默认类型object
void AnalysisAssignmentNode(AssignmentNode assignmentNode)
{
Evaluate(assignmentNode);
}
AnalysisAssignmentNode(assignmentNode);
break;
case BinaryOperationNode binaryOperationNode: // 二元运算操作
void AnalysisBinaryOperationNode(BinaryOperationNode binaryOperationNode)
{
Evaluate(binaryOperationNode);
}
AnalysisBinaryOperationNode(binaryOperationNode);
break;
case CollectionIndexNode collectionIndexNode: // 集合类型操作
void AnalysisCollectionIndexNode(CollectionIndexNode collectionIndexNode)
{
Evaluate(collectionIndexNode);
/*Analysis(collectionIndexNode.Collection); // 分析集合类型(变量,对象成员)
Analysis(collectionIndexNode.Index); // 分析索引类型
var collectionType = NodeSymbolInfos[collectionIndexNode.Collection];
var indexExprType = NodeSymbolInfos[collectionIndexNode.Index];
if (!TryGetIndexerType(collectionType, out var expectedIndexType, out var resultType))
throw new Exception($"类型 {collectionType} 不支持索引操作");
if (!expectedIndexType.IsAssignableFrom(indexExprType))
throw new Exception($"索引类型不匹配:需要 {expectedIndexType},实际为 {indexExprType}");
NodeSymbolInfos[collectionIndexNode] = resultType;*/
}
AnalysisCollectionIndexNode(collectionIndexNode);
break;
case ClassTypeDefinitionNode classTypeDefinitionNode: // 类型定义
Evaluate(classTypeDefinitionNode);
break;
case ObjectInstantiationNode objectInstantiationNode: // 类型实例化
Evaluate(objectInstantiationNode);
break;
case ObjectMemberExpressionNode objectMemberExpressionNode: // 类型表达式(链式调用)
Evaluate(objectMemberExpressionNode);
break;
case MemberAccessNode memberAccessNode: // 对象成员访问
Evaluate(memberAccessNode);
break;
case MemberAssignmentNode memberAssignmentNode: // 对象成员赋值
void AnalysisMemberAssignmentNode(MemberAssignmentNode memberAssignmentNode)
{
Evaluate(memberAssignmentNode);
}
AnalysisMemberAssignmentNode(memberAssignmentNode);
break;
case MemberFunctionCallNode memberFunctionCallNode: // 对象方法调用
Evaluate(memberFunctionCallNode);
break;
case FunctionCallNode functionCallNode: // 外部挂载的函数调用
Evaluate(functionCallNode);
break;
default: // 未定义的节点类型
break;
}
}
/// <summary>
/// 类型获取
/// </summary>
/// <param name="node"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
/// <exception cref="NotImplementedException"></exception>
private Type Evaluate(ASTNode node)
{
switch (node)
{
case ProgramNode programNode: // 程序开始节点
NodeSymbolInfos[programNode] = typeof(void);
return typeof(void);
case ReturnNode returnNode: // 程序退出节点
Type EvaluateReturnNode(ReturnNode returnNode)
{
var resultType = Evaluate(returnNode.Value);
NodeSymbolInfos[returnNode.Value] = resultType;
NodeSymbolInfos[returnNode] = resultType;
return resultType;
}
return EvaluateReturnNode(returnNode);
case NullNode nullNode: // null
NodeSymbolInfos[nullNode] = typeof(object);
return typeof(object);
case CharNode charNode: // char字面量
NodeSymbolInfos[charNode] = typeof(char);
return typeof(char);
case StringNode stringNode: // 字符串字面量
NodeSymbolInfos[stringNode] = typeof(string);
return typeof(string);
case BooleanNode booleanNode: // 布尔值字面量
NodeSymbolInfos[booleanNode] = typeof(bool);
return typeof(bool);
case NumberIntNode numberIntNode: // int整型数值字面量
NodeSymbolInfos[numberIntNode] = typeof(int);
return typeof(int);
case NumberLongNode numberLongNode: // long整型数值字面量
NodeSymbolInfos[numberLongNode] = typeof(long);
return typeof(long);
case NumberFloatNode numberFloatNode: // float浮点数值字面量
NodeSymbolInfos[numberFloatNode] = typeof(float);
return typeof(float);
case NumberDoubleNode numberDoubleNode: // double浮点数值字面量
NodeSymbolInfos[numberDoubleNode] = typeof(double);
return typeof(double);
case IdentifierNode identifierNode: // 变量定义
Type EvaluateIdentifierNode(IdentifierNode identifierNode)
{
var cacheNode = NodeSymbolInfos.Keys.FirstOrDefault(n => n is IdentifierNode idNode && idNode.Name == identifierNode.Name);
Type type = cacheNode is null ? typeof(object) : NodeSymbolInfos[cacheNode];
NodeSymbolInfos[identifierNode] = type;
return type;
}
return EvaluateIdentifierNode(identifierNode);
case IfNode ifNode: // if语句结构
Type EvaluateIfNode(IfNode ifNode)
{
var conditionType = Evaluate(ifNode.Condition); // 获取条件语句部分的返回类型
NodeSymbolInfos[ifNode.Condition] = conditionType;
if (conditionType == typeof(bool?) || conditionType == typeof(bool))
{
foreach (var item in ifNode.TrueBranch)
{
var itemType = Evaluate(item); // 解析真分支的语句块
NodeSymbolInfos[item] = itemType;
}
foreach (var item in ifNode.FalseBranch)
{
var itemType = Evaluate(item); // 解析假分支的语句块
NodeSymbolInfos[item] = itemType;
}
NodeSymbolInfos[ifNode] = typeof(void);
return typeof(void); // if语句不产生类型
}
else
{
throw new NotImplementedException("if...else...条件返回值不为布尔类型变量");
}
}
return EvaluateIfNode(ifNode);
case WhileNode whileNode: // while语句结构
Type EvaluateWhileNode(WhileNode whileNode)
{
var conditionType = Evaluate(whileNode.Condition); // 获取条件语句部分的返回类型
NodeSymbolInfos[whileNode.Condition] = conditionType;
if (conditionType == typeof(bool?) || conditionType == typeof(bool))
{
foreach (var item in whileNode.Body)
{
var itemType = Evaluate(item); // 解析真分支的语句块
NodeSymbolInfos[item] = itemType;
}
NodeSymbolInfos[whileNode] = typeof(void); // while流程不产生类型
return typeof(void); // if语句不产生类型
}
else
{
throw new NotImplementedException("if...else...条件返回值不为布尔类型变量");
}
}
return EvaluateWhileNode(whileNode);
case AssignmentNode assignmentNode:
// 对象赋值语句let x;默认赋值null。默认类型object
Type EvaluateAssignmentNode(AssignmentNode assignmentNode)
{
var targetType = Evaluate(assignmentNode.Target);
var valueType = Evaluate (assignmentNode.Value);
if (!targetType.IsAssignableFrom(valueType))
throw new Exception($"索引类型不匹配:需要 {targetType},实际为 {valueType}");
NodeSymbolInfos[assignmentNode.Value] = valueType;
NodeSymbolInfos[assignmentNode.Target] = valueType;
NodeSymbolInfos[assignmentNode] = typeof(void); // 赋值语句不产生类型
return targetType;
}
return EvaluateAssignmentNode(assignmentNode);
case BinaryOperationNode binaryOperationNode: // 二元运算操作
Type EvaluateBinaryOperationNode(BinaryOperationNode binaryOperationNode)
{
var leftType = Evaluate(binaryOperationNode.Left); // 递归判断左值类型
var rightType = Evaluate(binaryOperationNode.Right); // 递归判断右值类型
var op = binaryOperationNode.Operator;
var resultType = BinaryOperationEvaluator.EvaluateType(leftType, op, rightType);
NodeSymbolInfos[binaryOperationNode.Left] = leftType;
NodeSymbolInfos[binaryOperationNode.Right] = rightType;
NodeSymbolInfos[binaryOperationNode] = resultType;
return resultType;
}
return EvaluateBinaryOperationNode(binaryOperationNode);
case CollectionIndexNode collectionIndexNode: // 集合类型操作,获取集合操作后返回的类型
Type EvaluateCollectionIndexNode(CollectionIndexNode collectionIndexNode)
{
var collectionType = Evaluate(collectionIndexNode.Collection); // 分析集合类型(变量,对象成员)
var indexExprType = Evaluate(collectionIndexNode.Index); // 分析索引类型
if (!TryGetIndexerType(collectionType, out var expectedIndexType, out var resultType))
throw new Exception($"类型 {collectionType} 不支持索引操作");
if (!expectedIndexType.IsAssignableFrom(indexExprType))
throw new Exception($"索引类型不匹配:需要 {expectedIndexType},实际为 {indexExprType}");
NodeSymbolInfos[collectionIndexNode.Collection] = collectionType;
NodeSymbolInfos[collectionIndexNode.Index] = indexExprType;
NodeSymbolInfos[collectionIndexNode] = resultType;
return resultType;
}
return EvaluateCollectionIndexNode(collectionIndexNode);
case ClassTypeDefinitionNode classTypeDefinitionNode: // 类型定义
Type EvaluateClassTypeDefinitionNode(ClassTypeDefinitionNode classTypeDefinitionNode)
{
var classType = DynamicObjectHelper.GetCacheType(classTypeDefinitionNode.ClassName);
if (classType is null)
classType = DynamicObjectHelper.CreateTypeWithProperties(classTypeDefinitionNode.Fields, classTypeDefinitionNode.ClassName);
NodeSymbolInfos[classTypeDefinitionNode] = classType;
return classType;
}
return EvaluateClassTypeDefinitionNode(classTypeDefinitionNode);
case ObjectInstantiationNode objectInstantiationNode: // 类型实例化
Type EvaluateObjectInstantiationNode(ObjectInstantiationNode objectInstantiationNode)
{
Type? resultType = null;
try
{
resultType = Type.GetType(objectInstantiationNode.TypeName); // 从命名空间查询类型
}
finally
{
if (resultType is null)
{
resultType = DynamicObjectHelper.GetCacheType(objectInstantiationNode.TypeName); // 从自定义类型查询类型
}
}
NodeSymbolInfos[objectInstantiationNode] = resultType;
return resultType;
}
return EvaluateObjectInstantiationNode(objectInstantiationNode);
case ObjectMemberExpressionNode objectMemberExpressionNode: // 类型表达式(链式调用)
Type EvaluateObjectMemberExpressionNode(ObjectMemberExpressionNode objectMemberExpressionNode)
{
// 1. 对象成员获取 MemberAccessNode
// 2. 对象方法调用 MemberFunctionCallNode
// 3. 对象集合成员获取 CollectionIndexNode
Type? resultType = Evaluate(objectMemberExpressionNode.Value);
NodeSymbolInfos[objectMemberExpressionNode.Value] = resultType;
NodeSymbolInfos[objectMemberExpressionNode] = resultType;
return resultType;
}
return EvaluateObjectMemberExpressionNode(objectMemberExpressionNode);
case MemberAccessNode memberAccessNode: // 对象成员访问
Type EvaluateMemberAccessNode(MemberAccessNode memberAccessNode)
{
var objectType = Evaluate(memberAccessNode.Object);
var property = objectType.GetProperty(memberAccessNode.MemberName);
if (property is null)
throw new Exception($"类型 {objectType} 没有成员 {memberAccessNode.MemberName}");
NodeSymbolInfos[memberAccessNode.Object] = objectType;
NodeSymbolInfos[memberAccessNode] = property.PropertyType;
return property.PropertyType;
}
return EvaluateMemberAccessNode(memberAccessNode);
case MemberAssignmentNode memberAssignmentNode: // 对象成员赋值
Type EvaluateMemberAssignmentNode(MemberAssignmentNode memberAssignmentNode)
{
var objectType = Evaluate(memberAssignmentNode.Object);
var property = objectType.GetProperty(memberAssignmentNode.MemberName);
if(property is null)
throw new Exception($"类型异常:类型 {objectType} 没有成员 {memberAssignmentNode.MemberName}");
var propertyType = property.PropertyType;
var valueType = Evaluate(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 EvaluateMemberAssignmentNode(memberAssignmentNode);
case MemberFunctionCallNode memberFunctionCallNode: // 对象方法调用
Type EvaluateMemberFunctionCallNode(MemberFunctionCallNode memberFunctionCallNode)
{
var objectType = Evaluate(memberFunctionCallNode.Object);
var types = memberFunctionCallNode.Arguments.Select(arg => Evaluate(arg)).ToArray();
var methodInfo = objectType.GetMethod(memberFunctionCallNode.FunctionName, types);
if (methodInfo is null)
throw new Exception($"类型 {objectType} 没有方法 {memberFunctionCallNode.FunctionName}");
for (int index = 0; index < memberFunctionCallNode.Arguments.Count; index++)
{
ASTNode argNode = memberFunctionCallNode.Arguments[index];
Type argType = types[index];
NodeSymbolInfos[argNode] = argType;
}
NodeSymbolInfos[memberFunctionCallNode.Object] = objectType;
NodeSymbolInfos[memberFunctionCallNode] = methodInfo.ReturnType;
return methodInfo.ReturnType;
}
return EvaluateMemberFunctionCallNode(memberFunctionCallNode);
case FunctionCallNode functionCallNode: // 外部挂载的函数调用
Type EvaluateFunctionCallNode(FunctionCallNode functionCallNode)
{
if(!SereinScriptInterpreter.FunctionInfoTable.TryGetValue(functionCallNode.FunctionName, out var methodInfo))
{
throw new Exception($"脚本没有挂载方法 {functionCallNode.FunctionName}");
}
var types = functionCallNode.Arguments.Select(arg => Evaluate(arg)).ToArray();
for (int index = 0; index < functionCallNode.Arguments.Count; index++)
{
ASTNode argNode = functionCallNode.Arguments[index];
Type argType = types[index];
NodeSymbolInfos[argNode] = argType;
}
NodeSymbolInfos[functionCallNode] = methodInfo.ReturnType;
return methodInfo.ReturnType;
}
return EvaluateFunctionCallNode(functionCallNode);
default: // 未定义的节点类型
break;
}
throw new NotImplementedException();
}
private void Analysis2(ASTNode node)
{
switch (node)
{
case ProgramNode programNode: // 程序开始节点
break;
case ReturnNode returnNode: // 程序退出节点
break;
case NullNode nullNode: // null
break;
case CharNode charNode: // char字面量
break;
case StringNode stringNode: // 字符串字面量
break;
case BooleanNode booleanNode: // 布尔值字面量
break;
case NumberIntNode numberIntNode: // int整型数值字面量
break;
case NumberLongNode numberLongNode: // long整型数值字面量
break;
case NumberFloatNode numberFloatNode: // float浮点数值字面量
break;
case NumberDoubleNode numberDoubleNode: // double浮点数值字面量
break;
case IdentifierNode identifierNode: // 变量定义
break;
case IfNode ifNode: // if语句结构
break;
case WhileNode whileNode: // while语句结构
break;
case AssignmentNode assignmentNode: // 对象赋值语句let x;默认赋值null。默认类型object
break;
case BinaryOperationNode binaryOperationNode: // 二元运算操作
break;
case CollectionIndexNode collectionIndexNode: // 集合类型操作
break;
case ClassTypeDefinitionNode classTypeDefinitionNode: // 类型定义
break;
case ObjectInstantiationNode objectInstantiationNode: // 类型实例化
break;
case ObjectMemberExpressionNode objectMemberExpressionNode: // 类型表达式(链式调用)
break;
case MemberAccessNode memberAccessNode: // 对象成员访问
break;
case MemberAssignmentNode memberAssignmentNode: // 对象成员赋值
break;
case MemberFunctionCallNode memberFunctionCallNode: // 对象方法调用
break;
case FunctionCallNode functionCallNode: // 外部挂载的函数调用
break;
default: // 未定义的节点类型
break;
}
}
/// <summary>
/// 获取某个集合类型支持的索引参数类型
/// </summary>
/// <param name="collectionType">集合类型</param>
/// <param name="indexType">索引</param>
/// <param name="resultType">获取到的类型</param>
/// <returns></returns>
public static bool TryGetIndexerType(Type collectionType, out Type indexType, out Type resultType)
{
indexType = null!;
resultType = null!;
// 检查是否是数组
if (collectionType.IsArray)
{
indexType = typeof(int);
resultType = collectionType.GetElementType()!;
return true;
}
// 检查是否实现 IDictionary<K, V>
var dictInterface = collectionType
.GetInterfaces()
.FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IDictionary<,>));
if (dictInterface != null)
{
var args = dictInterface.GetGenericArguments();
indexType = args[0]; // Key
resultType = args[1]; // Value
return true;
}
// 检查是否实现 IList<T>
var listInterface = collectionType
.GetInterfaces()
.FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IList<>));
if (listInterface != null)
{
indexType = typeof(int);
resultType = listInterface.GetGenericArguments()[0];
return true;
}
// 检查是否有索引器属性
var indexer = collectionType
.GetDefaultMembers()
.OfType<PropertyInfo>()
.FirstOrDefault(p =>
{
var args = p.GetIndexParameters();
return args.Length == 1;
});
if (indexer != null)
{
var param = indexer.GetIndexParameters()[0];
indexType = param.ParameterType;
resultType = indexer.PropertyType;
return true;
}
return false;
}
#region
/// <summary>
/// 符号表
/// </summary>
public Dictionary<string, SymbolInfo> SymbolInfos { get; } = new Dictionary<string, SymbolInfo>();
/* public SereinScriptTypeAnalysis(ProgramNode programNode)
{ {
SymbolInfos.Clear(); // 清空符号表 SymbolInfos.Clear(); // 清空符号表
// 初始化符号表
foreach (ASTNode astNode in programNode.Statements) foreach (ASTNode astNode in programNode.Statements)
{ {
var type = Trace(astNode); var type = Trace(astNode);
if (type is null) continue; if (type is null) continue;
var info = Analyse(astNode, type); var info = Analyse(astNode, type);
if(info != null) if (info != null)
{ {
SymbolInfos[info.Name] = info; SymbolInfos[info.Name] = info;
} }
/*if(astNode is AssignmentNode assignmentNode) }
{
var name = assignmentNode.Variable; // 类型分析
var node = assignmentNode.Value; foreach (ASTNode astNode in programNode.Statements)
var type = Analyse(node); {
if(type is null)
{
continue;
}
var symbolInfo = new SymbolInfo
{
Type = type,
Node = node,
Name = name,
};
SymbolInfos[name] = symbolInfo;
}*/
} }
} }
*/
private Type? GetTypeOnMemberFunctionCallNode(ASTNode objectNode)
{
Type objectType = null;
if (objectNode is IdentifierNode identifierNode)
{
if (SymbolInfos.TryGetValue(identifierNode.Name, out var symbolInfo))
{
objectType = symbolInfo.Type;
}
}
return objectType;
}
private Type? GetMethodReturnType(Type type, string methodName)
{
if (type is null) return null;
var methodInfos = type.GetMethods();
var methodInfo = methodInfos.FirstOrDefault(md => md.Name == methodName);
var returnType = methodInfo?.ReturnType;
return returnType;
}
/// <summary> /// <summary>
/// 追踪类型 /// 追踪类型
@@ -71,12 +650,27 @@ namespace Serein.Script
case CharNode charNode: // char case CharNode charNode: // char
return typeof(char); return typeof(char);
case IdentifierNode identifierNode: // 定义变量 case IdentifierNode identifierNode: // 定义变量
return typeof(object); if(SymbolInfos.TryGetValue(identifierNode.Name, out var varSymbolInfo))
{
return varSymbolInfo.Type; // 返回定义的类型
}
return typeof(object); // 默认为 object
case AssignmentNode assignmentNode: // 赋值行为 case AssignmentNode assignmentNode: // 赋值行为
var type = Trace(assignmentNode.Value); var targetType = Trace(assignmentNode.Target);
return type; var valueType = Trace(assignmentNode.Value);
//throw new SereinSciptException(identifierNode, "尝试使用值为null的变量"); if (targetType.IsAssignableFrom(valueType))
//throw new SereinSciptException(identifierNode, "尝试使用未声明的变量"); {
if(assignmentNode.Target is IdentifierNode identifierNode
&& !SymbolInfos.ContainsKey(identifierNode.Name))
{
return valueType;
}
return targetType;
}
else
{
throw new Exception("无法转换类型");
}
case BinaryOperationNode binOpNode: // 递归计算二元操作 case BinaryOperationNode binOpNode: // 递归计算二元操作
var leftType = Trace(binOpNode.Left); var leftType = Trace(binOpNode.Left);
var op = binOpNode.Operator; var op = binOpNode.Operator;
@@ -84,18 +678,29 @@ namespace Serein.Script
var resultType = BinaryOperationEvaluator.EvaluateType(leftType, op, rightType); var resultType = BinaryOperationEvaluator.EvaluateType(leftType, op, rightType);
return resultType; return resultType;
case ClassTypeDefinitionNode classTypeDefinitionNode: case ClassTypeDefinitionNode classTypeDefinitionNode:
var definitionType = DynamicObjectHelper.CreateTypeWithProperties(classTypeDefinitionNode.Fields, classTypeDefinitionNode.ClassName, true); var definitionType = DynamicObjectHelper.CreateTypeWithProperties(classTypeDefinitionNode.Fields, classTypeDefinitionNode.ClassName);
return definitionType; return definitionType;
case ObjectInstantiationNode objectInstantiationNode: // 创建对象 case ObjectInstantiationNode objectInstantiationNode: // 创建对象
var typeName = objectInstantiationNode.TypeName; var typeName = objectInstantiationNode.TypeName;
var objectType = Type.GetType(typeName); var objectType = Type.GetType(typeName);
objectType ??= DynamicObjectHelper.GetCacheType(typeName); objectType ??= DynamicObjectHelper.GetCacheType(typeName);
return objectType; return objectType;
case FunctionCallNode callNode: // 调用方法 case FunctionCallNode callNode: // 调用方法
return null; return null;
case MemberAssignmentNode memberAssignmentNode:
var leftValueType = Trace(memberAssignmentNode.Object);
var propertyType = leftValueType.GetProperty(memberAssignmentNode.MemberName)?.PropertyType;
var rightValueType = Trace(memberAssignmentNode.Value);
if (propertyType is not null && !propertyType.IsAssignableFrom(rightValueType))
{
throw new Exception("无法转换类型");
}
break;
case MemberFunctionCallNode memberFunctionCallNode: // 对象方法调用 case MemberFunctionCallNode memberFunctionCallNode: // 对象方法调用
return null; var objectNode = memberFunctionCallNode.Object;
var objType = GetTypeOnMemberFunctionCallNode(objectNode);
var methodName = memberFunctionCallNode.FunctionName;
return GetMethodReturnType(objType, methodName);
case MemberAccessNode memberAccessNode: // 对象成员访问 case MemberAccessNode memberAccessNode: // 对象成员访问
var memberType = memberAccessNode.MemberName; var memberType = memberAccessNode.MemberName;
return null; return null;
@@ -110,7 +715,7 @@ namespace Serein.Script
return null; return null;
} }
private SymbolInfo Analyse(ASTNode node, Type type) private SymbolInfo Analyse(ASTNode node, Type type)
{ {
@@ -128,20 +733,32 @@ namespace Serein.Script
Type = type, Type = type,
}; };
case AssignmentNode assignmentNode: // 赋值行为 case AssignmentNode assignmentNode: // 赋值行为
return new SymbolInfo if(assignmentNode.Target is IdentifierNode identifierNode1)
{ {
Name = assignmentNode.Variable, return new SymbolInfo
Node = node, {
Type = type, Name = identifierNode1.Name,
}; Node = node,
Type = type,
};
}
break;
case BinaryOperationNode binOpNode: // 递归计算二元操作 case BinaryOperationNode binOpNode: // 递归计算二元操作
break;
//case ClassTypeDefinitionNode classTypeDefinitionNode //case ClassTypeDefinitionNode classTypeDefinitionNode
case ObjectInstantiationNode objectInstantiationNode: // 创建对象 case ObjectInstantiationNode objectInstantiationNode: // 创建对象
break;
case FunctionCallNode callNode: // 调用方法 case FunctionCallNode callNode: // 调用方法
break;
case MemberFunctionCallNode memberFunctionCallNode: // 对象方法调用 case MemberFunctionCallNode memberFunctionCallNode: // 对象方法调用
break;
case MemberAccessNode memberAccessNode: // 对象成员访问 case MemberAccessNode memberAccessNode: // 对象成员访问
break;
case CollectionIndexNode collectionIndexNode: case CollectionIndexNode collectionIndexNode:
break;
case ReturnNode returnNode: // 返回内容 case ReturnNode returnNode: // 返回内容
break;
default: default:
break; break;
//throw new SereinSciptException(node, $"解释器 EvaluateAsync() 未实现{node}节点行为"); //throw new SereinSciptException(node, $"解释器 EvaluateAsync() 未实现{node}节点行为");
@@ -150,24 +767,43 @@ namespace Serein.Script
return null; return null;
} }
/* #endregion
case NullNode nullNode: // 返回null
case BooleanNode booleanNode: // 返回布尔
case NumberIntNode numberNode: // 数值
case StringNode stringNode: // 字符串
case CharNode charNode: // char
case IdentifierNode identifierNode: // 定义变量
case AssignmentNode assignmentNode: // 赋值行为
case BinaryOperationNode binOpNode: // 递归计算二元操作
case ObjectInstantiationNode objectInstantiationNode: // 创建对象
case FunctionCallNode callNode: // 调用方法
case MemberFunctionCallNode memberFunctionCallNode: // 对象方法调用
case MemberAccessNode memberAccessNode: // 对象成员访问
case CollectionIndexNode collectionIndexNode:
case ReturnNode returnNode: // 返回内容
default:
break;
*/
} }
} }
/*
case NullNode nullNode: // 返回null
case BooleanNode booleanNode: // 返回布尔
case NumberIntNode numberNode: // 数值
case StringNode stringNode: // 字符串
case CharNode charNode: // char
case IdentifierNode identifierNode: // 定义变量
case AssignmentNode assignmentNode: // 赋值行为
case BinaryOperationNode binOpNode: // 递归计算二元操作
case ObjectInstantiationNode objectInstantiationNode: // 创建对象
case FunctionCallNode callNode: // 调用方法
case MemberFunctionCallNode memberFunctionCallNode: // 对象方法调用
case MemberAccessNode memberAccessNode: // 对象成员访问
case CollectionIndexNode collectionIndexNode:
case ReturnNode returnNode: // 返回内容
default:
break;
*/
/* if (SymbolInfos.TryGetValue(varName, out var symbolInfo))
{
var state = symbolInfo.Type.IsAssignableFrom(type);
if (!state)
{
// 错误:变量[{varName}]赋值异常,[{type.FullName}]无法转换为[{symbolInfo.Type.FullName}]
//SereinEnv.WriteLine(InfoType.ERROR, $"[{type.FullName}]无法转化为[{symbolInfo.Type.FullName}]。源代码:{assignmentNode.Code.Replace(Environment.NewLine,"")} [行{assignmentNode.Row}]");
SereinEnv.WriteLine(InfoType.ERROR, $"类型异常:无法赋值变量[{varName}],因为[{type.FullName}]无法转化为[{symbolInfo.Type.FullName}]。在[行{assignmentNode.Row}]:{assignmentNode.Code}");
}
}*/

View File

@@ -17,7 +17,7 @@ namespace Serein.Script.Symbol
/// <summary> /// <summary>
/// 符号信息 /// 符号信息
/// </summary> /// </summary>
internal class SymbolInfo public class SymbolInfo
{ {
/// <summary> /// <summary>
/// 符号名称 /// 符号名称