fix:改进语法分析器支持顶层语句

This commit is contained in:
Luke 2025-05-16 16:08:35 +08:00
parent d4d2b3b87c
commit 87284c50d4

View File

@ -51,14 +51,6 @@ Parser采用**递归下降**和**运算符优先解析**相结合的方法:顶
* **AST节点** 抽象语法树采用面向对象节点类层次表示。基类`Node`定义了通用接口各子类对应不同语法成分。主要节点类例如ModuleNode模块含名称和函数列表、FunctionNode函数定义含名称、参数列表、返回类型、函数体、ImportNode导入声明、ParameterNode形参定义含名和类型、Block结构节点如IfNode、LoopNode包含条件和内部语句块以及表达式节点如 IdentifierNode、NumberLiteralNode、BinaryExpressionNode 等。AST节点在解析时被实例化语义分析阶段可能会在节点上附加类型等注释信息。整个Parser输出一个AST节点列表一般情况下包含一个ModuleNode源文件级模块作为根。如果语法有误解析器会抛出带错误位置和原因的异常停止编译。 * **AST节点** 抽象语法树采用面向对象节点类层次表示。基类`Node`定义了通用接口各子类对应不同语法成分。主要节点类例如ModuleNode模块含名称和函数列表、FunctionNode函数定义含名称、参数列表、返回类型、函数体、ImportNode导入声明、ParameterNode形参定义含名和类型、Block结构节点如IfNode、LoopNode包含条件和内部语句块以及表达式节点如 IdentifierNode、NumberLiteralNode、BinaryExpressionNode 等。AST节点在解析时被实例化语义分析阶段可能会在节点上附加类型等注释信息。整个Parser输出一个AST节点列表一般情况下包含一个ModuleNode源文件级模块作为根。如果语法有误解析器会抛出带错误位置和原因的异常停止编译。
上面是Parser相关介绍
## 需要你完成的
1. 解压然后读取项目里面全部相关代码,然后解决下面的问题
2. 目前问题是Parser对顶层非模块内容的支持不完善当前TopLevelParserFactory只注册了模块解析。如果源码未以`module`开头比如仅有独立函数定义或语句ParserEngine将无法识别顶层结构而报错。这在设计上可能考虑过支持**脚本模式**无模块包裹的代码从IR生成器看也有相应处理逻辑将顶层Statement封装进`_start`函数但由于顶层解析未实现直接处理Statement实际使用中需要至少有一个模块声明。目标:为提高灵活性扩展Parser支持隐式模块包装或允许顶层函数定义。
3. Parser目前对错误恢复支持有限一旦遇到语法错误通常终止分析实现在捕获错误后跳过一定Token继续分析收集多个错误再统一报告。
4. 帮我解决以上两个问题,确保修改后和后面模块兼容,给我修改后的代码和新增的代码
## 语义分析模块 ## 语义分析模块
**语义分析器(Semantic Analyzer)** 以AST为输入在不改变结构的前提下检查和补充程序的意义信息。主要任务包括标识符解析、作用域和生命周期管理、类型检查如果有静态类型、控制流合法性检查等。SCompiler的语义分析由`SemanticAnalyzerRunner`统一调度,内部调用`SemanticAnalyzer`执行具体步骤: **语义分析器(Semantic Analyzer)** 以AST为输入在不改变结构的前提下检查和补充程序的意义信息。主要任务包括标识符解析、作用域和生命周期管理、类型检查如果有静态类型、控制流合法性检查等。SCompiler的语义分析由`SemanticAnalyzerRunner`统一调度,内部调用`SemanticAnalyzer`执行具体步骤:
@ -67,11 +59,22 @@ Parser采用**递归下降**和**运算符优先解析**相结合的方法:顶
2. **函数体语义检查**随后SemanticAnalyzer对每个模块内的函数逐一检查`FunctionChecker`执行具体逻辑。FunctionChecker会为每个函数创建**局部符号表**SymbolTable并将函数形参作为变量首先注册到符号表中。然后遍历函数体中的每条语句节点利用预先注册的**语义分析器**StatementAnalyzer/ExpressionAnalyzer对不同类型的语句和表达式进行检查。例如对变量赋值语句AssignmentAnalyzer会检查变量是否已在当前或上层作用域声明、赋值类型是否兼容对函数调用CallExpressionAnalyzer会检索被调用函数在ModuleRegistry中是否存在以及参数数量和类型是否匹配被调函数签名等对控制结构如IfAnalyzer检查条件表达式类型预期为布尔以及`then/else`分支的返回路径一致性LoopAnalyzer检查循环初始化和更新部分等。每个Analyzer通过Context上下文对象获取所需信息并记录错误。**符号表**在进入函数时创建离开函数时销毁当前实现中无嵌套块作用域每个函数体使用一个SymbolTable参数和局部变量都登记其中。对于未声明的变量或不支持的语法分析器将添加`SemanticError`错误对象。SemanticAnalyzer汇总所有错误`SemanticAnalysisReporter`统一输出错误列表;如果存在语义错误则终止后续编译流程。 2. **函数体语义检查**随后SemanticAnalyzer对每个模块内的函数逐一检查`FunctionChecker`执行具体逻辑。FunctionChecker会为每个函数创建**局部符号表**SymbolTable并将函数形参作为变量首先注册到符号表中。然后遍历函数体中的每条语句节点利用预先注册的**语义分析器**StatementAnalyzer/ExpressionAnalyzer对不同类型的语句和表达式进行检查。例如对变量赋值语句AssignmentAnalyzer会检查变量是否已在当前或上层作用域声明、赋值类型是否兼容对函数调用CallExpressionAnalyzer会检索被调用函数在ModuleRegistry中是否存在以及参数数量和类型是否匹配被调函数签名等对控制结构如IfAnalyzer检查条件表达式类型预期为布尔以及`then/else`分支的返回路径一致性LoopAnalyzer检查循环初始化和更新部分等。每个Analyzer通过Context上下文对象获取所需信息并记录错误。**符号表**在进入函数时创建离开函数时销毁当前实现中无嵌套块作用域每个函数体使用一个SymbolTable参数和局部变量都登记其中。对于未声明的变量或不支持的语法分析器将添加`SemanticError`错误对象。SemanticAnalyzer汇总所有错误`SemanticAnalysisReporter`统一输出错误列表;如果存在语义错误则终止后续编译流程。
项目提供了一些基础的语义检查实现变量重复定义检测、变量未声明就使用、函数重复声明、函数调用不存在、参数不匹配等。类型系统方面SCompiler目前是静态类型雏形定义了BuiltinTypeRegistry含基本类型int,string,float,bool,double等枚举和值对象但**尚未严格执行类型检查**。例如变量声明了类型但赋值时类型不符的情况Analyzer可能未完全实现检查。在SignatureRegistrar会对未知类型记录错误但像算术运算左右项类型兼容性、条件表达式类型等并未全面检查。这是因为当前语言实现对类型要求不严格更像动态类型处理。**改进**后续可加强类型检查逻辑在ExpressionAnalyzer中加入对操作数类型的校验对不匹配情况给出错误。 项目提供了一些基础的语义检查实现变量重复定义检测、变量未声明就使用、函数重复声明、函数调用不存在、参数不匹配等。类型系统方面SCompiler目前是静态类型雏形定义了BuiltinTypeRegistry含基本类型int,string,float,bool,double等枚举和值对象但**尚未严格执行类型检查**。例如变量声明了类型但赋值时类型不符的情况Analyzer可能未完全实现检查。在SignatureRegistrar会对未知类型记录错误但像算术运算左右项类型兼容性、条件表达式类型等并未全面检查。这是因为当前语言实现对类型要求不严格更像动态类型处理。**改进**加强类型检查逻辑在ExpressionAnalyzer中加入对操作数类型的校验对不匹配情况给出错误。
语义分析结束后若无错误即可确保AST上的每个标识符引用都有定义每个函数调用可解析到目标函数每条语句在语义上是合理的。这为后续代码生成提供了可靠基础。语义阶段还可以在AST节点上附加类型注解便于代码生成选择合适的指令。目前Context的parseType会将类型名字符串转换为Type对象如BuiltinType.INT等供符号记录但AST节点未存储类型属性后端主要依赖变量的Type信息选择指令。整个SemanticAnalyzer设计采用了**注册表 + 分派**模式通过AnalyzerRegistrar将具体AST节点类型与相应SemanticAnalyzer关联FunctionChecker运行时按节点类型获取分析器。这种设计方便扩展新的语义检查规则只需增加对应节点的Analyzer并注册即可。 语义分析结束后若无错误即可确保AST上的每个标识符引用都有定义每个函数调用可解析到目标函数每条语句在语义上是合理的。这为后续代码生成提供了可靠基础。语义阶段还可以在AST节点上附加类型注解便于代码生成选择合适的指令。目前Context的parseType会将类型名字符串转换为Type对象如BuiltinType.INT等供符号记录但AST节点未存储类型属性后端主要依赖变量的Type信息选择指令。整个SemanticAnalyzer设计采用了**注册表 + 分派**模式通过AnalyzerRegistrar将具体AST节点类型与相应SemanticAnalyzer关联FunctionChecker运行时按节点类型获取分析器。这种设计方便扩展新的语义检查规则只需增加对应节点的Analyzer并注册即可。
*健壮性*: 语义分析目前存在一些可改进点:一是**错误收集**不完善,目前遇到语义错误就记录并在最后可能退出,但对于不同模块或函数的多个错误能否一次收集输出没有详述。可以改进为**非终止检查**,在尽可能继续分析后面的代码前提下收集所有错误。二是**模块导入解析**还不完整Import只验证模块是否存在于当前编译单元内的ModuleRegistry若要支持跨文件模块需要扩展编译器能够根据import加载其它源文件或已编译中间文件当前FileIOUtils等类可能为此做准备。三是**作用域管理**仅支持函数级缺少块级作用域支持如在if/loop内部声明的变量不单独成域如需支持更细粒度的SymbolTable嵌套和Analyzer处理需实现。四是**类型系统**如上所述比较原始没有检查表达式的类型正确性例如算术运算混用int和string未来可引入类型推断或强制类型检查使语言更加健壮。 *健壮性*: 语义分析目前存在一些可改进点:二是三是四是
上面是Semantic相关介绍
## 需要你完成的
1. 解压然后读取项目里面全部相关代码,然后解决下面的问题
2. **错误收集**不完善,目前遇到语义错误就记录并在最后可能退出,但对于不同模块或函数的多个错误能否一次收集输出没有详述。改进为**非终止检查**,在尽可能继续分析后面的代码前提下收集所有错误。
3. **模块导入解析**还不完整Import只验证模块是否存在于当前编译单元内的ModuleRegistry需要支持跨文件模块需要扩展编译器能够根据import加载其它源文件或已编译中间文件
4. **作用域管理**仅支持函数级缺少块级作用域支持如在if/loop内部声明的变量不单独成域需要更细粒度的SymbolTable嵌套和Analyzer处理需实现。
5. **类型系统**如上所述比较原始没有检查表达式的类型正确性例如算术运算混用int和string未来可引入类型推断或强制类型检查使语言更加健壮。
6. 帮我解决以上问题,确保修改后和后面模块兼容,给我修改后的代码和新增的代码
## 中间代码(IR)生成 ## 中间代码(IR)生成