using Serein.Library.Utils; using Serein.Script.Node; using Serein.Script.Node.FlowControl; using System.Collections; namespace Serein.Script { /// /// SereinScriptParser 用于解析 Serein 脚本语言的语法。 /// public ref struct SereinScriptParser { private SereinScriptLexer _lexer; private Token _currentToken; public SereinScriptParser() { } /// /// 解析脚本并返回 AST(抽象语法树)根节点。 /// /// public ProgramNode Parse(string script) { _lexer = new SereinScriptLexer(script); // 语法分析 _currentToken = _lexer.NextToken(); return Program(); } /// /// 命名空间 /// public List UsingNamespaces { get; } = new List(); /// /// 程序节点 /// public List Statements { get; } = new List(); /// /// 解析整个程序,直到遇到文件结尾(EOF)为止。 /// /// private ProgramNode Program() { Statements.Clear(); while (_currentToken.Type != TokenType.EOF) { var astNode = Statement(); // 解析单个语句 if (astNode == null) { continue; } Statements.Add(astNode); // 将解析得到的 AST 节点添加到语句列表中 } var programNode = new ProgramNode(Statements); programNode.SetTokenInfo(_currentToken); // 程序节点,包含所有解析的语句列表 return programNode; /*if (astNode is ClassTypeDefinitionNode) { statements = [astNode, ..statements]; // 类型定义置顶 } else { statements.Add(astNode); }*/ } private ASTNode Statement() { if (_currentToken.Type == TokenType.Semicolon) { NextToken(); // 消耗 ";" return null; } if (_currentToken.Type == TokenType.Identifier) { /* 赋值语句与一般语句的表达形式 1. 赋值语句: 目标对象 表达式获取 Target() | = | Expression() | | = | variable; | (变量) | = | value; | 显式设置的字面量。 | = | obj.Value...; | obj为之前的上下文中出现过的变量,调用表达式包含对象成员数组、方法 | = | array[...]; | array为之前的上下文中出现过的变量。 | = | array[...].Value...; | array为之前的上下文中出现过的变量。调用表达式包含对象成员数组、方法 | = | new Class(...); | 实例化类型,包含构造函数 补充:Target() 可能的成员 1. variable 2. obj.Value... 3. array[index] 4. array[index].Value... 2. 一般语句(方法调用): 1. localFunc(...); 2. obj....Func(...); 3. array[]....Func(...); */ #region 分析是赋值语句还是一般语句。赋值语句中间存在 = 操作符,一般语句不存在。 var backupToken = _currentToken; // 保存当前token var peekCount = 0; // peek次数 var isAssignment = false; // 指示操作类型,true代表赋值语句,false代表一般语句 while (true) { // 分析阶段,不移动token var peekToken = _lexer.PeekToken(peekCount++); // 预览下一个节点 if (peekToken.Type == TokenType.Semicolon) break; // 遇到分号,结束词法分析 if (JudgmentOperator(peekToken, "=")) { isAssignment = true; break; } if(peekCount > 3999) { throw new Exception("解析异常,peek次数过多,可能是解析器出了bug"); } } #endregion #region 生成赋值语句/一般语句的ASTNode if (isAssignment) { // 以赋值语句的形式进行处理 var assignmentNode = ParseAssignmentNode(); // 解析复制表达式 //if(_currentToken.Type == TokenType.Semicolon) NextToken();// 消耗 ";" return assignmentNode; } else { // 以一般语句的形式进行处理,可当作表达式进行解析 var targetNode = ParserExpression(); //if (_currentToken.Type == TokenType.Semicolon) NextToken();// 消耗 ";" return targetNode; } #endregion } else if (JudgmentKeyword("using")) // 定义对象 { var usingNode = ParseUsingNode(); UsingNamespaces.Add(usingNode.Namespace); return usingNode; } else if (JudgmentKeyword("class")) // 定义对象 { var classDefinitionNode = ParseClassDefinitionNode(); return classDefinitionNode; } else if (JudgmentKeyword("return")) // 返回语句 { var returnNode = ParseReturnNode(); return returnNode; } else if (_currentToken.Type == TokenType.Keyword) // 语句块 { /* 可能的关键字 1. if()...else... 2. while(){...} */ if (JudgmentKeyword("if")) { return ParseIf(); } else if (JudgmentKeyword("while")) { return ParseWhile(); } } throw new Exception($"解析异常。{_currentToken.ToString()}"); /*else { // 为避免解析异常,除了 Statement() 方法以外,其它地方不需要对 TokenType.Semicolon 进行处理 throw new Exception("解析异常, Statement() 方法以外的地方处理了 TokenType.Semicolon "); }*/ } /// /// 解析表达式根节点 /// /// private ASTNode ParserExpRootNode() { var name = _currentToken.Value; foreach(var nsp in UsingNamespaces) { var fullName = $"{nsp}.{name}"; var type = SereinScriptTypeAnalysis.GetTypeOfString(fullName); if (type is null) { continue; } var typeNode = new TypeNode(fullName).SetTokenInfo(_currentToken); return typeNode; } return new IdentifierNode(_currentToken.Value).SetTokenInfo(_currentToken); } /// /// 解析赋值语句 /// /// public ASTNode ParseAssignmentNode() { /* 解析赋值语句 赋值语句: 目标对象 表达式获取 Target() | = | Expression() | | = | variable; | (变量) | = | value; | 显式设置的字面量。 | = | obj.Value...; | obj为之前的上下文中出现过的变量,调用表达式包含对象成员数组、方法 | = | array[...]; | array为之前的上下文中出现过的变量。 | = | array[...].Value...; | array为之前的上下文中出现过的变量。调用表达式包含对象成员数组、方法 | = | new Class(...); | 实例化类型,包含构造函数 | = | [v1, v2, v3]; | 定义数组 补充:Target() 可能的成员 1. variable 2. obj.Value... 3. array[index] 4. array[index].Value... 循环获取token判断 如果是 "." ,代表需要从对象中获取成员(属性、方法调用、数组) 如果是 "(" ,代表调用挂载的本地方法 如果是 "[" ,代表需要获取数组索引 如果是 "=" ,代表是变量赋值,退出循环 */ /* 获取成员的方式有三种: * 1. 获取成员 => PeekToken.Type = TokenType.Dot * 2. 获取集合 => PeekToken.Type = TokenType.SquareBracketsLeft * 3. 调用成员方法 => PeekToken.Type = TokenType.ParenthesisLeft * * */ //if (JudgmentOperator(_currentToken, "=")) break; // 退出 //var tempPeekToken = _lexer.PeekToken(); var targetNode = ParserExpRootNode(); // 生成 Tagget 标记节点 //var targetNode = new IdentifierNode(_currentToken.Value).SetTokenInfo(_currentToken); // 生成 Tagget 标记节点 List nodes = [targetNode]; ASTNode? source; var peekNextToken = _lexer.PeekToken(); // 预览下个标识符 if (JudgmentOperator(peekNextToken, "=")) { NextToken(); } else { if (peekNextToken.Type == TokenType.ParenthesisLeft) { // 解析调用挂载方法 // ... = variable()()(); // 暂时不支持柯里化调用... = variable()()(); var functionCallNode = ParseFunctionCallNode(); if (_currentToken.Type == TokenType.Semicolon) { return functionCallNode; } targetNode = functionCallNode; } else if (peekNextToken.Type == TokenType.SquareBracketsLeft) { // 解析集合获取 var collectionIndexNode = ParseCollectionIndexNode(targetNode); if (_currentToken.Type == TokenType.Semicolon) { return collectionIndexNode; } targetNode = collectionIndexNode; } else if (peekNextToken.Type == TokenType.Dot) { NextToken(); } nodes = [targetNode]; // 开始解析 while (true) { if (JudgmentOperator(_currentToken, "=")) break; // 退出 var peekToken = _currentToken; // _lexer.PeekToken(); // 获取下一个token开始判断 source = nodes[^1]; // 重定向节点 if (peekToken.Type == TokenType.Identifier) throw new Exception($"无法从对象获取成员,当前Token类型为 {peekToken.Type}。"); if (peekToken.Type == TokenType.Dot) // 从对象获取 { /* * 获取成员的方式有三种: * 1. 获取成员 => PeekToken.Type = TokenType.Dot * 2. 获取集合 => PeekToken.Type = TokenType.SquareBracketsLeft * 3. 调用成员方法 => PeekToken.Type = TokenType.ParenthesisLeft */ NextToken(); // 消耗 "." 并获取下一个成员。 var peekToken3 = _lexer.PeekToken(); if (JudgmentOperator(peekToken3, "=")) { var tempMemberAccessNode = ParseMemberAccessNode(source); // 获取对象中的成员 source.Value... nodes.Add(tempMemberAccessNode); break; } ASTNode tempNode = peekToken3.Type switch { TokenType.Dot or TokenType.Semicolon or TokenType.ParenthesisRight => ParseMemberAccessNode(source), // 获取对象中的成员 source.Value... TokenType.SquareBracketsLeft => ParseCollectionIndexNode(source), // 获取集合中的元素 source[index].... TokenType.ParenthesisLeft => ParseMemberFunctionCallNode(source), // 获取需要调用的方法 source(arg1,arg2...)... _ => throw new Exception($"无法从对象获取成员,当前Token类型为 {peekToken.Type}。") }; nodes.Add(tempNode); continue; // 结束当前轮次的token判断 } else if (peekToken.Type == TokenType.ParenthesisLeft) // 调用对象方法 { var memberFunctionCallNode = ParseMemberFunctionCallNode(source); nodes.Add(memberFunctionCallNode); continue; // 结束当前轮次的token判断 } else if (peekToken.Type == TokenType.SquareBracketsLeft) // 集合获取 { var collectionIndexNode = ParseCollectionIndexNode(source); nodes.Add(collectionIndexNode); continue; // 结束当前轮次的token判断 } } } targetNode = nodes[^1]; if (targetNode is FunctionCallNode or MemberFunctionCallNode) { throw new Exception($"赋值语句左值部分不允许为方法调用,{targetNode.Code}"); } else { var c = _currentToken; // 反转赋值。 NextToken(); // 消耗 "=" 并获取赋值语句的右值表达式。 ASTNode valueNode = ParserExpression(); if (targetNode is MemberAccessNode memberAccessNode) { MemberAssignmentNode memberAssignmentNode = new MemberAssignmentNode(memberAccessNode.Object, memberAccessNode.MemberName, valueNode); return memberAssignmentNode; } else if (targetNode is CollectionIndexNode collectionIndeNode) { CollectionAssignmentNode collectionAssignmentNode = new CollectionAssignmentNode(collectionIndeNode, valueNode); return collectionAssignmentNode; } else { // 获取赋值节点 AssignmentNode assignmentNode = new AssignmentNode(target: targetNode, value: valueNode); return assignmentNode; } } } /// /// (不处理分号)解析获取“集合获取”AST节点 /// /// /// public MemberAccessNode ParseMemberAccessNode(ASTNode sourceNode) { string memberName = _currentToken.Value; // 成员名称 var memberAccessNode = new MemberAccessNode(sourceNode, memberName); NextToken(); // 消耗成员名称 memberAccessNode.SetTokenInfo(_currentToken); return memberAccessNode; } /// /// (不处理分号)解析获取“集合获取”AST节点 /// /// /// public CollectionIndexNode ParseCollectionIndexNode(ASTNode sourceNode) { var collectionToken = _currentToken; if(_currentToken.Type == TokenType.SquareBracketsLeft) { // 集合中获取集合 NextToken(); // 消耗 "[" 集合标识符的左中括号 ASTNode indexNode = ParserExpression(); // 解析获取索引Node NextToken(); // 消耗 "]" 集合标识符的右中括号 if (sourceNode is IdentifierNode) { var collectionIndexNode = new CollectionIndexNode(sourceNode, indexNode); collectionIndexNode.SetTokenInfo(collectionToken); // 表示获取集合第几个索引 return collectionIndexNode; } else { var collectionIndexNode = new CollectionIndexNode(sourceNode, indexNode); collectionIndexNode.SetTokenInfo(collectionToken); // 表示获取集合第几个索引 return collectionIndexNode; } } else { string collectionName = _currentToken.Value; // 集合名称 NextToken(TokenType.SquareBracketsLeft); // 消耗集合名称 NextToken(); // 消耗 "[" 集合标识符的左中括号 ASTNode indexNode = ParserExpression(); // 解析获取索引Node NextToken(); // 消耗 "]" 集合标识符的右中括号 if (sourceNode is IdentifierNode) { var collectionIndexNode = new CollectionIndexNode(sourceNode, indexNode); collectionIndexNode.SetTokenInfo(collectionToken); // 表示获取集合第几个索引 return collectionIndexNode; } else { var memberAccessNode = new MemberAccessNode(sourceNode, collectionName).SetTokenInfo(_currentToken); // 表示集合从上一轮获取到的成员获取 var collectionIndexNode = new CollectionIndexNode(memberAccessNode, indexNode); collectionIndexNode.SetTokenInfo(collectionToken); // 表示获取集合第几个索引 return collectionIndexNode; } } } /// /// (不处理分号)解析获取“对象方法调用”AST节点 /// /// /// public MemberFunctionCallNode ParseMemberFunctionCallNode(ASTNode sourceNode) { string methodName = _currentToken.Value; // 方法名称 NextToken(TokenType.ParenthesisLeft); // 消耗方法名称 List argNodes = []; // 方法参数Node NextToken(); // 消耗 "(" while (_currentToken.Type != TokenType.ParenthesisRight) // 遇到 ")" 表示参数获取完毕 { ASTNode node = ParserArgNode(); // 解析方法调用参数 argNodes.Add(node); if (_currentToken.Type == TokenType.Comma) { NextToken(); // 消耗参数分隔符 "," } } NextToken(); // 消耗 ")" 表示参数获取完毕 var memberFunctionCallNode = new MemberFunctionCallNode(sourceNode, methodName, argNodes); memberFunctionCallNode.SetTokenInfo(_currentToken); return memberFunctionCallNode; // 结束当前轮次的token判断 } /// /// (不处理分号)解析获取“调用挂载的方法”AST节点 /// /// public FunctionCallNode ParseFunctionCallNode() { string functionName = _currentToken.Value; // 方法名称 NextToken(TokenType.ParenthesisLeft); // 消耗方法名称 List argNodes = []; // 方法参数Node、 NextToken(); // 消耗 "(" while (_currentToken.Type != TokenType.ParenthesisRight) // 遇到 ")" 表示参数获取完毕 { ASTNode node = ParserArgNode(); // 解析挂载方法的入参 argNodes.Add(node); if (_currentToken.Type == TokenType.Comma) { NextToken(); // 消耗参数分隔符 "," } } NextToken(); // 消耗 ")" var functionCallNode = new FunctionCallNode(functionName, argNodes); functionCallNode.SetTokenInfo(_currentToken); return functionCallNode; } /// /// (不处理分号,逗号,右括号)用于解析(...) / [...] 中的参数部分。终止条件是 "," 参数分隔符 、")" 方法入参终止符、"]" 数组定义终止符 /// /// public ASTNode ParserArgNode() { ASTNode node = ParserExpression(); // 解析参数 // ParserExpression 会完全解析当前表达式,自动移动到下一个Token,所以需要在这里判断是否符合期望的TokenType if(_currentToken.Type == TokenType.Comma || _currentToken.Type == TokenType.ParenthesisRight || _currentToken.Type == TokenType.SquareBracketsRight) { return node; } throw new Exception($"解析参数节点后,当前Token类型不符合预期,当前类型为 {_currentToken.Type}。"); } /// /// (不处理分号) /// 1. 引入命名空间 /// /// private UsingNode ParseUsingNode() { var startIndex = _lexer.GetIndex(); // 从“using”开始锚定代码范围 NextToken(); // 消耗“using”关键字,获取类名 List namespaceItems = []; while (true) // 遇到 ";" 时结束 { string className = _currentToken.Value; // 命名空间 namespaceItems.Add(className); if (_currentToken.Type == TokenType.Semicolon) { break; } NextToken(); // 命名空间 } var nsp = string.Join('.', namespaceItems); UsingNode usingNode = new UsingNode(nsp); var usingToken = _currentToken; usingToken.Code = _lexer.GetCoreContent(startIndex); // 收集类型定义的代码。 usingNode.SetTokenInfo(usingToken); return usingNode; } /// /// (没有分号)解析类定义 /// /// /// private ASTNode ParseClassDefinitionNode() { /* class [ClassName] { FieldType FieldName1; FieldType FieldName2; FieldType FieldName3; FieldType FieldName4; } */ var coreStartRangeIndex = _lexer.GetIndex(); // 从“class”开始锚定代码范围 if (!JudgmentKeyword("class")) throw new Exception($"解析类型定义节点时,当前Token不为关键字“class”。"); NextToken(TokenType.Identifier); // 消耗“class”关键字,获取类名 string className = _currentToken.Value; // 类型名称 NextToken(TokenType.BraceLeft); // 消耗类型名称,并判断是否为 "{" NextToken(); var classFields = new Dictionary(); // 记录类型中定义的字段 while (_currentToken.Type != TokenType.BraceRight) // 遇到 "}" 时表示类型解析完毕 { // 获取字段的类型、名称,类型允许包含逗号(使用C#中的类型) /* class User { System.Int32 Age; // 等效于 int Age; } 字段解析时的预期顺序: 1 2 3 4 5 6 [id -> dot -> id -> dot -> id] -> id -> Semicolon [ 字段定义 ] 字段名称 解析完成 */ string fieldTypeName = _currentToken.Value; string fieldName; while (true) { var peekToken = _lexer.PeekToken(); if (peekToken.Type == TokenType.Dot) { NextToken(); NextToken(TokenType.Identifier); fieldTypeName = $"{fieldTypeName}.{_currentToken.Value}"; // 向后扩充 continue; } else if (peekToken.Type == TokenType.SquareBracketsLeft) { NextToken(); // 消耗数组类型定义的 "[" NextToken(); // 消耗数组类型定义的 "]" fieldTypeName += "[]"; continue; } else if (peekToken.Type == TokenType.Identifier) { // 尝试解析变量名称 fieldName = peekToken.Value; // 字段名称 NextToken(); // 消耗类型定义的最后一个Token NextToken(TokenType.Semicolon); // 消耗字段名称,如果下一个Token如果不为分号,说明词法异常 break; } } var fieldType = DynamicObjectHelper.GetCacheType(fieldTypeName); // 查询是否在其它脚本中创建过类型 fieldType = fieldType ?? fieldTypeName.ToTypeOfString(); // 如果没有定义过类型,则从c#运行时尝试获取类型 if(fieldType is null) { throw new Exception($"定义类型 {className} 时,解析成员 {fieldName} 失败,没有找到类型 {fieldTypeName}。"); } classFields.Add(fieldName, fieldType); NextToken(); // 当前字段类型定义完毕,消耗";" } var classToken = _currentToken; classToken.Code = _lexer.GetCoreContent(coreStartRangeIndex); // 收集类型定义的代码。 NextToken(); // 当前类型定义完毕,消耗"}" // 词法分析时不应该获取类型,类型应该放在类型分支中进行追踪 var type = DynamicObjectHelper.GetCacheType(className); if(type is null) // 解析时创建类型,因为后续的类型定义中,某个字段可能使用该类型,而解析时需要获取到其类型 { DynamicObjectHelper.CreateTypeWithProperties(classFields, className); } TypeNode classTypeNode = new TypeNode(className); Dictionary propertyTypes = classFields.ToDictionary(f => f.Key, f => new TypeNode(f.Value.FullName)); var classTypeDefinitionNode = new ClassTypeDefinitionNode(propertyTypes, classTypeNode); classTypeDefinitionNode.SetTokenInfo(classToken); return classTypeDefinitionNode; } /// /// 解析 return 语句。 /// /// public ReturnNode ParseReturnNode() { var returnToken = _currentToken; if (!JudgmentKeyword("return")) throw new Exception($"解析返回节点时,当前Token不为关键字“return”。"); NextToken(); // 消耗关键字 ReturnNode returnNode; if (_currentToken.Type == TokenType.Semicolon) { returnNode = new ReturnNode(); // 空返回 } else { var resultValue = BooleanExpression(); // 解析值表达式 returnNode = new ReturnNode(resultValue); // 带值返回 } returnNode.SetTokenInfo(returnToken); if (_currentToken.Type == TokenType.Semicolon) { NextToken(); // 消耗 ";" ,语句完毕 } return returnNode; } /// /// (不处理分号)解析对象实例化行为 /// /// /// public ObjectInstantiationNode ParseObjectInstantiationNode() { // 获取类型名称,类型允许包含逗号(使用C#中的类型) /* new [TypeName]([Exp1],[Exp2]); 类型解析时的预期顺序: 1 2 3 4 5 6 new -> [id -> dot -> id -> dot -> id] -> ParenthesisLeft -> [CtroArg] -> ParenthesisRight -> Semicolon [ 类型定义 ] 括号 "(" 构造入参 括号 ")" 分号,解析完成 */ var instantiationToken = _currentToken; // 第一次进入循环时,会消耗 new 关键字 NextToken(TokenType.Identifier); var typeToken = _currentToken; string typeName = _currentToken.Value; // 类名 List ctorArguments = []; // 构造入参 while (true) { var peekToken = _lexer.PeekToken(); if (peekToken.Type == TokenType.Dot) { NextToken(); NextToken(); typeName = $"{typeName}.{_currentToken.Value}"; // 向后扩充 continue; } else if (peekToken.Type == TokenType.ParenthesisLeft) { // 类名定义完成,解析构造方法入参。 NextToken(); // 消耗 类型Token NextToken(); // 消耗 "(" while (_currentToken.Type != TokenType.ParenthesisRight) // 表示参数获取完毕 { ASTNode node = ParserArgNode(); // 解析构造方法的入参 ctorArguments.Add(node); if(_currentToken.Type == TokenType.Comma) { NextToken(); // 消耗参数分隔符 "," } } NextToken(); // 消耗 ")" break; } else if (peekToken.Type == TokenType.BraceLeft) { NextToken(); // 消耗 类型名称 break; } } TypeNode typeNode = new TypeNode(typeName); typeNode.SetTokenInfo(typeToken); ObjectInstantiationNode objectInstantiationNode = new ObjectInstantiationNode(typeNode, ctorArguments); List ctorAssignmentNodes = new List(); // 构造器赋值 /* 类型构造器 new Type { Value1 = [Exp] , Value2 = [Exp] , } */ if (_currentToken.Type == TokenType.BraceLeft) { NextToken(); // 消耗 "{" string propertyName = ""; Token propertyToken = _currentToken; while( _currentToken.Type != TokenType.BraceRight) { if (_currentToken.Type == TokenType.Identifier) { propertyToken = _currentToken; propertyName = _currentToken.Value; NextToken(); continue; } else if (JudgmentOperator(_currentToken,"=")) { NextToken(); ASTNode value = ParserExpression(); CtorAssignmentNode ctorAssignmentNode = new CtorAssignmentNode(typeNode, propertyName, value); ctorAssignmentNode.SetTokenInfo(propertyToken); ctorAssignmentNodes.Add(ctorAssignmentNode); if(_currentToken .Type == TokenType.Comma) { NextToken(); // 消耗 "," continue; } else if (_currentToken.Type == TokenType.BraceRight) { continue; } } else { throw new Exception($"类型构造器词法分析异常。{_currentToken.ToString()}"); } } NextToken(); // 消耗 "}" objectInstantiationNode.SetCtorAssignments(ctorAssignmentNodes); } objectInstantiationNode.SetTokenInfo(instantiationToken); return objectInstantiationNode; } #region 控制流语句解析 /// /// 解析 if 语句。 /// /// /// private ASTNode ParseIf() { NextToken(TokenType.ParenthesisLeft); // 消耗 "if" NextToken(); // 消耗 "(" ASTNode condition = BooleanExpression(); NextToken(TokenType.BraceLeft); // 消耗 ")" NextToken(); // 消耗 "{" // 解析大括号中的语句 List trueBranch = new List(); List falseBranch = new List(); while (_currentToken.Type != TokenType.BraceRight) { var astNode = Statement(); // 解析 true 分支中的语句 if (astNode != null) { trueBranch.Add(astNode); } } // 确保匹配右大括号 } if (_currentToken.Type != TokenType.BraceRight) { throw new Exception("非预期的标识符 '}' "); } NextToken(); // 消耗 "}" if (_currentToken.Type == TokenType.Keyword && _currentToken.Value == "else") { NextToken(TokenType.BraceLeft); // 消耗 "else" NextToken(); // 消耗 "{" while (_currentToken.Type != TokenType.BraceRight) { var astNode = Statement(); // 解析 else 分支中的语句 if (astNode != null) { falseBranch.Add(astNode); // 将 else 分支的语句添加到 falseBranch 中 } } // 确保匹配右大括号 } if (_currentToken.Type != TokenType.BraceRight) { throw new Exception("非预期的标识符 '}' "); } NextToken(); // 消耗 "}" } return new IfNode(condition, trueBranch, falseBranch).SetTokenInfo(_currentToken); } /// /// 解析 while 循环语句。 /// /// private ASTNode ParseWhile() { NextToken(TokenType.ParenthesisLeft); // 消耗 "while" NextToken(); // 消耗 "(" ASTNode condition = BooleanExpression(); NextToken(TokenType.BraceLeft); // 消耗 ")" NextToken(); // 消耗 "{" List body = new List(); while (_currentToken.Type != TokenType.BraceRight) { var node = Statement(); if (node is not null) { body.Add(node); // 解析循环体中的语句 } } _currentToken = _lexer.NextToken(); // 消耗 "}" return new WhileNode(condition, body).SetTokenInfo(_currentToken); } #endregion #region 表达式解析:BooleanExpression -> ComparisonExpression -> Expression -> Term -> Factor /// /// 解析表达式 /// /// private ASTNode ParserExpression() { // 处理表达式时,从布尔表达式开始。 return BooleanExpression(); } #region 表达式处理 /// /// 布尔表达式 /// /// 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; } /// /// 比较表达式(==, !=, <, <=, >, >=) /// /// 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; } /// /// 加减 /// /// private ASTNode Expression() { ASTNode left = Term(); while (_currentToken.Type == TokenType.Operator && (_currentToken.Value == "+" || _currentToken.Value == "-")) { string op = _currentToken.Value; _currentToken = _lexer.NextToken(); ASTNode right = Term(); left = new BinaryOperationNode(left, op, right).SetTokenInfo(_currentToken); } return left; } /// /// 乘除 /// /// private ASTNode Term() { ASTNode left = Factor(); while (_currentToken.Type == TokenType.Operator && (_currentToken.Value == "*" || _currentToken.Value == "/")) { string op = _currentToken.Value; _currentToken = _lexer.NextToken(); ASTNode right = Factor(); left = new BinaryOperationNode(left, op, right).SetTokenInfo(_currentToken); } return left; } #endregion /// /// 解析因子(Factor),用于处理基本的字面量、标识符、括号表达式等。 /// /// /// private ASTNode Factor() { /* 表达式类型: 1. 赋值语句中的右值 ... = [Exp];(左值不为表达式) 2. 一般语句 [Exp]; 3. 方法中参数 func([Exp1],[Exp2],[Exp3]...) 单个入参 3. 实例化类型 new Class(); 表达式特征: a. 在第 1 次分析中,当 _currentToken.Type 为 Identifier 时,下一个 Token 可能为: 1. TokenType.ParenthesisLeft => 调用本地方法 2. TokenType.Dot => 当前 Toke 代表变量,需要获取对象成员 3. TokenType.ParenthesisLeft => 当前 Token 表示数组对象,索引为 PeekToken(2),根据索引获取成员 4. TokenType.Keyword("new") => 实例化类型 5. TokenType.Semicolon => 表达式结束 b. 在第 N + 1 次分析中,当 _currentToken.Type 为 Identifier 时,下一个 Token 可能为: 1. TokenType.ParenthesisLeft => 以上一次分析得到的 Node 为 Source Object,调用其的方法。 2. TokenType.Dot => 以上一次分析得到的 Node 为 Source Object,需要获取对象成员 3. TokenType.ParenthesisLeft => 以上一次分析得到的 Node 为 Source Object,获取 _currentToken.Value 对应的数组成员,索引为 PeekToken(2),根据索引获取成员 4. TokenType.Keyword("new") => 实例化类型 5. TokenType.Semicolon => 表达式结束 c. 当 _currentToken.Type 为 ParenthesisLeft 时 : 存在嵌套表达式,再次调用 ParserExpression() 方法。 */ // 标识符节点 var factorToken = _currentToken; // 记录一下进入 Factor() 的 Token if (_currentToken.Type == TokenType.Identifier) { /* 表达式获取 Expression() variable; | 变量 √ value; | 显式设置的字面量。 √ obj.Value...; | obj为之前的上下文中出现过的变量,调用表达式包含对象成员数组、方法 array[...]; | array为之前的上下文中出现过的变量。 array[...].Value...; | array为之前的上下文中出现过的变量。调用表达式包含对象成员数组、方法 new Class(...); | 实例化类型,包含构造函数 √ */ var backupToken = _currentToken; //var tempPeekToken = _lexer.PeekToken(); var targetNode = new IdentifierNode(_currentToken.Value).SetTokenInfo(_currentToken); // 获取变量 var peekToken2 = _lexer.PeekToken(); // 消耗 第一个标识符 if (peekToken2.Type == TokenType.Semicolon || peekToken2.Type == TokenType.ParenthesisRight || peekToken2.Type == TokenType.SquareBracketsRight || peekToken2.Type == TokenType.Comma || peekToken2.Type == TokenType.Operator ) { NextToken(); // 消耗标识符 return targetNode; } if (peekToken2.Type == TokenType.ParenthesisLeft) { // 解析调用挂载方法 // ... = variable()()(); // 暂时不支持柯里化调用... = variable()()(); var functionCallNode = ParseFunctionCallNode(); if(_currentToken.Type == TokenType.Semicolon || _currentToken.Type == TokenType.Operator) { return functionCallNode; } targetNode = functionCallNode; } else if (peekToken2.Type == TokenType.SquareBracketsLeft) { // 解析集合获取 var collectionIndexNode = ParseCollectionIndexNode(targetNode); if (_currentToken.Type == TokenType.Semicolon || _currentToken.Type == TokenType.Operator) { return collectionIndexNode; } targetNode = collectionIndexNode; }else if (peekToken2.Type == TokenType.Dot) { NextToken(); // 消耗标识符 } // 开始解析 List nodes = [targetNode]; ASTNode? source; while (true) { var peekToken = _currentToken; // _lexer.PeekToken(); // 获取下一个token开始判断 source = nodes[^1]; // 重定向节点 if (peekToken.Type == TokenType.Dot) // 从对象获取 { /* 1. 获取成员 => PeekToken.Type = TokenType.Dot 2. 获取集合 => PeekToken.Type = TokenType.SquareBracketsLeft 3. 调用成员方法 => PeekToken.Type = TokenType.ParenthesisLeft */ NextToken(); // 消耗 "." 并获取下一个成员。 var peekToken3 = _lexer.PeekToken(); ASTNode tempNode = peekToken3.Type switch { TokenType.Comma or TokenType.Operator or TokenType.Dot or TokenType.Semicolon or TokenType.ParenthesisRight => ParseMemberAccessNode(source), // 获取对象中的成员 source.Value... TokenType.SquareBracketsLeft => ParseCollectionIndexNode(source), // 获取集合中的元素 source[index].... TokenType.ParenthesisLeft => ParseMemberFunctionCallNode(source), // 获取需要调用的方法 source(arg1,arg2...)... _ => throw new Exception($"无法从对象获取成员,当前Token : {peekToken.ToString()}。") }; nodes.Add(tempNode); continue; // 结束当前轮次的token判断 } else if (peekToken.Type == TokenType.ParenthesisLeft) // 调用对象方法 { var memberFunctionCallNode = ParseMemberFunctionCallNode(source); nodes.Add(memberFunctionCallNode); continue; // 结束当前轮次的token判断 } else if (peekToken.Type == TokenType.SquareBracketsLeft) // 集合获取 { var collectionIndexNode = ParseCollectionIndexNode(source); nodes.Add(collectionIndexNode); continue; // 结束当前轮次的token判断 } else if (peekToken.Type == TokenType.Semicolon) { break; } else { if(peekToken.Type == TokenType.ParenthesisRight // 可能解析完了方法参数 || peekToken.Type == TokenType.Comma // 可能解析完了方法参数 || peekToken.Type == TokenType.Operator // 可能解析完了方法参数 || peekToken.Type == TokenType.BraceRight // 可能解析完了方法参数 || peekToken.Type == TokenType.ParenthesisRight) // 可能解析完了下标索引 { return source; } // 应该是异常,如果是其它符号,说明词法解析不符合预期 throw new Exception($"在 Expression().Factor() 遇到意外的 Token: [{_currentToken.Type}]\"{_currentToken.Value}\" "); } } return source; } else if (_currentToken.Type == TokenType.ParenthesisLeft) // 嵌套表达式 { NextToken(); // 消耗 "(" var expNode = BooleanExpression(); if (_currentToken.Type != TokenType.ParenthesisRight) throw new Exception($"解析嵌套表达式时遇到非预期的符号 \"{_currentToken.Type}\",预期符号为\")\"。"); NextToken(); // 消耗 ")" return expNode; } else if (_currentToken.Type == TokenType.SquareBracketsLeft) { NextToken(); // 消耗 "[" List elements = []; while (_currentToken.Type != TokenType.SquareBracketsRight) // 遇到 "]" 时结束 { var element = ParserArgNode(); elements.Add(element); if (_currentToken.Type == TokenType.Comma) { NextToken(); // 消耗参数分隔符 "," } } NextToken(); // 消耗 "]" ArrayDefintionNode arrayDefintionNode = new ArrayDefintionNode(elements); return arrayDefintionNode.SetTokenInfo(_currentToken); } else if(_currentToken.Type == TokenType.Keyword && _currentToken.Value == "new") // 创建对象 { return ParseObjectInstantiationNode(); } #region 字面量因子 else if (_currentToken.Type == TokenType.Null) { NextToken(); // 消耗 null return new NullNode().SetTokenInfo(factorToken); } else if (_currentToken.Type == TokenType.Boolean) { var value = bool.Parse(_currentToken.Value); NextToken(); // 消耗布尔量 return new BooleanNode(value).SetTokenInfo(factorToken); } else if (_currentToken.Type == TokenType.RawString) { var value = _currentToken.Value; NextToken(); // 消耗字符串 var node = new RawStringNode(value).SetTokenInfo(factorToken); return node; } else if (_currentToken.Type == TokenType.String) { var value = _currentToken.Value; NextToken(); // 消耗字符串 var node = new StringNode(value).SetTokenInfo(factorToken); return node; } else if (_currentToken.Type == TokenType.Char) { var value = _currentToken.Value; NextToken(); ; // 消耗Char var @char = char.Parse(value); return new CharNode(@char).SetTokenInfo(factorToken); } else if (_currentToken.Type == TokenType.InterpolatedString) { // 暂未实现插值字符串 // 可能是插值字符串; // let context = $"a{A}b{B}c"; // let context = "a" + A + "b" + B + c; NextToken(); // 消耗字符串 while (_currentToken.Type == TokenType.String) { } } else if (_currentToken.Type == TokenType.NumberInt) { var value = int.Parse(_currentToken.Value); NextToken(); // 消耗 int 整型 return new NumberIntNode(value).SetTokenInfo(factorToken); } else if (_currentToken.Type == TokenType.NumberLong) { var value = long.Parse(_currentToken.Value); NextToken(); // 消耗 long 整型 return new NumberLongNode(value).SetTokenInfo(factorToken); } else if (_currentToken.Type == TokenType.NumberFloat) { var value = float.Parse(_currentToken.Value); NextToken(); // 消耗 float 浮点数 return new NumberFloatNode(value).SetTokenInfo(factorToken); } else if (_currentToken.Type == TokenType.NumberDouble) { var value = double.Parse(_currentToken.Value); NextToken(); // 消耗 double 浮点数 return new NumberDoubleNode(value).SetTokenInfo(factorToken); } #endregion throw new Exception($"在 Expression().Factor() 遇到意外的 TokenType ,{_currentToken.Type} {_currentToken.Value} "); } #endregion #region 辅助方法 private Token NextToken() { _currentToken = _lexer.NextToken(); return _currentToken; } private Token NextToken(TokenType expectationTokenType) { _currentToken = _lexer.NextToken(); if(_currentToken.Type != expectationTokenType) { throw new Exception($"分析器获取下一个Token时,期望获取 {expectationTokenType} ,但实际获取 {_currentToken.Type}。" + $"Value : {_currentToken.Value}" + $"StartIndex : {_currentToken.StartIndex}" + $"Length : {_currentToken.Length}" + $""); } return _currentToken; } /// /// 判断当前Token操作符类型 /// /// /// private bool JudgmentTokenType(TokenType tokenType) { return _currentToken.Type == tokenType; } /// /// 判断Token操作符类型 /// /// /// private bool JudgmentOperator(Token peekToken, string @operator) { if (peekToken.Type != TokenType.Operator) { return false; } return peekToken.Value == @operator; } /// /// 判断当前Token关键字类型 /// /// /// private bool JudgmentKeyword(string keyword) { if (_currentToken.Type != TokenType.Keyword) { return false; } return _currentToken.Value == keyword; } #endregion } }