From 9c5ae6762b92c0e47e4a99c49aa2229ec76a9c13 Mon Sep 17 00:00:00 2001 From: Luke Date: Wed, 11 Jun 2025 17:31:55 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0Boolean=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- playground/Demo4/Main.snow | 14 ++----- .../compiler/lexer/token/TokenFactory.java | 27 ++++++++---- .../snow/compiler/lexer/token/TokenType.java | 2 + .../compiler/parser/ast/BoolLiteralNode.java | 39 +++++++++++++++++ .../expression/BoolLiteralParselet.java | 33 +++++++++++++++ .../expression/PrattExpressionParser.java | 1 + .../expression/BoolLiteralAnalyzer.java | 42 +++++++++++++++++++ .../semantic/core/AnalyzerRegistrar.java | 1 + .../semantic/core/BuiltinTypeRegistry.java | 1 + .../compiler/semantic/type/BuiltinType.java | 2 + 10 files changed, 143 insertions(+), 19 deletions(-) create mode 100644 src/main/java/org/jcnc/snow/compiler/parser/ast/BoolLiteralNode.java create mode 100644 src/main/java/org/jcnc/snow/compiler/parser/expression/BoolLiteralParselet.java create mode 100644 src/main/java/org/jcnc/snow/compiler/semantic/analyzers/expression/BoolLiteralAnalyzer.java diff --git a/playground/Demo4/Main.snow b/playground/Demo4/Main.snow index 4a13b7d..4dc5351 100644 --- a/playground/Demo4/Main.snow +++ b/playground/Demo4/Main.snow @@ -3,15 +3,9 @@ module: Main parameter: return_type: int body: - declare n1: int =1 - declare n2: int =2 - declare n3: int =1 - if n1 ==1 then - if n2 ==2 then - n3 =3 - end if - end if - return n3 + declare b1: bool + + return 0 end body end function -end module \ No newline at end of file +end module diff --git a/src/main/java/org/jcnc/snow/compiler/lexer/token/TokenFactory.java b/src/main/java/org/jcnc/snow/compiler/lexer/token/TokenFactory.java index ab7b9e3..6a01378 100644 --- a/src/main/java/org/jcnc/snow/compiler/lexer/token/TokenFactory.java +++ b/src/main/java/org/jcnc/snow/compiler/lexer/token/TokenFactory.java @@ -28,19 +28,12 @@ public class TokenFactory { /** * 语言的保留关键字集合。 */ - private static final Set KEYWORDS = Set.of( - "module", "function", "parameter", "return_type", - "body", "end", "if", "then", "else", "loop", - "declare", "return", "import", - "initializer", "condition", "update" - ); + private static final Set KEYWORDS = Set.of("module", "function", "parameter", "return_type", "body", "end", "if", "then", "else", "loop", "declare", "return", "import", "initializer", "condition", "update"); /** * 内置类型名称集合,如 int、string 等。 */ - private static final Set TYPES = Set.of( - "int", "string", "float", "bool", "void", "double", "long", "short", "byte" - ); + private static final Set TYPES = Set.of("int", "string", "float", "bool", "void", "double", "long", "short", "byte"); /** * 创建一个根据内容自动推断类型的 {@link Token} 实例。 @@ -69,15 +62,30 @@ public class TokenFactory { * @return 推断出的 {@link TokenType} 类型 */ private static TokenType determineTokenType(String raw) { + if (isABoolean(raw)) return TokenType.BOOL_LITERAL; if (isType(raw)) return TokenType.TYPE; if (isKeyword(raw)) return TokenType.KEYWORD; if (isIdentifier(raw)) return TokenType.IDENTIFIER; return TokenType.UNKNOWN; } + /** + * 判断指定字符串是否为布尔字面量("true" 或 "false")。 + * + *

本方法通过字符串比较,判断输入是否严格等于 "true" 或 "false"。

+ * + * @param raw 待判断的字符串 + * @return 若为布尔字面量,则返回 {@code true};否则返回 {@code false} + */ + private static boolean isABoolean(String raw) { + return "true".equals(raw) || "false".equals(raw); + } + /** * 判断指定字符串是否为内置类型标识。 * + *

本方法用于辅助语义分析或类型识别,判断输入字符串是否存在于预定义的类型集合 {@code TYPES} 中。

+ * * @param raw 输入的字符串 * @return 若为类型名则返回 {@code true},否则返回 {@code false} */ @@ -85,6 +93,7 @@ public class TokenFactory { return TYPES.contains(raw); } + /** * 判断指定字符串是否为语言保留关键字。 * diff --git a/src/main/java/org/jcnc/snow/compiler/lexer/token/TokenType.java b/src/main/java/org/jcnc/snow/compiler/lexer/token/TokenType.java index db7f087..4ff4394 100644 --- a/src/main/java/org/jcnc/snow/compiler/lexer/token/TokenType.java +++ b/src/main/java/org/jcnc/snow/compiler/lexer/token/TokenType.java @@ -19,6 +19,8 @@ public enum TokenType { /** 内置类型名称(如 int、string、bool 等) */ TYPE, + /** 布尔字面量 (true / false) */ + BOOL_LITERAL, /** 字符串字面量(如 "hello") */ STRING_LITERAL, diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/BoolLiteralNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/BoolLiteralNode.java new file mode 100644 index 0000000..a82b98c --- /dev/null +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/BoolLiteralNode.java @@ -0,0 +1,39 @@ +package org.jcnc.snow.compiler.parser.ast; + +import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; + +/** + * 表示布尔字面量(boolean literal)的抽象语法树(AST)节点。 + *

+ * 本类实现了 {@link ExpressionNode} 接口,用于在编译器前端构建语法分析过程中, + * 表达布尔类型的字面量常量(如 "true" 或 "false")。 + *

+ */ +public class BoolLiteralNode implements ExpressionNode { + /** + * 字面量的布尔值。 + */ + private final boolean value; + + /** + * 使用布尔字面量字符串构造一个 {@code BoolLiteralNode} 实例。 + *

+ * 本构造方法接受一个字符串词素(lexeme),并通过 {@link Boolean#parseBoolean(String)} 解析为布尔值。 + * 如果传入的字符串为 "true"(忽略大小写),则解析结果为 {@code true};否则为 {@code false}。 + *

+ * + * @param lexeme 布尔字面量的字符串表示 + */ + public BoolLiteralNode(String lexeme) { + this.value = Boolean.parseBoolean(lexeme); + } + + /** + * 返回此布尔字面量节点的值。 + * + * @return 布尔值,代表源代码中的布尔字面量 + */ + public boolean getValue() { + return value; + } +} diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/BoolLiteralParselet.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/BoolLiteralParselet.java new file mode 100644 index 0000000..cb2ede5 --- /dev/null +++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/BoolLiteralParselet.java @@ -0,0 +1,33 @@ +package org.jcnc.snow.compiler.parser.expression; + +import org.jcnc.snow.compiler.lexer.token.Token; +import org.jcnc.snow.compiler.parser.ast.BoolLiteralNode; +import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.context.ParserContext; +import org.jcnc.snow.compiler.parser.expression.base.PrefixParselet; + +/** + * {@code BoolLiteralParselet} 是用于解析布尔字面量的前缀解析子(prefix parselet)。 + *

+ * 本类实现了 {@link PrefixParselet} 接口,用于在语法分析阶段将布尔类型的词法单元(如 "true" 或 "false") + * 转换为相应的抽象语法树(AST)节点 {@link BoolLiteralNode}。 + */ +public class BoolLiteralParselet implements PrefixParselet { + + /** + * 解析布尔字面量的词法单元,并返回对应的布尔字面量节点。 + *

+ * 本方法被语法分析器在遇到布尔字面量词法单元时调用。 + * 它将词法单元的词素(lexeme)传递给 {@link BoolLiteralNode} 构造器, + * 并返回构造得到的 AST 节点。 + *

+ * + * @param ctx 当前的语法分析上下文,用于提供所需的解析信息 + * @param token 代表布尔字面量的词法单元 + * @return 对应的 {@link BoolLiteralNode} 实例 + */ + @Override + public ExpressionNode parse(ParserContext ctx, Token token) { + return new BoolLiteralNode(token.getLexeme()); + } +} diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/PrattExpressionParser.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/PrattExpressionParser.java index 5edcf69..1a1d124 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/expression/PrattExpressionParser.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/PrattExpressionParser.java @@ -43,6 +43,7 @@ public class PrattExpressionParser implements ExpressionParser { prefixes.put(TokenType.IDENTIFIER.name(), new IdentifierParselet()); prefixes.put(TokenType.LPAREN.name(), new GroupingParselet()); prefixes.put(TokenType.STRING_LITERAL.name(), new StringLiteralParselet()); + prefixes.put(TokenType.BOOL_LITERAL.name(), new BoolLiteralParselet()); // 注册中缀解析器 infixes.put("+", new BinaryOperatorParselet(Precedence.SUM, true)); diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/expression/BoolLiteralAnalyzer.java b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/expression/BoolLiteralAnalyzer.java new file mode 100644 index 0000000..6824717 --- /dev/null +++ b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/expression/BoolLiteralAnalyzer.java @@ -0,0 +1,42 @@ +package org.jcnc.snow.compiler.semantic.analyzers.expression; + +import org.jcnc.snow.compiler.parser.ast.BoolLiteralNode; +import org.jcnc.snow.compiler.parser.ast.FunctionNode; +import org.jcnc.snow.compiler.semantic.analyzers.base.ExpressionAnalyzer; +import org.jcnc.snow.compiler.semantic.core.Context; +import org.jcnc.snow.compiler.semantic.core.ModuleInfo; +import org.jcnc.snow.compiler.semantic.symbol.SymbolTable; +import org.jcnc.snow.compiler.semantic.type.BuiltinType; +import org.jcnc.snow.compiler.semantic.type.Type; + +/** + * {@code BoolLiteralAnalyzer} 是布尔字面量表达式的语义分析器。 + *

+ * 本类实现 {@link ExpressionAnalyzer} 接口,用于在语义分析阶段对 {@link BoolLiteralNode} + * 进行类型推断和校验。在此实现中,所有布尔字面量表达式都被直接视为内建布尔类型 {@link BuiltinType#BOOLEAN}。 + *

+ *

+ * 该分析器不涉及值检查,仅负责返回类型信息,用于后续的类型检查与代码生成阶段。 + *

+ */ +public class BoolLiteralAnalyzer implements ExpressionAnalyzer { + + /** + * 分析布尔字面量表达式的语义,并返回其类型。 + *

+ * 由于布尔字面量具有确定且固定的类型,本方法始终返回 {@link BuiltinType#BOOLEAN}。 + *

+ * + * @param ctx 当前的语义分析上下文,包含全局编译状态 + * @param mi 所在模块的信息对象 + * @param fn 当前分析所在的函数节点 + * @param locals 当前作用域下的符号表 + * @param expr 被分析的布尔字面量表达式节点 + * @return {@link BuiltinType#BOOLEAN},表示布尔类型 + */ + @Override + public Type analyze(Context ctx, ModuleInfo mi, FunctionNode fn, + SymbolTable locals, BoolLiteralNode expr) { + return BuiltinType.BOOLEAN; + } +} diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/core/AnalyzerRegistrar.java b/src/main/java/org/jcnc/snow/compiler/semantic/core/AnalyzerRegistrar.java index d91d08c..865bb5e 100644 --- a/src/main/java/org/jcnc/snow/compiler/semantic/core/AnalyzerRegistrar.java +++ b/src/main/java/org/jcnc/snow/compiler/semantic/core/AnalyzerRegistrar.java @@ -39,6 +39,7 @@ public final class AnalyzerRegistrar { registry.registerStatementAnalyzer(IfNode.class, new IfAnalyzer()); registry.registerStatementAnalyzer(LoopNode.class, new LoopAnalyzer()); registry.registerStatementAnalyzer(ReturnNode.class, new ReturnAnalyzer()); + registry.registerExpressionAnalyzer(BoolLiteralNode.class, new BoolLiteralAnalyzer()); // 特殊处理:表达式语句(如 "foo();")作为语句包装表达式 registry.registerStatementAnalyzer(ExpressionStatementNode.class, diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/core/BuiltinTypeRegistry.java b/src/main/java/org/jcnc/snow/compiler/semantic/core/BuiltinTypeRegistry.java index 876411e..498f4a9 100644 --- a/src/main/java/org/jcnc/snow/compiler/semantic/core/BuiltinTypeRegistry.java +++ b/src/main/java/org/jcnc/snow/compiler/semantic/core/BuiltinTypeRegistry.java @@ -31,6 +31,7 @@ public final class BuiltinTypeRegistry { "float", BuiltinType.FLOAT, "double", BuiltinType.DOUBLE, "string", BuiltinType.STRING, + "boolean", BuiltinType.BOOLEAN, "void", BuiltinType.VOID ); diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/type/BuiltinType.java b/src/main/java/org/jcnc/snow/compiler/semantic/type/BuiltinType.java index 0602510..213cd80 100644 --- a/src/main/java/org/jcnc/snow/compiler/semantic/type/BuiltinType.java +++ b/src/main/java/org/jcnc/snow/compiler/semantic/type/BuiltinType.java @@ -15,6 +15,7 @@ package org.jcnc.snow.compiler.semantic.type; *
  • {@link #FLOAT} - 单精度浮点数
  • *
  • {@link #DOUBLE} - 双精度浮点数
  • *
  • {@link #STRING} - 字符串类型
  • + *
  • {@link #BOOLEAN} - 布尔类型
  • *
  • {@link #VOID} - 空类型,用于表示无返回值的函数
  • * * @@ -34,6 +35,7 @@ public enum BuiltinType implements Type { FLOAT, // 单精度浮点数 DOUBLE, // 双精度浮点数 STRING, // 字符串类型 + BOOLEAN, // 布尔类型 VOID; // 空类型,用于表示函数无返回值 /**