feat: 新增对象创建表达式节点

- 添加 NewExpressionNode 类,表示对象创建表达式
- 该节点用于处理 "new" 关键字实例化类型的语法
- 包含目标类型名、构造函数参数列表和源码位置信息
- 实现了 ExpressionNode 接口,提供获取源码上下文的方法
This commit is contained in:
Luke 2025-08-29 17:58:01 +08:00
parent 1ab4fb2e87
commit 1835b85c5c

View File

@ -0,0 +1,84 @@
package org.jcnc.snow.compiler.parser.expression;
import org.jcnc.snow.compiler.lexer.token.Token;
import org.jcnc.snow.compiler.lexer.token.TokenType;
import org.jcnc.snow.compiler.parser.ast.NewExpressionNode;
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
import org.jcnc.snow.compiler.parser.context.ParserContext;
import org.jcnc.snow.compiler.parser.context.TokenStream;
import org.jcnc.snow.compiler.parser.context.UnexpectedToken;
import org.jcnc.snow.compiler.parser.expression.base.PrefixParselet;
import java.util.ArrayList;
import java.util.List;
/**
* {@code NewObjectParselet}
* <p>
* 解析对象创建表达式 <code>new TypeName(arg1, arg2, ...)</code> 的前缀解析器实现
* <ul>
* <li>用于 Pratt 解析框架实现 new 关键字前缀的自定义解析逻辑</li>
* <li>支持类型名为内置类型TokenType.TYPE或用户结构体名TokenType.IDENTIFIER</li>
* <li>支持可变参数列表参数为任意表达式</li>
* </ul>
* </p>
*/
public class NewObjectParselet implements PrefixParselet {
/**
* 解析 new 对象创建表达式并生成 AST 新建节点
*
* @param ctx 语法分析上下文包含 TokenStream 及源文件名等信息
* @param token 当前读取到的 new 关键字 Token
* @return 表达式节点NewExpressionNode
*
* <p>
* 解析流程
* <ol>
* <li>读取类型名支持内建类型或结构体名</li>
* <li>读取参数列表参数为表达式用逗号分隔</li>
* <li>封装为 NewExpressionNode记录源码位置信息</li>
* </ol>
* 出错时会抛出 UnexpectedToken 异常
* </p>
*/
@Override
public ExpressionNode parse(ParserContext ctx, Token token) {
TokenStream ts = ctx.getTokens();
// ==========================
// 1) 解析类型名
// ==========================
// 类型名只能为内建类型TYPE或用户结构体名IDENTIFIER
if (ts.peek().getType() != TokenType.TYPE && ts.peek().getType() != TokenType.IDENTIFIER) {
var t = ts.peek();
throw new UnexpectedToken(
"期望的标记类型为 TYPE 或 IDENTIFIER但实际得到的是 " +
t.getType() + " ('" + t.getLexeme() + "')",
t.getLine(), t.getCol()
);
}
String typeName = ts.next().getLexeme();
// ==========================
// 2) 解析构造参数列表
// ==========================
ts.expect("("); // 必须有左括号
List<ExpressionNode> args = new ArrayList<>();
if (!ts.match(")")) { // 非空参数列表
// 连续处理逗号分隔的多个参数
do {
args.add(new PrattExpressionParser().parse(ctx));
} while (ts.match(","));
ts.expect(")"); // 结尾必须为右括号
}
// ==========================
// 3) 封装为 AST 节点并返回
// ==========================
NodeContext nc = new NodeContext(token.getLine(), token.getCol(), ctx.getSourceName());
return new NewExpressionNode(typeName, args, nc);
}
}