删除解析器
This commit is contained in:
parent
06ccb4f280
commit
2b7a2b86b8
@ -1,34 +1,25 @@
|
||||
// File: org/jcnc/snow/compiler/Main.java
|
||||
package org.jcnc.snow.compiler;
|
||||
|
||||
|
||||
import org.jcnc.snow.compiler.lexer.LexerEngine;
|
||||
import org.jcnc.snow.compiler.lexer.token.Token;
|
||||
import org.jcnc.snow.compiler.parser.ast.ASTModule;
|
||||
import org.jcnc.snow.compiler.parser.utils.ASTPrinter;
|
||||
import org.jcnc.snow.compiler.parser.ParserEngine;
|
||||
import org.jcnc.snow.compiler.lexer.utils.TokenPrinter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) throws IOException {
|
||||
// 1. 读文件
|
||||
// 如果命令行中提供了文件名,就读取该文件;否则默认读取当前目录下的 "opcode" 文件
|
||||
String filePath = args.length > 0 ? args[0] : "test";
|
||||
|
||||
String source = Files.readString(Path.of(filePath), StandardCharsets.UTF_8);
|
||||
|
||||
// 2. 词法分析
|
||||
LexerEngine lexer = new LexerEngine(source);
|
||||
List<Token> tokens = lexer.getAllTokens();
|
||||
|
||||
// 3. 语法分析
|
||||
ParserEngine parser = new ParserEngine(tokens);
|
||||
ASTModule moduleAst = parser.parseModule();
|
||||
|
||||
// 4. 使用 AST
|
||||
System.out.println("解析成功,模块名:" + moduleAst.getName());
|
||||
ASTPrinter.print(moduleAst);
|
||||
// 词法分析
|
||||
LexerEngine lexerEngine = new LexerEngine(source);
|
||||
// 打印所有 Token
|
||||
TokenPrinter.printTokens(lexerEngine.getAllTokens());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
package org.jcnc.snow.compiler.parser;
|
||||
|
||||
/**
|
||||
* 抽象表达式节点基类。所有具体的表达式类型(如标识符、字面量、
|
||||
* 二元运算等)都应继承此类,以便在语法树中统一表示表达式。
|
||||
*
|
||||
* <p>子类示例:
|
||||
* <ul>
|
||||
* <li>{@link org.jcnc.snow.compiler.parser.ast.ASTIdentifier}:表示变量或标识符。</li>
|
||||
* <li>{@link org.jcnc.snow.compiler.parser.ast.ASTLiteral}:表示整数字面量。</li>
|
||||
* <li>{@link org.jcnc.snow.compiler.parser.ast.ASTBinaryOp}:表示加减乘除等二元运算。</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>在解析过程中,parseExpression 方法会创建具体的 ASTExpression 实例。
|
||||
* 后续阶段(如语义分析、代码生成)可通过 instanceof 或 Visitor 模式对
|
||||
* 不同子类进行处理。
|
||||
*
|
||||
*/
|
||||
public abstract class ASTExpression {
|
||||
// 该类仅作为标记类型,不包含公共字段或方法
|
||||
}
|
||||
@ -1,4 +0,0 @@
|
||||
package org.jcnc.snow.compiler.parser;
|
||||
|
||||
// ----------------- AST 节点定义 -----------------
|
||||
public abstract class ASTNode {}
|
||||
@ -1,15 +0,0 @@
|
||||
package org.jcnc.snow.compiler.parser;
|
||||
|
||||
/**
|
||||
* 抽象语句节点基类。所有语法树中的语句类型(如声明、返回、循环、条件等)
|
||||
* 都应继承自此类,以便在解析器和后续处理(如语义分析、生成代码)
|
||||
* 中统一识别和处理。
|
||||
*
|
||||
* <p>ASTStatement 继承自 ASTNode,包含共通的节点属性和方法。
|
||||
* 具体子类需要实现各自的构造器及特定字段,并根据需要重写
|
||||
* Visitor 模式或其他遍历/处理逻辑。
|
||||
*
|
||||
* @see ASTNode
|
||||
*/
|
||||
public abstract class ASTStatement extends ASTNode {
|
||||
}
|
||||
@ -1,318 +0,0 @@
|
||||
package org.jcnc.snow.compiler.parser;
|
||||
|
||||
import org.jcnc.snow.compiler.lexer.token.Token;
|
||||
import org.jcnc.snow.compiler.lexer.token.TokenType;
|
||||
import org.jcnc.snow.compiler.parser.ast.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 递归下降解析器,用于解析模块、函数、语句和表达式,并生成相应的AST节点。
|
||||
*
|
||||
* <p>使用给定的词法分析器生成的令牌序列,对语法结构进行逐步匹配和构建。
|
||||
* 提供对模块(module)、函数(function)、参数(parameter)、声明(declare)、循环(loop)、
|
||||
* 条件(if)、返回(return)以及二元表达式的支持。
|
||||
*
|
||||
* <p>抛出ASTBinaryOp.ParseException以报告解析错误。
|
||||
*/
|
||||
public class ParserEngine {
|
||||
/** 令牌序列 */
|
||||
private final List<Token> tokens;
|
||||
/** 当前处理的令牌位置 */
|
||||
private int pos = 0;
|
||||
|
||||
/**
|
||||
* 构造函数,初始化解析器。
|
||||
*
|
||||
* @param tokens 由词法分析器生成的令牌列表
|
||||
*/
|
||||
public ParserEngine(List<Token> tokens) {
|
||||
this.tokens = tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析整个模块结构,包含模块名和函数定义列表。
|
||||
*
|
||||
* <pre>
|
||||
* module: 模块开始标记
|
||||
* IDENTIFIER: 模块名称
|
||||
* end module: 模块结束标记
|
||||
* </pre>
|
||||
*
|
||||
* @return 构建好的ASTModule节点
|
||||
* @throws ASTBinaryOp.ParseException 当解析过程中出现不匹配或意外令牌时抛出
|
||||
*/
|
||||
public ASTModule parseModule() {
|
||||
match(TokenType.KEYWORD, "module");
|
||||
match(TokenType.COLON);
|
||||
String moduleName = current().getLexeme();
|
||||
match(TokenType.IDENTIFIER);
|
||||
match(TokenType.NEWLINE);
|
||||
|
||||
ASTModule module = new ASTModule(moduleName);
|
||||
while (!peek(TokenType.KEYWORD, "end")) {
|
||||
module.addFunction(parseFunction());
|
||||
}
|
||||
|
||||
match(TokenType.KEYWORD, "end");
|
||||
match(TokenType.KEYWORD, "module");
|
||||
match(TokenType.NEWLINE);
|
||||
return module;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析函数定义,包括参数列表、返回类型和函数体。
|
||||
*
|
||||
* <pre>
|
||||
* function: 函数开始标记
|
||||
* parameter (可选): 参数声明块
|
||||
* return_type: 返回类型
|
||||
* body: 函数体语句
|
||||
* end function: 函数结束标记
|
||||
* </pre>
|
||||
*
|
||||
* @return 构建好的ASTFunction节点
|
||||
* @throws ASTBinaryOp.ParseException 当解析过程中出现不匹配或意外令牌时抛出
|
||||
*/
|
||||
private ASTFunction parseFunction() {
|
||||
match(TokenType.KEYWORD, "function");
|
||||
match(TokenType.COLON);
|
||||
String funcName = current().getLexeme();
|
||||
match(TokenType.IDENTIFIER);
|
||||
match(TokenType.NEWLINE);
|
||||
|
||||
ASTFunction fn = new ASTFunction(funcName);
|
||||
if (peek(TokenType.KEYWORD, "parameter")) {
|
||||
match(TokenType.KEYWORD, "parameter");
|
||||
match(TokenType.COLON);
|
||||
match(TokenType.NEWLINE);
|
||||
while (peek(TokenType.KEYWORD, "declare")) {
|
||||
fn.addParameter(parseParameter());
|
||||
}
|
||||
}
|
||||
|
||||
match(TokenType.KEYWORD, "return_type");
|
||||
match(TokenType.COLON);
|
||||
String returnType = current().getLexeme();
|
||||
match(TokenType.TYPE);
|
||||
match(TokenType.NEWLINE);
|
||||
fn.setReturnType(returnType);
|
||||
|
||||
match(TokenType.KEYWORD, "body");
|
||||
match(TokenType.COLON);
|
||||
match(TokenType.NEWLINE);
|
||||
while (!peek(TokenType.KEYWORD, "end")) {
|
||||
fn.addStatement(parseStatement());
|
||||
}
|
||||
match(TokenType.KEYWORD, "end");
|
||||
match(TokenType.KEYWORD, "body");
|
||||
match(TokenType.NEWLINE);
|
||||
|
||||
match(TokenType.KEYWORD, "end");
|
||||
match(TokenType.KEYWORD, "function");
|
||||
match(TokenType.NEWLINE);
|
||||
return fn;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析单个参数声明。
|
||||
*
|
||||
* <pre>
|
||||
* declare IDENTIFIER:type
|
||||
* </pre>
|
||||
*
|
||||
* @return 构建好的ASTParameter节点
|
||||
* @throws ASTBinaryOp.ParseException 当解析过程中出现不匹配或意外令牌时抛出
|
||||
*/
|
||||
private ASTParameter parseParameter() {
|
||||
match(TokenType.KEYWORD, "declare");
|
||||
String name = current().getLexeme();
|
||||
match(TokenType.IDENTIFIER);
|
||||
match(TokenType.COLON);
|
||||
String type = current().getLexeme();
|
||||
match(TokenType.TYPE);
|
||||
match(TokenType.NEWLINE);
|
||||
return new ASTParameter(name, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析一条语句,根据关键字分发到不同的解析器。
|
||||
* 支持return、declare、loop和if语句。
|
||||
*
|
||||
* @return 对应的ASTStatement子类实例
|
||||
* @throws ASTBinaryOp.ParseException 当无法识别语句类型时抛出
|
||||
*/
|
||||
private ASTStatement parseStatement() {
|
||||
if (peek(TokenType.KEYWORD, "return")) {
|
||||
return parseReturn();
|
||||
} else if (peek(TokenType.KEYWORD, "declare")) {
|
||||
return parseDeclare();
|
||||
} else if (peek(TokenType.KEYWORD, "loop")) {
|
||||
return parseLoop();
|
||||
} else if (peek(TokenType.KEYWORD, "if")) {
|
||||
return parseIf();
|
||||
}
|
||||
throw new ASTBinaryOp.ParseException("无法识别的语句:" + current());
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析return语句。
|
||||
*
|
||||
* @return 构建好的ASTReturn节点,包含返回的表达式
|
||||
*/
|
||||
private ASTReturn parseReturn() {
|
||||
match(TokenType.KEYWORD, "return");
|
||||
ASTExpression expr = parseExpression();
|
||||
match(TokenType.NEWLINE);
|
||||
return new ASTReturn(expr);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析声明语句,可选带初始化表达式。
|
||||
*
|
||||
* @return 构建好的ASTDeclare节点,若无初始化则init为null
|
||||
*/
|
||||
private ASTDeclare parseDeclare() {
|
||||
match(TokenType.KEYWORD, "declare");
|
||||
String name = current().getLexeme(); match(TokenType.IDENTIFIER);
|
||||
match(TokenType.COLON);
|
||||
String type = current().getLexeme(); match(TokenType.TYPE);
|
||||
if (peek(TokenType.EQUALS)) {
|
||||
match(TokenType.EQUALS);
|
||||
ASTExpression init = parseExpression();
|
||||
match(TokenType.NEWLINE);
|
||||
return new ASTDeclare(name, type, init);
|
||||
} else {
|
||||
match(TokenType.NEWLINE);
|
||||
return new ASTDeclare(name, type, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析循环语句,包含初始化、条件、更新和循环体。
|
||||
*
|
||||
* @return 构建好的ASTLoop节点
|
||||
*/
|
||||
private ASTLoop parseLoop() {
|
||||
match(TokenType.KEYWORD, "loop"); match(TokenType.COLON);
|
||||
match(TokenType.NEWLINE);
|
||||
match(TokenType.KEYWORD, "initializer"); match(TokenType.COLON); match(TokenType.NEWLINE);
|
||||
ASTDeclare init = parseDeclare();
|
||||
match(TokenType.KEYWORD, "condition"); match(TokenType.COLON); match(TokenType.NEWLINE);
|
||||
ASTExpression cond = parseExpression(); match(TokenType.NEWLINE);
|
||||
match(TokenType.KEYWORD, "update"); match(TokenType.COLON); match(TokenType.NEWLINE);
|
||||
ASTDeclare update = parseDeclare();
|
||||
match(TokenType.KEYWORD, "body"); match(TokenType.COLON); match(TokenType.NEWLINE);
|
||||
List<ASTStatement> stmts = new ArrayList<>();
|
||||
while (!peek(TokenType.KEYWORD, "end")) {
|
||||
stmts.add(parseStatement());
|
||||
}
|
||||
match(TokenType.KEYWORD, "end"); match(TokenType.KEYWORD, "body"); match(TokenType.NEWLINE);
|
||||
match(TokenType.KEYWORD, "end"); match(TokenType.KEYWORD, "loop"); match(TokenType.NEWLINE);
|
||||
return new ASTLoop(init, cond, update, stmts);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析条件语句,仅支持单分支if。
|
||||
*
|
||||
* @return 构建好的ASTIf节点
|
||||
*/
|
||||
private ASTIf parseIf() {
|
||||
match(TokenType.KEYWORD, "if");
|
||||
ASTExpression cond = parseExpression();
|
||||
match(TokenType.KEYWORD, "then"); match(TokenType.NEWLINE);
|
||||
List<ASTStatement> thenStmts = new ArrayList<>();
|
||||
while (!peek(TokenType.KEYWORD, "end")) {
|
||||
thenStmts.add(parseStatement());
|
||||
}
|
||||
match(TokenType.KEYWORD, "end"); match(TokenType.KEYWORD, "if"); match(TokenType.NEWLINE);
|
||||
return new ASTIf(cond, thenStmts);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析表达式,支持标识符、整数字面量和加减乘除二元运算。
|
||||
* 实现左递归消除,通过递归调用构建二元运算树。
|
||||
*
|
||||
* @return 构建好的ASTExpression子类实例
|
||||
* @throws ASTBinaryOp.ParseException 当遇到意外令牌时抛出
|
||||
*/
|
||||
private ASTExpression parseExpression() {
|
||||
ASTExpression left;
|
||||
Token t = current();
|
||||
if (t.getType() == TokenType.IDENTIFIER) {
|
||||
left = new ASTIdentifier(t.getLexeme()); pos++;
|
||||
} else if (t.getType() == TokenType.NUMBER_LITERAL) {
|
||||
left = new ASTLiteral(Integer.parseInt(t.getLexeme())); pos++;
|
||||
} else {
|
||||
throw new ASTBinaryOp.ParseException("表达式解析错误,意外的令牌:" + t);
|
||||
}
|
||||
// 处理二元运算符
|
||||
Token opTok = current();
|
||||
String lex = opTok.getLexeme();
|
||||
if (opTok.getType() == TokenType.PLUS
|
||||
|| opTok.getType() == TokenType.MINUS
|
||||
|| opTok.getType() == TokenType.MULTIPLY
|
||||
|| lex.equals("/")) {
|
||||
String op = lex;
|
||||
pos++;
|
||||
ASTExpression right = parseExpression();
|
||||
return new ASTBinaryOp(left, op, right);
|
||||
}
|
||||
return left;
|
||||
}
|
||||
|
||||
// 工具方法
|
||||
/**
|
||||
* 获取当前令牌,如果超出范围则抛出异常。
|
||||
*
|
||||
* @return 当前Token
|
||||
* @throws ASTBinaryOp.ParseException 当访问越界时抛出
|
||||
*/
|
||||
private Token current() {
|
||||
if (pos >= tokens.size()) throw new ASTBinaryOp.ParseException("超出令牌范围");
|
||||
return tokens.get(pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断当前令牌类型是否匹配。
|
||||
*
|
||||
* @param type 期望的TokenType
|
||||
* @return 匹配返回true,否则false
|
||||
*/
|
||||
private boolean peek(TokenType type) {
|
||||
return current().getType() == type;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断当前令牌类型和词法是否与期望匹配。
|
||||
*
|
||||
* @param type 期望的TokenType
|
||||
* @param lexeme 期望的词法串
|
||||
* @return 匹配返回true,否则false
|
||||
*/
|
||||
private boolean peek(TokenType type, String lexeme) {
|
||||
return peek(type) && current().getLexeme().equals(lexeme);
|
||||
}
|
||||
|
||||
/**
|
||||
* 强制匹配当前令牌类型,如果不匹配则抛出异常。
|
||||
*
|
||||
* @param type 期望的TokenType
|
||||
* @throws ASTBinaryOp.ParseException 当不匹配时抛出,包含错误信息
|
||||
*/
|
||||
private void match(TokenType type) {
|
||||
if (peek(type)) pos++; else throw new ASTBinaryOp.ParseException("期望 " + type + " 但找到 " + current());
|
||||
}
|
||||
|
||||
/**
|
||||
* 强制匹配当前令牌类型和词法,如果不匹配则抛出异常。
|
||||
*
|
||||
* @param type 期望的TokenType
|
||||
* @param lexeme 期望的词法串
|
||||
* @throws ASTBinaryOp.ParseException 当不匹配时抛出,包含错误信息
|
||||
*/
|
||||
private void match(TokenType type, String lexeme) {
|
||||
if (peek(type, lexeme)) pos++; else throw new ASTBinaryOp.ParseException("期望 '" + lexeme + "' 但找到 " + current());
|
||||
}
|
||||
}
|
||||
@ -1,82 +0,0 @@
|
||||
package org.jcnc.snow.compiler.parser.ast;
|
||||
|
||||
import org.jcnc.snow.compiler.parser.ASTExpression;
|
||||
|
||||
/**
|
||||
* 表示一个二元运算表达式节点(例如加法、减法、乘法、除法)。
|
||||
* 在 AST 中,该节点有一个左子表达式、一个运算符和一个右子表达式。
|
||||
*/
|
||||
public class ASTBinaryOp extends ASTExpression {
|
||||
/**
|
||||
* 左侧操作数表达式。
|
||||
*/
|
||||
private final ASTExpression left;
|
||||
|
||||
/**
|
||||
* 运算符字符串(如 "+", "-", "*", "/")。
|
||||
*/
|
||||
private final String op;
|
||||
|
||||
/**
|
||||
* 右侧操作数表达式。
|
||||
*/
|
||||
private final ASTExpression right;
|
||||
|
||||
/**
|
||||
* 构造一个二元运算节点。
|
||||
*
|
||||
* @param left 左侧子表达式,不得为 {@code null}
|
||||
* @param op 运算符文本,例如 "+"、"-"、"*"、"/"
|
||||
* @param right 右侧子表达式,不得为 {@code null}
|
||||
* @throws IllegalArgumentException 如果 {@code left} 或 {@code right} 为 {@code null}
|
||||
*/
|
||||
public ASTBinaryOp(ASTExpression left, String op, ASTExpression right) {
|
||||
if (left == null || right == null) {
|
||||
throw new IllegalArgumentException("左右表达式都必须非空");
|
||||
}
|
||||
this.left = left;
|
||||
this.op = op;
|
||||
this.right = right;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取左侧子表达式。
|
||||
*
|
||||
* @return 左侧的 {@link ASTExpression} 节点
|
||||
*/
|
||||
public ASTExpression getLeft() {
|
||||
return left;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取二元运算符。
|
||||
*
|
||||
* @return 运算符字符串,如 "+"、"-" 等
|
||||
*/
|
||||
public String getOperator() {
|
||||
return op;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取右侧子表达式。
|
||||
*
|
||||
* @return 右侧的 {@link ASTExpression} 节点
|
||||
*/
|
||||
public ASTExpression getRight() {
|
||||
return right;
|
||||
}
|
||||
|
||||
/**
|
||||
* 在解析过程中遇到语法错误时抛出此异常。
|
||||
*/
|
||||
public static class ParseException extends RuntimeException {
|
||||
/**
|
||||
* 使用指定的错误消息构造一个解析异常。
|
||||
*
|
||||
* @param msg 错误描述
|
||||
*/
|
||||
public ParseException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
package org.jcnc.snow.compiler.parser.ast;
|
||||
|
||||
import org.jcnc.snow.compiler.parser.ASTExpression;
|
||||
import org.jcnc.snow.compiler.parser.ASTStatement;
|
||||
|
||||
public class ASTDeclare extends ASTStatement {
|
||||
final String name, type;
|
||||
final ASTExpression init;
|
||||
public ASTDeclare(String name, String type, ASTExpression init) {
|
||||
this.name = name; this.type = type; this.init = init;
|
||||
}
|
||||
public String getName() { return name; }
|
||||
public String getType() { return type; }
|
||||
public ASTExpression getInitExpression() { return init; }
|
||||
}
|
||||
@ -1,22 +0,0 @@
|
||||
package org.jcnc.snow.compiler.parser.ast;
|
||||
|
||||
import org.jcnc.snow.compiler.parser.ASTNode;
|
||||
import org.jcnc.snow.compiler.parser.ASTStatement;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ASTFunction extends ASTNode {
|
||||
private final String name;
|
||||
private String returnType;
|
||||
private final List<ASTParameter> params = new ArrayList<>();
|
||||
private final List<ASTStatement> body = new ArrayList<>();
|
||||
public ASTFunction(String name) { this.name = name; }
|
||||
public void addParameter(ASTParameter p) { params.add(p); }
|
||||
public void setReturnType(String t) { this.returnType = t; }
|
||||
public void addStatement(ASTStatement stmt) { body.add(stmt); }
|
||||
public String getName() { return name; }
|
||||
public String getReturnType() { return returnType; }
|
||||
public List<ASTParameter> getParameters() { return params; }
|
||||
public List<ASTStatement> getBody() { return body; }
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
package org.jcnc.snow.compiler.parser.ast;
|
||||
|
||||
import org.jcnc.snow.compiler.parser.ASTExpression;
|
||||
|
||||
public class ASTIdentifier extends ASTExpression {
|
||||
final String name;
|
||||
public ASTIdentifier(String name) { this.name = name; }
|
||||
public String getName() { return name; }
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
package org.jcnc.snow.compiler.parser.ast;
|
||||
|
||||
import org.jcnc.snow.compiler.parser.ASTExpression;
|
||||
import org.jcnc.snow.compiler.parser.ASTStatement;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ASTIf extends ASTStatement {
|
||||
final ASTExpression condition;
|
||||
final List<ASTStatement> thenStmts;
|
||||
public ASTIf(ASTExpression condition, List<ASTStatement> thenStmts) {
|
||||
this.condition = condition; this.thenStmts = thenStmts;
|
||||
}
|
||||
public ASTExpression getCondition() { return condition; }
|
||||
public List<ASTStatement> getThenStatements() { return thenStmts; }
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
package org.jcnc.snow.compiler.parser.ast;
|
||||
|
||||
import org.jcnc.snow.compiler.parser.ASTExpression;
|
||||
|
||||
public class ASTLiteral extends ASTExpression {
|
||||
final int value;
|
||||
public ASTLiteral(int value) { this.value = value; }
|
||||
public int getValue() { return value; }
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
package org.jcnc.snow.compiler.parser.ast;
|
||||
|
||||
import org.jcnc.snow.compiler.parser.ASTExpression;
|
||||
import org.jcnc.snow.compiler.parser.ASTStatement;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ASTLoop extends ASTStatement {
|
||||
final ASTDeclare init;
|
||||
final ASTExpression condition;
|
||||
final ASTDeclare update;
|
||||
final List<ASTStatement> body;
|
||||
public ASTLoop(ASTDeclare init, ASTExpression condition, ASTDeclare update, List<ASTStatement> body) {
|
||||
this.init = init; this.condition = condition; this.update = update; this.body = body;
|
||||
}
|
||||
public ASTDeclare getInit() { return init; }
|
||||
public ASTExpression getCondition() { return condition; }
|
||||
public ASTDeclare getUpdate() { return update; }
|
||||
public List<ASTStatement> getBody() { return body; }
|
||||
}
|
||||
@ -1,27 +0,0 @@
|
||||
package org.jcnc.snow.compiler.parser.ast;
|
||||
|
||||
import org.jcnc.snow.compiler.parser.ASTNode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ASTModule extends ASTNode {
|
||||
private final String name;
|
||||
private final List<ASTFunction> functions = new ArrayList<>();
|
||||
|
||||
public ASTModule(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void addFunction(ASTFunction fn) {
|
||||
functions.add(fn);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public List<ASTFunction> getFunctions() {
|
||||
return functions;
|
||||
}
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
package org.jcnc.snow.compiler.parser.ast;
|
||||
|
||||
import org.jcnc.snow.compiler.parser.ASTNode;
|
||||
|
||||
public class ASTParameter extends ASTNode {
|
||||
final String name, type;
|
||||
public ASTParameter(String name, String type) { this.name = name; this.type = type; }
|
||||
public String getName() { return name; }
|
||||
public String getType() { return type; }
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
package org.jcnc.snow.compiler.parser.ast;
|
||||
|
||||
import org.jcnc.snow.compiler.parser.ASTExpression;
|
||||
import org.jcnc.snow.compiler.parser.ASTStatement;
|
||||
|
||||
public class ASTReturn extends ASTStatement {
|
||||
final ASTExpression expr;
|
||||
public ASTReturn(ASTExpression expr) { this.expr = expr; }
|
||||
public ASTExpression getExpression() { return expr; }
|
||||
}
|
||||
@ -1,90 +0,0 @@
|
||||
package org.jcnc.snow.compiler.parser.utils;
|
||||
|
||||
import org.jcnc.snow.compiler.parser.ASTExpression;
|
||||
import org.jcnc.snow.compiler.parser.ASTStatement;
|
||||
import org.jcnc.snow.compiler.parser.ast.*;
|
||||
|
||||
// ----------------- AST 打印工具 -----------------
|
||||
public class ASTPrinter {
|
||||
private static final String INDENT = " ";
|
||||
|
||||
public static void print(ASTModule module) {
|
||||
System.out.println("Module: " + module.getName());
|
||||
for (ASTFunction fn : module.getFunctions()) {
|
||||
printFunction(fn, 1);
|
||||
}
|
||||
}
|
||||
|
||||
private static void printFunction(ASTFunction fn, int level) {
|
||||
String indent = INDENT.repeat(level);
|
||||
System.out.println(indent + "Function: " + fn.getName() + " returns " + fn.getReturnType());
|
||||
if (!fn.getParameters().isEmpty()) {
|
||||
System.out.println(indent + " Parameters:");
|
||||
for (ASTParameter p : fn.getParameters()) {
|
||||
System.out.println(indent + " - " + p.getName() + ": " + p.getType());
|
||||
}
|
||||
}
|
||||
System.out.println(indent + " Body:");
|
||||
for (ASTStatement stmt : fn.getBody()) {
|
||||
printStatement(stmt, level + 2);
|
||||
}
|
||||
}
|
||||
|
||||
private static void printStatement(ASTStatement stmt, int level) {
|
||||
String indent = INDENT.repeat(level);
|
||||
switch (stmt) {
|
||||
case ASTReturn astReturn -> {
|
||||
System.out.print(indent + "Return: ");
|
||||
printExpression(astReturn.getExpression());
|
||||
System.out.println();
|
||||
}
|
||||
case ASTDeclare d -> {
|
||||
System.out.print(indent + "Declare " + d.getName() + ": " + d.getType());
|
||||
if (d.getInitExpression() != null) {
|
||||
System.out.print(" = ");
|
||||
printExpression(d.getInitExpression());
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
case ASTLoop loop -> {
|
||||
System.out.println(indent + "Loop:");
|
||||
System.out.print(indent + " Init: ");
|
||||
printStatement(loop.getInit(), 0);
|
||||
System.out.print(indent + " Condition: ");
|
||||
printExpression(loop.getCondition());
|
||||
System.out.println();
|
||||
System.out.print(indent + " Update: ");
|
||||
printStatement(loop.getUpdate(), 0);
|
||||
System.out.println(indent + " Body:");
|
||||
for (ASTStatement s : loop.getBody()) {
|
||||
printStatement(s, level + 2);
|
||||
}
|
||||
}
|
||||
case ASTIf ifs -> {
|
||||
System.out.print(indent + "If condition: ");
|
||||
printExpression(ifs.getCondition());
|
||||
System.out.println();
|
||||
System.out.println(indent + " Then:");
|
||||
for (ASTStatement s : ifs.getThenStatements()) {
|
||||
printStatement(s, level + 2);
|
||||
}
|
||||
}
|
||||
default -> System.out.println(indent + stmt.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
private static void printExpression(ASTExpression expr) {
|
||||
switch (expr) {
|
||||
case ASTLiteral astLiteral -> System.out.print(astLiteral.getValue());
|
||||
case ASTIdentifier astIdentifier -> System.out.print(astIdentifier.getName());
|
||||
case ASTBinaryOp bin -> {
|
||||
System.out.print("(");
|
||||
printExpression(bin.getLeft());
|
||||
System.out.print(" " + bin.getOperator() + " ");
|
||||
printExpression(bin.getRight());
|
||||
System.out.print(")");
|
||||
}
|
||||
default -> System.out.print(expr.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user