From 87284c50d493878b796aee0cc838c0652f1d3732 Mon Sep 17 00:00:00 2001 From: Luke Date: Fri, 16 May 2025 16:08:35 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E6=94=B9=E8=BF=9B=E8=AF=AD=E6=B3=95?= =?UTF-8?q?=E5=88=86=E6=9E=90=E5=99=A8=E6=94=AF=E6=8C=81=E9=A1=B6=E5=B1=82?= =?UTF-8?q?=E8=AF=AD=E5=8F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/Snow语言文档.md | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/doc/Snow语言文档.md b/doc/Snow语言文档.md index 36c5105..7ba67cd 100644 --- a/doc/Snow语言文档.md +++ b/doc/Snow语言文档.md @@ -51,14 +51,6 @@ Parser采用**递归下降**和**运算符优先解析**相结合的方法:顶 * **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`执行具体步骤: @@ -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`统一输出错误列表;如果存在语义错误则终止后续编译流程。 -项目提供了一些基础的语义检查实现,如:变量重复定义检测、变量未声明就使用、函数重复声明、函数调用不存在、参数不匹配等。类型系统方面,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并注册即可。 -*健壮性*: 语义分析目前存在一些可改进点:一是**错误收集**不完善,目前遇到语义错误就记录并在最后可能退出,但对于不同模块或函数的多个错误能否一次收集输出没有详述。可以改进为**非终止检查**,在尽可能继续分析后面的代码前提下收集所有错误。二是**模块导入解析**还不完整,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)生成