重写脚本解释器的实现,提高其可读性。

This commit is contained in:
fengjiayi
2025-07-13 17:34:03 +08:00
parent 6141d2c1c1
commit 01ab905155
42 changed files with 1747 additions and 715 deletions

View File

@@ -22,7 +22,7 @@ namespace Serein.Script.Node
/// </summary>
public ASTNode Value { get; }
public AssignmentNode(ASTNode targetObject, ASTNode value) => (Target, Value) = (targetObject, value);
public AssignmentNode(ASTNode target, ASTNode value) => (Target, Value) = (target, value);
}

View File

@@ -22,8 +22,28 @@ namespace Serein.Script.Node
/// <summary>
/// 字段名称及字段类型
/// </summary>
[Obsolete("此属性已经过时将会改为Dictionary<string, string>", false)]
public Dictionary<string, Type> Fields { get; }
/// <summary>
/// 字段名称及字段类型(Kvp[fididName:fidleTypeName])
/// </summary>
public Dictionary<string, string> FieldInfos { get; }
public ClassTypeDefinitionNode(Dictionary<string, string> fields, string className)
{
this.FieldInfos = fields;
this.ClassName = className;
}
[Obsolete("此构造方法已经过时,可能在下一个版本中移除", false)]
public ClassTypeDefinitionNode(Dictionary<string, Type> fields, string className)
{
this.Fields = fields;
this.ClassName = className;
}
[Obsolete("此构造方法已经过时,可能在下一个版本中移除", false)]
public ClassTypeDefinitionNode(Dictionary<string, Type> fields, string className, bool isOverlay)
{
this.Fields = fields;

View File

@@ -20,10 +20,33 @@ namespace Serein.Script.Node
/// 索引来源
/// </summary>
public ASTNode Index { get; }
public CollectionIndexNode(ASTNode TargetValue,ASTNode indexValue)
public CollectionIndexNode(ASTNode Collection, ASTNode indexValue)
{
this.Collection = TargetValue;
this.Collection = Collection;
this.Index = indexValue;
}
}
/// <summary>
/// 集合赋值节点
/// </summary>
public class CollectionAssignmentNode : ASTNode
{
/// <summary>
/// 集合来源
/// </summary>
public CollectionIndexNode Collection { get; }
/// <summary>
/// 索引来源
/// </summary>
public ASTNode Value { get; }
public CollectionAssignmentNode(CollectionIndexNode collection, ASTNode value)
{
this.Collection = collection;
this.Value = value;
}
}
}

View File

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

View File

