fix:ast
This commit is contained in:
parent
85ec6c3700
commit
06ccb4f280
@ -3,7 +3,7 @@ package org.jcnc.snow.compiler;
|
|||||||
import org.jcnc.snow.compiler.lexer.LexerEngine;
|
import org.jcnc.snow.compiler.lexer.LexerEngine;
|
||||||
import org.jcnc.snow.compiler.lexer.token.Token;
|
import org.jcnc.snow.compiler.lexer.token.Token;
|
||||||
import org.jcnc.snow.compiler.parser.ast.ASTModule;
|
import org.jcnc.snow.compiler.parser.ast.ASTModule;
|
||||||
import org.jcnc.snow.compiler.parser.ASTPrinter;
|
import org.jcnc.snow.compiler.parser.utils.ASTPrinter;
|
||||||
import org.jcnc.snow.compiler.parser.ParserEngine;
|
import org.jcnc.snow.compiler.parser.ParserEngine;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|||||||
@ -1,8 +1,21 @@
|
|||||||
package org.jcnc.snow.compiler.parser;
|
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 {
|
public abstract class ASTExpression {
|
||||||
|
// 该类仅作为标记类型,不包含公共字段或方法
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,15 @@
|
|||||||
package org.jcnc.snow.compiler.parser;
|
package org.jcnc.snow.compiler.parser;
|
||||||
|
|
||||||
public abstract class ASTStatement extends ASTNode {}
|
/**
|
||||||
|
* 抽象语句节点基类。所有语法树中的语句类型(如声明、返回、循环、条件等)
|
||||||
|
* 都应继承自此类,以便在解析器和后续处理(如语义分析、生成代码)
|
||||||
|
* 中统一识别和处理。
|
||||||
|
*
|
||||||
|
* <p>ASTStatement 继承自 ASTNode,包含共通的节点属性和方法。
|
||||||
|
* 具体子类需要实现各自的构造器及特定字段,并根据需要重写
|
||||||
|
* Visitor 模式或其他遍历/处理逻辑。
|
||||||
|
*
|
||||||
|
* @see ASTNode
|
||||||
|
*/
|
||||||
|
public abstract class ASTStatement extends ASTNode {
|
||||||
|
}
|
||||||
@ -8,16 +8,41 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 递归下降解析器,实现对模块、函数、语句和表达式的完整解析
|
* 递归下降解析器,用于解析模块、函数、语句和表达式,并生成相应的AST节点。
|
||||||
|
*
|
||||||
|
* <p>使用给定的词法分析器生成的令牌序列,对语法结构进行逐步匹配和构建。
|
||||||
|
* 提供对模块(module)、函数(function)、参数(parameter)、声明(declare)、循环(loop)、
|
||||||
|
* 条件(if)、返回(return)以及二元表达式的支持。
|
||||||
|
*
|
||||||
|
* <p>抛出ASTBinaryOp.ParseException以报告解析错误。
|
||||||
*/
|
*/
|
||||||
public class ParserEngine {
|
public class ParserEngine {
|
||||||
|
/** 令牌序列 */
|
||||||
private final List<Token> tokens;
|
private final List<Token> tokens;
|
||||||
|
/** 当前处理的令牌位置 */
|
||||||
private int pos = 0;
|
private int pos = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造函数,初始化解析器。
|
||||||
|
*
|
||||||
|
* @param tokens 由词法分析器生成的令牌列表
|
||||||
|
*/
|
||||||
public ParserEngine(List<Token> tokens) {
|
public ParserEngine(List<Token> tokens) {
|
||||||
this.tokens = tokens;
|
this.tokens = tokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析整个模块结构,包含模块名和函数定义列表。
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* module: 模块开始标记
|
||||||
|
* IDENTIFIER: 模块名称
|
||||||
|
* end module: 模块结束标记
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @return 构建好的ASTModule节点
|
||||||
|
* @throws ASTBinaryOp.ParseException 当解析过程中出现不匹配或意外令牌时抛出
|
||||||
|
*/
|
||||||
public ASTModule parseModule() {
|
public ASTModule parseModule() {
|
||||||
match(TokenType.KEYWORD, "module");
|
match(TokenType.KEYWORD, "module");
|
||||||
match(TokenType.COLON);
|
match(TokenType.COLON);
|
||||||
@ -36,6 +61,20 @@ public class ParserEngine {
|
|||||||
return module;
|
return module;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析函数定义,包括参数列表、返回类型和函数体。
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* function: 函数开始标记
|
||||||
|
* parameter (可选): 参数声明块
|
||||||
|
* return_type: 返回类型
|
||||||
|
* body: 函数体语句
|
||||||
|
* end function: 函数结束标记
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @return 构建好的ASTFunction节点
|
||||||
|
* @throws ASTBinaryOp.ParseException 当解析过程中出现不匹配或意外令牌时抛出
|
||||||
|
*/
|
||||||
private ASTFunction parseFunction() {
|
private ASTFunction parseFunction() {
|
||||||
match(TokenType.KEYWORD, "function");
|
match(TokenType.KEYWORD, "function");
|
||||||
match(TokenType.COLON);
|
match(TokenType.COLON);
|
||||||
@ -76,6 +115,16 @@ public class ParserEngine {
|
|||||||
return fn;
|
return fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析单个参数声明。
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* declare IDENTIFIER:type
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @return 构建好的ASTParameter节点
|
||||||
|
* @throws ASTBinaryOp.ParseException 当解析过程中出现不匹配或意外令牌时抛出
|
||||||
|
*/
|
||||||
private ASTParameter parseParameter() {
|
private ASTParameter parseParameter() {
|
||||||
match(TokenType.KEYWORD, "declare");
|
match(TokenType.KEYWORD, "declare");
|
||||||
String name = current().getLexeme();
|
String name = current().getLexeme();
|
||||||
@ -87,6 +136,13 @@ public class ParserEngine {
|
|||||||
return new ASTParameter(name, type);
|
return new ASTParameter(name, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析一条语句,根据关键字分发到不同的解析器。
|
||||||
|
* 支持return、declare、loop和if语句。
|
||||||
|
*
|
||||||
|
* @return 对应的ASTStatement子类实例
|
||||||
|
* @throws ASTBinaryOp.ParseException 当无法识别语句类型时抛出
|
||||||
|
*/
|
||||||
private ASTStatement parseStatement() {
|
private ASTStatement parseStatement() {
|
||||||
if (peek(TokenType.KEYWORD, "return")) {
|
if (peek(TokenType.KEYWORD, "return")) {
|
||||||
return parseReturn();
|
return parseReturn();
|
||||||
@ -100,6 +156,11 @@ public class ParserEngine {
|
|||||||
throw new ASTBinaryOp.ParseException("无法识别的语句:" + current());
|
throw new ASTBinaryOp.ParseException("无法识别的语句:" + current());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析return语句。
|
||||||
|
*
|
||||||
|
* @return 构建好的ASTReturn节点,包含返回的表达式
|
||||||
|
*/
|
||||||
private ASTReturn parseReturn() {
|
private ASTReturn parseReturn() {
|
||||||
match(TokenType.KEYWORD, "return");
|
match(TokenType.KEYWORD, "return");
|
||||||
ASTExpression expr = parseExpression();
|
ASTExpression expr = parseExpression();
|
||||||
@ -107,6 +168,11 @@ public class ParserEngine {
|
|||||||
return new ASTReturn(expr);
|
return new ASTReturn(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析声明语句,可选带初始化表达式。
|
||||||
|
*
|
||||||
|
* @return 构建好的ASTDeclare节点,若无初始化则init为null
|
||||||
|
*/
|
||||||
private ASTDeclare parseDeclare() {
|
private ASTDeclare parseDeclare() {
|
||||||
match(TokenType.KEYWORD, "declare");
|
match(TokenType.KEYWORD, "declare");
|
||||||
String name = current().getLexeme(); match(TokenType.IDENTIFIER);
|
String name = current().getLexeme(); match(TokenType.IDENTIFIER);
|
||||||
@ -123,6 +189,11 @@ public class ParserEngine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析循环语句,包含初始化、条件、更新和循环体。
|
||||||
|
*
|
||||||
|
* @return 构建好的ASTLoop节点
|
||||||
|
*/
|
||||||
private ASTLoop parseLoop() {
|
private ASTLoop parseLoop() {
|
||||||
match(TokenType.KEYWORD, "loop"); match(TokenType.COLON);
|
match(TokenType.KEYWORD, "loop"); match(TokenType.COLON);
|
||||||
match(TokenType.NEWLINE);
|
match(TokenType.NEWLINE);
|
||||||
@ -142,6 +213,11 @@ public class ParserEngine {
|
|||||||
return new ASTLoop(init, cond, update, stmts);
|
return new ASTLoop(init, cond, update, stmts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析条件语句,仅支持单分支if。
|
||||||
|
*
|
||||||
|
* @return 构建好的ASTIf节点
|
||||||
|
*/
|
||||||
private ASTIf parseIf() {
|
private ASTIf parseIf() {
|
||||||
match(TokenType.KEYWORD, "if");
|
match(TokenType.KEYWORD, "if");
|
||||||
ASTExpression cond = parseExpression();
|
ASTExpression cond = parseExpression();
|
||||||
@ -154,6 +230,13 @@ public class ParserEngine {
|
|||||||
return new ASTIf(cond, thenStmts);
|
return new ASTIf(cond, thenStmts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析表达式,支持标识符、整数字面量和加减乘除二元运算。
|
||||||
|
* 实现左递归消除,通过递归调用构建二元运算树。
|
||||||
|
*
|
||||||
|
* @return 构建好的ASTExpression子类实例
|
||||||
|
* @throws ASTBinaryOp.ParseException 当遇到意外令牌时抛出
|
||||||
|
*/
|
||||||
private ASTExpression parseExpression() {
|
private ASTExpression parseExpression() {
|
||||||
ASTExpression left;
|
ASTExpression left;
|
||||||
Token t = current();
|
Token t = current();
|
||||||
@ -164,13 +247,13 @@ public class ParserEngine {
|
|||||||
} else {
|
} else {
|
||||||
throw new ASTBinaryOp.ParseException("表达式解析错误,意外的令牌:" + t);
|
throw new ASTBinaryOp.ParseException("表达式解析错误,意外的令牌:" + t);
|
||||||
}
|
}
|
||||||
// 处理二元运算
|
// 处理二元运算符
|
||||||
Token opTok = current();
|
Token opTok = current();
|
||||||
String lex = opTok.getLexeme();
|
String lex = opTok.getLexeme();
|
||||||
if (opTok.getType() == TokenType.PLUS
|
if (opTok.getType() == TokenType.PLUS
|
||||||
|| opTok.getType() == TokenType.MINUS
|
|| opTok.getType() == TokenType.MINUS
|
||||||
|| opTok.getType() == TokenType.MULTIPLY
|
|| opTok.getType() == TokenType.MULTIPLY
|
||||||
|| lex.equals("/")) {
|
|| lex.equals("/")) {
|
||||||
String op = lex;
|
String op = lex;
|
||||||
pos++;
|
pos++;
|
||||||
ASTExpression right = parseExpression();
|
ASTExpression right = parseExpression();
|
||||||
@ -180,22 +263,56 @@ public class ParserEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 工具方法
|
// 工具方法
|
||||||
|
/**
|
||||||
|
* 获取当前令牌,如果超出范围则抛出异常。
|
||||||
|
*
|
||||||
|
* @return 当前Token
|
||||||
|
* @throws ASTBinaryOp.ParseException 当访问越界时抛出
|
||||||
|
*/
|
||||||
private Token current() {
|
private Token current() {
|
||||||
if (pos >= tokens.size()) throw new ASTBinaryOp.ParseException("超出令牌范围");
|
if (pos >= tokens.size()) throw new ASTBinaryOp.ParseException("超出令牌范围");
|
||||||
return tokens.get(pos);
|
return tokens.get(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断当前令牌类型是否匹配。
|
||||||
|
*
|
||||||
|
* @param type 期望的TokenType
|
||||||
|
* @return 匹配返回true,否则false
|
||||||
|
*/
|
||||||
private boolean peek(TokenType type) {
|
private boolean peek(TokenType type) {
|
||||||
return current().getType() == type;
|
return current().getType() == type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断当前令牌类型和词法是否与期望匹配。
|
||||||
|
*
|
||||||
|
* @param type 期望的TokenType
|
||||||
|
* @param lexeme 期望的词法串
|
||||||
|
* @return 匹配返回true,否则false
|
||||||
|
*/
|
||||||
private boolean peek(TokenType type, String lexeme) {
|
private boolean peek(TokenType type, String lexeme) {
|
||||||
return peek(type) && current().getLexeme().equals(lexeme);
|
return peek(type) && current().getLexeme().equals(lexeme);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 强制匹配当前令牌类型,如果不匹配则抛出异常。
|
||||||
|
*
|
||||||
|
* @param type 期望的TokenType
|
||||||
|
* @throws ASTBinaryOp.ParseException 当不匹配时抛出,包含错误信息
|
||||||
|
*/
|
||||||
private void match(TokenType type) {
|
private void match(TokenType type) {
|
||||||
if (peek(type)) pos++; else throw new ASTBinaryOp.ParseException("期望 " + type + " 但找到 " + current());
|
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) {
|
private void match(TokenType type, String lexeme) {
|
||||||
if (peek(type, lexeme)) pos++; else throw new ASTBinaryOp.ParseException("期望 '" + lexeme + "' 但找到 " + current());
|
if (peek(type, lexeme)) pos++; else throw new ASTBinaryOp.ParseException("期望 '" + lexeme + "' 但找到 " + current());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
package org.jcnc.snow.compiler.parser;
|
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.*;
|
import org.jcnc.snow.compiler.parser.ast.*;
|
||||||
|
|
||||||
// ----------------- AST 打印工具 -----------------
|
// ----------------- AST 打印工具 -----------------
|
||||||
Loading…
x
Reference in New Issue
Block a user