mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-03-10 11:40:48 +08:00
为Serein.Script增加类型分析,增加了更加详细的Number类型节点,优化了对象节点的链式表达式,修复了Lexer分析词法时,部分Token代码属性错误的问题。
This commit is contained in:
@@ -3,9 +3,11 @@ using Serein.Library;
|
||||
using Serein.Library.Utils;
|
||||
using Serein.Script.Node;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Serein.Script
|
||||
{
|
||||
@@ -30,8 +32,9 @@ namespace Serein.Script
|
||||
/// 解析脚本并返回 AST(抽象语法树)根节点。
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ASTNode Parse()
|
||||
public ProgramNode Parse()
|
||||
{
|
||||
|
||||
return Program();
|
||||
}
|
||||
|
||||
@@ -43,7 +46,7 @@ namespace Serein.Script
|
||||
/// 解析整个程序,直到遇到文件结尾(EOF)为止。
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private ASTNode Program()
|
||||
private ProgramNode Program()
|
||||
{
|
||||
Statements.Clear();
|
||||
while (_currentToken.Type != TokenType.EOF)
|
||||
@@ -59,7 +62,6 @@ namespace Serein.Script
|
||||
var programNode = new ProgramNode(Statements);
|
||||
programNode.SetTokenInfo(_currentToken); // 程序节点,包含所有解析的语句列表
|
||||
|
||||
SereinScriptTypeAnalysis typeAnalysis = new SereinScriptTypeAnalysis(programNode);
|
||||
return programNode;
|
||||
|
||||
/*if (astNode is ClassTypeDefinitionNode)
|
||||
@@ -135,6 +137,7 @@ namespace Serein.Script
|
||||
if (_currentToken.Type == TokenType.Null)
|
||||
{
|
||||
// 处理 null 语句
|
||||
return BooleanExpression();
|
||||
return Expression();
|
||||
}
|
||||
|
||||
@@ -157,7 +160,254 @@ namespace Serein.Script
|
||||
/// <returns></returns>
|
||||
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();
|
||||
if (_tempToken.Type == TokenType.ParenthesisLeft)
|
||||
@@ -168,6 +418,7 @@ namespace Serein.Script
|
||||
else if (_tempToken.Type == TokenType.Dot)
|
||||
{
|
||||
// 对象成员的获取
|
||||
|
||||
return ParseMemberAccessOrAssignment();
|
||||
}
|
||||
else if (_tempToken.Type == TokenType.SquareBracketsLeft)
|
||||
@@ -213,7 +464,8 @@ namespace Serein.Script
|
||||
{
|
||||
//_currentToken = _lexer.NextToken(); // 消耗操作符
|
||||
//_currentToken = _lexer.NextToken(); // 消耗操作符
|
||||
valueNode = Expression();
|
||||
valueNode = BooleanExpression();
|
||||
//valueNode = Expression();
|
||||
}
|
||||
else if (_tempToken.Type == TokenType.ParenthesisLeft)
|
||||
{
|
||||
@@ -224,9 +476,11 @@ namespace Serein.Script
|
||||
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)
|
||||
{
|
||||
@@ -253,7 +507,7 @@ namespace Serein.Script
|
||||
{
|
||||
|
||||
_currentToken = _lexer.NextToken(); // Consume "let"
|
||||
string variable = _currentToken.Value.ToString(); // 变量名称
|
||||
string variableName = _currentToken.Value.ToString(); // 变量名称
|
||||
_currentToken = _lexer.NextToken(); // Consume identifier
|
||||
ASTNode value;
|
||||
AssignmentNode assignmentNode;
|
||||
@@ -261,7 +515,8 @@ namespace Serein.Script
|
||||
{
|
||||
// 定义一个变量,初始值为 null
|
||||
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信息
|
||||
}
|
||||
else
|
||||
@@ -272,8 +527,10 @@ namespace Serein.Script
|
||||
throw new Exception("Expected '=' after variable name");
|
||||
_currentToken = _lexer.NextToken(); // 消耗操作符(“=”)
|
||||
var nodeToken = _currentToken;
|
||||
value = Expression(); // 解析获取赋值表达式
|
||||
assignmentNode = new AssignmentNode(variable, value); // 生成node
|
||||
value = BooleanExpression(); // 解析获取赋值表达式
|
||||
//value = Expression(); // 解析获取赋值表达式
|
||||
var variableNode = new IdentifierNode(variableName).SetTokenInfo(_currentToken);
|
||||
assignmentNode = new AssignmentNode(variableNode, value); // 生成node
|
||||
assignmentNode.SetTokenInfo(nodeToken); // 设置token信息
|
||||
_currentToken = _lexer.NextToken(); // 消耗分号
|
||||
}
|
||||
@@ -316,7 +573,10 @@ namespace Serein.Script
|
||||
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(); // 消耗类型
|
||||
var fieldName = _currentToken.Value.ToString(); // 获取定义的类名
|
||||
_currentToken = _lexer.NextToken(); // 消耗字段名称
|
||||
@@ -334,7 +594,9 @@ namespace Serein.Script
|
||||
|
||||
}
|
||||
_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);
|
||||
_currentToken.Code = typeDefinitionCode;
|
||||
node.SetTokenInfo(_currentToken);
|
||||
@@ -361,7 +623,8 @@ namespace Serein.Script
|
||||
var arguments = new List<ASTNode>();
|
||||
while (_currentToken.Type != TokenType.ParenthesisRight)
|
||||
{
|
||||
arguments.Add(Expression()); // 获取参数表达式
|
||||
//arguments.Add(Expression()); // 获取参数表达式
|
||||
arguments.Add(BooleanExpression()); // 获取参数表达式
|
||||
if (_currentToken.Type == TokenType.Comma)
|
||||
{
|
||||
_currentToken = _lexer.NextToken(); // consume ","
|
||||
@@ -383,17 +646,40 @@ namespace Serein.Script
|
||||
|
||||
string collectionName = _currentToken.Value.ToString();
|
||||
//_lexer.NextToken(); // consume "["
|
||||
_currentToken = _lexer.NextToken(); // consume identifier
|
||||
_currentToken = _lexer.NextToken(); // 消耗数组名称 identifier
|
||||
// ParenthesisLeft
|
||||
if (_currentToken.Type != TokenType.SquareBracketsLeft)
|
||||
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 "]"
|
||||
return new CollectionIndexNode(identifierNode,indexValue).SetTokenInfo(_currentToken);
|
||||
_currentToken = _lexer.NextToken(); // 消耗 "]"
|
||||
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>
|
||||
@@ -425,7 +711,10 @@ namespace Serein.Script
|
||||
// 成员赋值 obj.Member = xxx;
|
||||
_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);
|
||||
}
|
||||
else
|
||||
@@ -465,27 +754,28 @@ namespace Serein.Script
|
||||
private ASTNode ParseMemberFunctionCall(ASTNode targetNode)
|
||||
{
|
||||
string functionName = _currentToken.Value.ToString(); // 函数名称
|
||||
_currentToken = _lexer.NextToken(); // consume identifier
|
||||
_currentToken = _lexer.NextToken(); // 消耗函数名称
|
||||
|
||||
if (_currentToken.Type != TokenType.ParenthesisLeft)
|
||||
throw new Exception("Expected '(' after function name");
|
||||
|
||||
_currentToken = _lexer.NextToken(); // consume "("
|
||||
_currentToken = _lexer.NextToken(); // 消耗 "("
|
||||
|
||||
var arguments = new List<ASTNode>();
|
||||
while (_currentToken.Type != TokenType.ParenthesisRight)
|
||||
{
|
||||
// 获取参数表达式
|
||||
var arg = Expression();
|
||||
_currentToken = _lexer.NextToken(); // consume arg
|
||||
//var arg = Expression();
|
||||
var arg = BooleanExpression();
|
||||
_currentToken = _lexer.NextToken(); // 消耗参数 arg
|
||||
arguments.Add(arg); // 添加到参数列表
|
||||
if (_currentToken.Type == TokenType.Comma)
|
||||
{
|
||||
_currentToken = _lexer.NextToken(); // consume ","
|
||||
_currentToken = _lexer.NextToken(); // 消耗参数分隔符 ","
|
||||
}
|
||||
if (_currentToken.Type == TokenType.Semicolon)
|
||||
{
|
||||
break; // consume ";"
|
||||
break; // 消耗 ";"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -510,25 +800,37 @@ namespace Serein.Script
|
||||
|
||||
_currentToken = _lexer.NextToken(); // consume "("
|
||||
|
||||
var arguments = new List<ASTNode>();
|
||||
bool isBreak = false;
|
||||
while (_currentToken.Type != TokenType.ParenthesisRight)
|
||||
var arguments = new List<ASTNode>();
|
||||
// 获取参数
|
||||
while (true)// _currentToken.Type != TokenType.ParenthesisRight
|
||||
{
|
||||
var arg = Expression(); // 获取参数表达式
|
||||
_currentToken = _lexer.NextToken(); // consume arg
|
||||
//var arg = Expression(); // 获取参数表达式
|
||||
var arg = BooleanExpression(); // 获取参数表达式
|
||||
arguments.Add(arg);
|
||||
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 ";"
|
||||
}
|
||||
/*if (_currentToken.Type == TokenType.Semicolon) // 提前结束
|
||||
{
|
||||
arguments.Add(arg);
|
||||
isBreak = true;
|
||||
break; // consume ";"
|
||||
}*/
|
||||
//_currentToken = _lexer.NextToken(); // consume arg
|
||||
}
|
||||
if(!isBreak)
|
||||
_currentToken = _lexer.NextToken(); // consume ")"
|
||||
//if(!isBreak)
|
||||
// _currentToken = _lexer.NextToken(); // consume ")"
|
||||
|
||||
|
||||
//var node = Statements[^1];
|
||||
@@ -559,7 +861,8 @@ namespace Serein.Script
|
||||
{
|
||||
return new ReturnNode().SetTokenInfo(_currentToken); // 返回空的 ReturnNode
|
||||
}
|
||||
var resultValue = Expression(); // 获取返回值表达式
|
||||
var resultValue = BooleanExpression(); // 获取返回值表达式
|
||||
//var resultValue = Expression(); // 获取返回值表达式
|
||||
_currentToken = _lexer.NextToken();
|
||||
return new ReturnNode(resultValue).SetTokenInfo(_currentToken);
|
||||
}
|
||||
@@ -574,7 +877,8 @@ namespace Serein.Script
|
||||
{
|
||||
_currentToken = _lexer.NextToken(); // Consume "if"
|
||||
_currentToken = _lexer.NextToken(); // Consume "("
|
||||
ASTNode condition = Expression();
|
||||
ASTNode condition = BooleanExpression();
|
||||
//ASTNode condition = Expression();
|
||||
_currentToken = _lexer.NextToken(); // Consume ")"
|
||||
|
||||
// 确保遇到左大括号 { 后进入代码块解析
|
||||
@@ -590,6 +894,10 @@ namespace Serein.Script
|
||||
while (_currentToken.Type != TokenType.BraceRight && _currentToken.Type != TokenType.EOF)
|
||||
{
|
||||
var astNode = Statement(); // 解析 if 分支中的语句
|
||||
while (_currentToken.Type == TokenType.Semicolon)
|
||||
{
|
||||
_currentToken = _lexer.NextToken();
|
||||
}
|
||||
if (astNode != null)
|
||||
{
|
||||
trueBranch.Add(astNode); // 将 if 分支的语句添加到 trueBranch 中
|
||||
@@ -608,6 +916,10 @@ namespace Serein.Script
|
||||
while (_currentToken.Type != TokenType.BraceRight && _currentToken.Type != TokenType.EOF)
|
||||
{
|
||||
var astNode = Statement(); // 解析 else 分支中的语句
|
||||
while (_currentToken.Type == TokenType.Semicolon)
|
||||
{
|
||||
_currentToken = _lexer.NextToken();
|
||||
}
|
||||
if (astNode != null)
|
||||
{
|
||||
falseBranch.Add(astNode); // 将 else 分支的语句添加到 falseBranch 中
|
||||
@@ -633,7 +945,8 @@ namespace Serein.Script
|
||||
{
|
||||
_currentToken = _lexer.NextToken(); // Consume "while"
|
||||
_currentToken = _lexer.NextToken(); // Consume "("
|
||||
ASTNode condition = Expression();
|
||||
ASTNode condition = BooleanExpression();
|
||||
//ASTNode condition = Expression();
|
||||
_currentToken = _lexer.NextToken(); // Consume ")"
|
||||
_currentToken = _lexer.NextToken(); // Consume "{"
|
||||
List<ASTNode> body = new List<ASTNode>();
|
||||
@@ -645,43 +958,131 @@ namespace Serein.Script
|
||||
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>
|
||||
/// <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>
|
||||
/// <returns></returns>
|
||||
private ASTNode Expression()
|
||||
{
|
||||
ASTNode left = Term();
|
||||
while (_currentToken.Type == TokenType.Operator && (
|
||||
_currentToken.Value == "+" || _currentToken.Value == "-" ||
|
||||
_currentToken.Value == "*" || _currentToken.Value == "/"))
|
||||
|
||||
while (_currentToken.Type == TokenType.Operator &&
|
||||
(_currentToken.Value == "+" || _currentToken.Value == "-"))
|
||||
{
|
||||
string op = _currentToken.Value.ToString();
|
||||
string op = _currentToken.Value;
|
||||
_currentToken = _lexer.NextToken();
|
||||
ASTNode right = Term();
|
||||
left = new BinaryOperationNode(left, op, right).SetTokenInfo(_currentToken);
|
||||
}
|
||||
return left;
|
||||
|
||||
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 == "!="))
|
||||
(_currentToken.Value == "*" || _currentToken.Value == "/"))
|
||||
{
|
||||
string op = _currentToken.Value.ToString();
|
||||
string op = _currentToken.Value;
|
||||
_currentToken = _lexer.NextToken();
|
||||
ASTNode right = Factor();
|
||||
left = new BinaryOperationNode(left, op, right).SetTokenInfo(_currentToken);
|
||||
}
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
@@ -692,6 +1093,8 @@ namespace Serein.Script
|
||||
/// <exception cref="Exception"></exception>
|
||||
private ASTNode Factor()
|
||||
{
|
||||
|
||||
|
||||
#region 返回字面量
|
||||
if (_currentToken.Type == TokenType.Null)
|
||||
{
|
||||
@@ -757,11 +1160,122 @@ namespace Serein.Script
|
||||
}
|
||||
#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(); // 消耗 "("
|
||||
var expr = Expression();
|
||||
var expr = BooleanExpression();
|
||||
//var expr = Expression();
|
||||
if (_currentToken.Type != TokenType.ParenthesisRight)
|
||||
throw new Exception("非预期的符号,预期符号为\")\"。");
|
||||
_currentToken = _lexer.NextToken(); // 消耗 ")"
|
||||
@@ -775,38 +1289,10 @@ namespace Serein.Script
|
||||
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} " );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user