@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Serein.Script.Node
namespace Serein.Script.Node.FlowControl
{
/// <summary>
/// 条件节点

View File

@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Serein.Script.Node
namespace Serein.Script.Node.FlowControl
{
/// <summary>
/// 程序入口

View File

@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Serein.Script.Node
namespace Serein.Script.Node.FlowControl
{
/// <summary>
/// 返回值

View File

@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Serein.Script.Node
namespace Serein.Script.Node.FlowControl
{
/// <summary>
/// 循环条件节点

View File

@@ -2,10 +2,12 @@
using Serein.Library;
using Serein.Library.Utils;
using Serein.Script.Node;
using Serein.Script.Node.FlowControl;
using System.ComponentModel.Design;
using System.Reflection;
using System.Reflection.Metadata.Ecma335;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Serein.Script
@@ -358,7 +360,10 @@ namespace Serein.Script
case AssignmentNode assignment: // 出现在 = 右侧的表达式
await ExecutionAssignmentNodeAsync(context, assignment);
break;
case ObjectMemberExpressionNode objectMemberExpressionNode:
case CollectionAssignmentNode collectionAssignmentNode:
await SetCollectionValue(context,collectionAssignmentNode);
break;
case ExpressionNode objectMemberExpressionNode:
break;
case MemberAssignmentNode memberAssignmentNode: // 设置对象属性
await SetMemberValue(context, memberAssignmentNode);
@@ -455,8 +460,8 @@ namespace Serein.Script
return await GetCollectionValue(context, collectionIndexNode);
case ReturnNode returnNode: // 返回内容
return await EvaluateAsync(context, returnNode.Value); // 直接返回响应的内容
case ObjectMemberExpressionNode objectMemberExpressionNode: // 对象链式表达式
return await EvaluateAsync(context, objectMemberExpressionNode.Value);
case ExpressionNode expressionNode: // 表达式
return await EvaluateAsync(context, expressionNode.Value);
default:
throw new SereinSciptException(node, $"解释器 EvaluateAsync() 未实现{node}节点行为");
}
@@ -666,6 +671,79 @@ namespace Serein.Script
throw new ArgumentException($"解析{collectionIndexNode}节点时,左值并非有效集合。");
}
/// <summary>
/// 设置集合中的成员
/// </summary>
/// <param name="memberAccessNode"></param>
/// <returns></returns>
/// <exception cref="SereinSciptException"></exception>
public async Task SetCollectionValue(IScriptInvokeContext context, CollectionAssignmentNode collectionAssignmentNode)
{
var collectionValue = await EvaluateAsync(context, collectionAssignmentNode.Collection.Collection);
var indexValue = await EvaluateAsync(context, collectionAssignmentNode.Collection.Index);
if (collectionValue is null)
{
throw new ArgumentNullException($"解析{collectionAssignmentNode}节点时,集合返回空。");
}
if (indexValue is null)
{
throw new ArgumentNullException($"解析{collectionAssignmentNode}节点时,索引返回空。");
}
// 解析数组/集合名与索引部分
var targetType = collectionValue.GetType(); // 目标对象的类型
#region
if (targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof(Dictionary<,>))
{
// 目标是键值对
var method = targetType.GetMethod("set_Item", BindingFlags.Public | BindingFlags.Instance);
if (method is not null)
{
var valueValue = await EvaluateAsync(context, collectionAssignmentNode.Value);
method.Invoke(collectionValue, [indexValue, valueValue]);
}
}
#endregion
#region
else
{
if (indexValue is int index)
{
// 获取数组或集合对象
// 访问数组或集合中的指定索引
if (collectionValue is Array array)
{
if (index < 0 || index >= array.Length)
{
throw new ArgumentException($"解析{collectionValue}节点时,数组下标越界。");
}
var valueValue = await EvaluateAsync(context, collectionAssignmentNode.Value);
array.SetValue(valueValue, index);
return;
}
else if (collectionValue is IList<object> list)
{
if (index < 0 || index >= list.Count)
{
throw new ArgumentException($"解析{collectionValue}节点时,数组下标越界。");
}
var valueValue = await EvaluateAsync(context, collectionAssignmentNode.Value);
list[index] = valueValue;
return;
}
else
{
throw new ArgumentException($"解析{collectionValue}节点时,左值并非有效集合。");
}
}
}
#endregion
throw new ArgumentException($"解析{collectionValue}节点时,左值并非有效集合。");
}
/// <summary>
/// 缓存method委托

View File

@@ -174,6 +174,15 @@ namespace Serein.Script
return nextToken; // 返回下一个 token
}
/// <summary>
/// 重置Lexer
/// </summary>
public void Reset()
{
this._row = 0;
this._index = 0;
}
/// <summary>
/// 根据 token 重置Lexer
/// </summary>
@@ -184,6 +193,7 @@ namespace Serein.Script
this._index = token.StartIndex;
}
internal Token NextToken()
{

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,7 @@
using Serein.Library;
using Serein.Library.Utils;
using Serein.Script.Node;
using Serein.Script.Node.FlowControl;
using Serein.Script.Symbol;
using System;
using System.Collections.Generic;
@@ -30,9 +31,21 @@ namespace Serein.Script
}
public void LoadSymbol(Dictionary<string,Type> identifierNodes)
{
foreach(var kvp in identifierNodes)
{
var name = kvp.Key;
var type = kvp.Value;
var identifierNode = new IdentifierNode(name);
NodeSymbolInfos[identifierNode] = type;
}
}
public void AnalysisProgramNode(ProgramNode astNode)
{
NodeSymbolInfos.Clear();
//NodeSymbolInfos.Clear();
for (int i = 0; i < astNode.Statements.Count; i++)
{
var node = astNode.Statements[i];
@@ -59,103 +72,6 @@ namespace Serein.Script
/// <summary>
/// 类型分析
/// </summary>
/// <param name="node"></param>
/// <exception cref="NotImplementedException"></exception>
private void Analysis1(ASTNode node)
{
switch (node)
{
case ProgramNode programNode: // 程序开始节点
break;
case ReturnNode returnNode: // 程序退出节点
Analysis(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浮点数值字面量
Analysis(node);
break;
case IdentifierNode identifierNode: // 变量定义
void AnalysisIdentifierNode(IdentifierNode identifierNode)
{
Analysis(identifierNode); // 解析变量定义的类型
}
AnalysisIdentifierNode(identifierNode);
break;
case IfNode ifNode: // if语句结构
void AnalysisIfNode(IfNode ifNode)
{
Analysis(ifNode);
}
AnalysisIfNode(ifNode);
break;
case WhileNode whileNode: // while语句结构
void AnalysisWhileNode(WhileNode whileNode)
{
Analysis(whileNode);
}
AnalysisWhileNode(whileNode);
break;
case AssignmentNode assignmentNode: // 对象赋值语句let x;默认赋值null。默认类型object
void AnalysisAssignmentNode(AssignmentNode assignmentNode)
{
Analysis(assignmentNode);
}
AnalysisAssignmentNode(assignmentNode);
break;
case BinaryOperationNode binaryOperationNode: // 二元运算操作
void AnalysisBinaryOperationNode(BinaryOperationNode binaryOperationNode)
{
Analysis(binaryOperationNode);
}
AnalysisBinaryOperationNode(binaryOperationNode);
break;
case CollectionIndexNode collectionIndexNode: // 集合类型操作
void AnalysisCollectionIndexNode(CollectionIndexNode collectionIndexNode)
{
Analysis(collectionIndexNode);
}
AnalysisCollectionIndexNode(collectionIndexNode);
break;
case ClassTypeDefinitionNode classTypeDefinitionNode: // 类型定义
Analysis(classTypeDefinitionNode);
break;
case ObjectInstantiationNode objectInstantiationNode: // 类型实例化
Analysis(objectInstantiationNode);
break;
case ObjectMemberExpressionNode objectMemberExpressionNode: // 类型表达式(链式调用)
Analysis(objectMemberExpressionNode);
break;
case MemberAccessNode memberAccessNode: // 对象成员访问
Analysis(memberAccessNode);
break;
case MemberAssignmentNode memberAssignmentNode: // 对象成员赋值
void AnalysisMemberAssignmentNode(MemberAssignmentNode memberAssignmentNode)
{
Analysis(memberAssignmentNode);
}
AnalysisMemberAssignmentNode(memberAssignmentNode);
break;
case MemberFunctionCallNode memberFunctionCallNode: // 对象方法调用
Analysis(memberFunctionCallNode);
break;
case FunctionCallNode functionCallNode: // 外部挂载的函数调用
Analysis(functionCallNode);
break;
default: // 未定义的节点类型
break;
}
}
/// <summary>
/// 类型获取
/// </summary>
@@ -302,6 +218,20 @@ namespace Serein.Script
return resultType;
}
return AnalysisCollectionIndexNode(collectionIndexNode);
case CollectionAssignmentNode collectionAssignmentNode: // 集合赋值操作
Type AnalysisCollectionAssignmentNode(CollectionAssignmentNode collectionAssignmentNode)
{
var resultType = Analysis(collectionAssignmentNode.Collection); // 分析集合返回返回类型
var valueType = Analysis(collectionAssignmentNode.Value); // 分析赋值的类型
if (!resultType.IsAssignableFrom(valueType))
throw new Exception($"类型 {resultType} 不支持索引操作");
NodeSymbolInfos[collectionAssignmentNode.Collection] = resultType;
NodeSymbolInfos[collectionAssignmentNode.Value] = valueType;
NodeSymbolInfos[collectionAssignmentNode] = typeof(void); // 赋值语句不产生类型
return typeof(void);
}
return AnalysisCollectionAssignmentNode(collectionAssignmentNode);
case ClassTypeDefinitionNode classTypeDefinitionNode: // 类型定义
Type AnalysisClassTypeDefinitionNode(ClassTypeDefinitionNode classTypeDefinitionNode)
{
@@ -331,18 +261,18 @@ namespace Serein.Script
return resultType;
}
return AnalysisObjectInstantiationNode(objectInstantiationNode);
case ObjectMemberExpressionNode objectMemberExpressionNode: // 类型表达式(链式调用)
Type AnalysisObjectMemberExpressionNode(ObjectMemberExpressionNode objectMemberExpressionNode)
case ExpressionNode expressionNode: // 类型表达式(链式调用)
Type AnalysisObjectMemberExpressionNode(ExpressionNode expressionNode)
{
// 1. 对象成员获取 MemberAccessNode
// 2. 对象方法调用 MemberFunctionCallNode
// 3. 对象集合成员获取 CollectionIndexNode
Type? resultType = Analysis(objectMemberExpressionNode.Value);
NodeSymbolInfos[objectMemberExpressionNode.Value] = resultType;
NodeSymbolInfos[objectMemberExpressionNode] = resultType;
Type? resultType = Analysis(expressionNode.Value);
NodeSymbolInfos[expressionNode.Value] = resultType;
NodeSymbolInfos[expressionNode] = resultType;
return resultType;
}
return AnalysisObjectMemberExpressionNode(objectMemberExpressionNode);
return AnalysisObjectMemberExpressionNode(expressionNode);
case MemberAccessNode memberAccessNode: // 对象成员访问
Type AnalysisMemberAccessNode(MemberAccessNode memberAccessNode)
{
@@ -416,6 +346,106 @@ namespace Serein.Script
}
/// <summary>
/// 类型分析
/// </summary>
/// <param name="node"></param>
/// <exception cref="NotImplementedException"></exception>
private void Analysis1(ASTNode node)
{
switch (node)
{
case ProgramNode programNode: // 程序开始节点
break;
case ReturnNode returnNode: // 程序退出节点
Analysis(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浮点数值字面量
Analysis(node);
break;
case IdentifierNode identifierNode: // 变量定义
void AnalysisIdentifierNode(IdentifierNode identifierNode)
{
Analysis(identifierNode); // 解析变量定义的类型
}
AnalysisIdentifierNode(identifierNode);
break;
case IfNode ifNode: // if语句结构
void AnalysisIfNode(IfNode ifNode)
{
Analysis(ifNode);
}
AnalysisIfNode(ifNode);
break;
case WhileNode whileNode: // while语句结构
void AnalysisWhileNode(WhileNode whileNode)
{
Analysis(whileNode);
}
AnalysisWhileNode(whileNode);
break;
case AssignmentNode assignmentNode: // 对象赋值语句let x;默认赋值null。默认类型object
void AnalysisAssignmentNode(AssignmentNode assignmentNode)
{
Analysis(assignmentNode);
}
AnalysisAssignmentNode(assignmentNode);
break;
case BinaryOperationNode binaryOperationNode: // 二元运算操作
void AnalysisBinaryOperationNode(BinaryOperationNode binaryOperationNode)
{
Analysis(binaryOperationNode);
}
AnalysisBinaryOperationNode(binaryOperationNode);
break;
case CollectionIndexNode collectionIndexNode: // 集合类型操作
void AnalysisCollectionIndexNode(CollectionIndexNode collectionIndexNode)
{
Analysis(collectionIndexNode);
}
AnalysisCollectionIndexNode(collectionIndexNode);
break;
case ClassTypeDefinitionNode classTypeDefinitionNode: // 类型定义
Analysis(classTypeDefinitionNode);
break;
case ObjectInstantiationNode objectInstantiationNode: // 类型实例化
Analysis(objectInstantiationNode);
break;
case ExpressionNode expressionNode: // 类型表达式(链式调用)
Analysis(expressionNode.Value);
break;
case MemberAccessNode memberAccessNode: // 对象成员访问
Analysis(memberAccessNode);
break;
case MemberAssignmentNode memberAssignmentNode: // 对象成员赋值
void AnalysisMemberAssignmentNode(MemberAssignmentNode memberAssignmentNode)
{
Analysis(memberAssignmentNode);
}
AnalysisMemberAssignmentNode(memberAssignmentNode);
break;
case MemberFunctionCallNode memberFunctionCallNode: // 对象方法调用
Analysis(memberFunctionCallNode);
break;
case FunctionCallNode functionCallNode: // 外部挂载的函数调用
Analysis(functionCallNode);
break;
default: // 未定义的节点类型
break;
}
}
private void Analysis2(ASTNode node)
{
switch (node)
@@ -450,13 +480,15 @@ namespace Serein.Script
break;
case BinaryOperationNode binaryOperationNode: // 二元运算操作
break;
case CollectionAssignmentNode collectionAssignmentNode:
break;
case CollectionIndexNode collectionIndexNode: // 集合类型操作
break;
case ClassTypeDefinitionNode classTypeDefinitionNode: // 类型定义
break;
case ObjectInstantiationNode objectInstantiationNode: // 类型实例化
break;
case ObjectMemberExpressionNode objectMemberExpressionNode: // 类型表达式(链式调用)
case ExpressionNode expressionNode: // 类型表达式(链式调用)
break;
case MemberAccessNode memberAccessNode: // 对象成员访问
break;
@@ -472,6 +504,9 @@ namespace Serein.Script
}
/// <summary>
/// 获取某个集合类型支持的索引参数类型
/// </summary>