使用纪录类
This commit is contained in:
parent
8d1b180c2d
commit
157f1e2f11
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/ast/JsonFormatter.java
|
|
||||||
package org.jcnc.snow.compiler;
|
package org.jcnc.snow.compiler;
|
||||||
|
|
||||||
public class JsonFormatter {
|
public class JsonFormatter {
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/ParserEngine.java
|
|
||||||
package org.jcnc.snow.compiler.parser;
|
package org.jcnc.snow.compiler.parser;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.lexer.token.TokenType;
|
import org.jcnc.snow.compiler.lexer.token.TokenType;
|
||||||
@ -23,7 +22,7 @@ public class ParserEngine {
|
|||||||
public List<Node> parse() {
|
public List<Node> parse() {
|
||||||
List<Node> nodes = new ArrayList<>();
|
List<Node> nodes = new ArrayList<>();
|
||||||
TokenStream ts = ctx.getTokens();
|
TokenStream ts = ctx.getTokens();
|
||||||
while (!ts.isAtEnd()) {
|
while (ts.isAtEnd()) {
|
||||||
// 跳过空行(NEWLINE)
|
// 跳过空行(NEWLINE)
|
||||||
if (ts.peek().getType() == TokenType.NEWLINE) {
|
if (ts.peek().getType() == TokenType.NEWLINE) {
|
||||||
ts.next();
|
ts.next();
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/TopLevelParser.java
|
|
||||||
package org.jcnc.snow.compiler.parser;
|
package org.jcnc.snow.compiler.parser;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.parser.context.ParserContext;
|
import org.jcnc.snow.compiler.parser.context.ParserContext;
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/ast/ASTJsonSerializer.java
|
|
||||||
package org.jcnc.snow.compiler.parser.ast;
|
package org.jcnc.snow.compiler.parser.ast;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -39,7 +38,7 @@ public class ASTJsonSerializer {
|
|||||||
for (int i = 0; i < m.getImports().size(); i++) {
|
for (int i = 0; i < m.getImports().size(); i++) {
|
||||||
ImportNode imp = m.getImports().get(i);
|
ImportNode imp = m.getImports().get(i);
|
||||||
sb.append("{\"type\":\"Import\",\"module\":")
|
sb.append("{\"type\":\"Import\",\"module\":")
|
||||||
.append(quote(imp.getModuleName())).append("}");
|
.append(quote(imp.moduleName())).append("}");
|
||||||
if (i + 1 < m.getImports().size()) sb.append(",");
|
if (i + 1 < m.getImports().size()) sb.append(",");
|
||||||
}
|
}
|
||||||
sb.append("],");
|
sb.append("],");
|
||||||
@ -56,20 +55,20 @@ public class ASTJsonSerializer {
|
|||||||
private static String functionToJson(FunctionNode f) {
|
private static String functionToJson(FunctionNode f) {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append("{\"type\":\"Function\",")
|
sb.append("{\"type\":\"Function\",")
|
||||||
.append("\"name\":").append(quote(f.getName())).append(",");
|
.append("\"name\":").append(quote(f.name())).append(",");
|
||||||
// parameters
|
// parameters
|
||||||
sb.append("\"parameters\":[");
|
sb.append("\"parameters\":[");
|
||||||
for (int i = 0; i < f.getParameters().size(); i++) {
|
for (int i = 0; i < f.parameters().size(); i++) {
|
||||||
ParameterNode p = f.getParameters().get(i);
|
ParameterNode p = f.parameters().get(i);
|
||||||
sb.append("{\"name\":").append(quote(p.getName()))
|
sb.append("{\"name\":").append(quote(p.name()))
|
||||||
.append(",\"type\":").append(quote(p.getType())).append("}");
|
.append(",\"type\":").append(quote(p.type())).append("}");
|
||||||
if (i + 1 < f.getParameters().size()) sb.append(",");
|
if (i + 1 < f.parameters().size()) sb.append(",");
|
||||||
}
|
}
|
||||||
sb.append("],");
|
sb.append("],");
|
||||||
sb.append("\"returnType\":").append(quote(f.getReturnType())).append(",");
|
sb.append("\"returnType\":").append(quote(f.returnType())).append(",");
|
||||||
// body
|
// body
|
||||||
sb.append("\"body\":[");
|
sb.append("\"body\":[");
|
||||||
List<StatementNode> body = f.getBody();
|
List<StatementNode> body = f.body();
|
||||||
for (int i = 0; i < body.size(); i++) {
|
for (int i = 0; i < body.size(); i++) {
|
||||||
sb.append(nodeToJson(body.get(i)));
|
sb.append(nodeToJson(body.get(i)));
|
||||||
if (i + 1 < body.size()) sb.append(",");
|
if (i + 1 < body.size()) sb.append(",");
|
||||||
@ -92,18 +91,18 @@ public class ASTJsonSerializer {
|
|||||||
|
|
||||||
private static String assignmentToJson(AssignmentNode a) {
|
private static String assignmentToJson(AssignmentNode a) {
|
||||||
return "{\"type\":\"Assignment\",\"variable\":"
|
return "{\"type\":\"Assignment\",\"variable\":"
|
||||||
+ quote(a.getVariable())
|
+ quote(a.variable())
|
||||||
+ ",\"value\":"
|
+ ",\"value\":"
|
||||||
+ exprToJson(a.getValue())
|
+ exprToJson(a.value())
|
||||||
+ "}";
|
+ "}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String ifToJson(IfNode i) {
|
private static String ifToJson(IfNode i) {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append("{\"type\":\"If\",\"condition\":")
|
sb.append("{\"type\":\"If\",\"condition\":")
|
||||||
.append(exprToJson(i.getCondition())).append(",");
|
.append(exprToJson(i.condition())).append(",");
|
||||||
sb.append("\"then\":[");
|
sb.append("\"then\":[");
|
||||||
List<StatementNode> thenBranch = i.getThenBranch();
|
List<StatementNode> thenBranch = i.thenBranch();
|
||||||
for (int j = 0; j < thenBranch.size(); j++) {
|
for (int j = 0; j < thenBranch.size(); j++) {
|
||||||
sb.append(nodeToJson(thenBranch.get(j)));
|
sb.append(nodeToJson(thenBranch.get(j)));
|
||||||
if (j + 1 < thenBranch.size()) sb.append(",");
|
if (j + 1 < thenBranch.size()) sb.append(",");
|
||||||
@ -115,11 +114,11 @@ public class ASTJsonSerializer {
|
|||||||
private static String loopToJson(LoopNode l) {
|
private static String loopToJson(LoopNode l) {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append("{\"type\":\"Loop\",")
|
sb.append("{\"type\":\"Loop\",")
|
||||||
.append("\"initializer\":").append(nodeToJson(l.getInitializer())).append(",")
|
.append("\"initializer\":").append(nodeToJson(l.initializer())).append(",")
|
||||||
.append("\"condition\":").append(exprToJson(l.getCondition())).append(",")
|
.append("\"condition\":").append(exprToJson(l.condition())).append(",")
|
||||||
.append("\"update\":").append(nodeToJson(l.getUpdate())).append(",")
|
.append("\"update\":").append(nodeToJson(l.update())).append(",")
|
||||||
.append("\"body\":[");
|
.append("\"body\":[");
|
||||||
List<StatementNode> body = l.getBody();
|
List<StatementNode> body = l.body();
|
||||||
for (int i = 0; i < body.size(); i++) {
|
for (int i = 0; i < body.size(); i++) {
|
||||||
sb.append(nodeToJson(body.get(i)));
|
sb.append(nodeToJson(body.get(i)));
|
||||||
if (i + 1 < body.size()) sb.append(",");
|
if (i + 1 < body.size()) sb.append(",");
|
||||||
@ -140,7 +139,7 @@ public class ASTJsonSerializer {
|
|||||||
|
|
||||||
private static String exprStmtToJson(ExpressionStatementNode es) {
|
private static String exprStmtToJson(ExpressionStatementNode es) {
|
||||||
return "{\"type\":\"ExpressionStatement\",\"expression\":"
|
return "{\"type\":\"ExpressionStatement\",\"expression\":"
|
||||||
+ exprToJson(es.getExpression())
|
+ exprToJson(es.expression())
|
||||||
+ "}";
|
+ "}";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,30 +162,30 @@ public class ASTJsonSerializer {
|
|||||||
+ "}";
|
+ "}";
|
||||||
}
|
}
|
||||||
private static String idToJson(IdentifierNode id) {
|
private static String idToJson(IdentifierNode id) {
|
||||||
return "{\"type\":\"Identifier\",\"name\":" + quote(id.getName()) + "}";
|
return "{\"type\":\"Identifier\",\"name\":" + quote(id.name()) + "}";
|
||||||
}
|
}
|
||||||
private static String numToJson(NumberLiteralNode num) {
|
private static String numToJson(NumberLiteralNode num) {
|
||||||
return "{\"type\":\"NumberLiteral\",\"value\":" + quote(num.getValue()) + "}";
|
return "{\"type\":\"NumberLiteral\",\"value\":" + quote(num.value()) + "}";
|
||||||
}
|
}
|
||||||
private static String strToJson(StringLiteralNode str) {
|
private static String strToJson(StringLiteralNode str) {
|
||||||
return "{\"type\":\"StringLiteral\",\"value\":" + quote(str.getValue()) + "}";
|
return "{\"type\":\"StringLiteral\",\"value\":" + quote(str.value()) + "}";
|
||||||
}
|
}
|
||||||
private static String callToJson(CallExpressionNode c) {
|
private static String callToJson(CallExpressionNode c) {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append("{\"type\":\"CallExpression\",\"callee\":")
|
sb.append("{\"type\":\"CallExpression\",\"callee\":")
|
||||||
.append(exprToJson(c.getCallee())).append(",")
|
.append(exprToJson(c.callee())).append(",")
|
||||||
.append("\"arguments\":[");
|
.append("\"arguments\":[");
|
||||||
for (int i = 0; i < c.getArguments().size(); i++) {
|
for (int i = 0; i < c.arguments().size(); i++) {
|
||||||
sb.append(exprToJson(c.getArguments().get(i)));
|
sb.append(exprToJson(c.arguments().get(i)));
|
||||||
if (i + 1 < c.getArguments().size()) sb.append(",");
|
if (i + 1 < c.arguments().size()) sb.append(",");
|
||||||
}
|
}
|
||||||
sb.append("]}");
|
sb.append("]}");
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
private static String memberToJson(MemberExpressionNode m) {
|
private static String memberToJson(MemberExpressionNode m) {
|
||||||
return "{\"type\":\"MemberExpression\",\"object\":"
|
return "{\"type\":\"MemberExpression\",\"object\":"
|
||||||
+ exprToJson(m.getObject())
|
+ exprToJson(m.object())
|
||||||
+ ",\"member\":" + quote(m.getMember())
|
+ ",\"member\":" + quote(m.member())
|
||||||
+ "}";
|
+ "}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/ast/ASTPrinter.java
|
|
||||||
package org.jcnc.snow.compiler.parser.ast;
|
package org.jcnc.snow.compiler.parser.ast;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -19,16 +18,16 @@ public class ASTPrinter {
|
|||||||
if (n instanceof ModuleNode m) {
|
if (n instanceof ModuleNode m) {
|
||||||
System.out.println(pad + "module " + m.getName());
|
System.out.println(pad + "module " + m.getName());
|
||||||
for (ImportNode imp : m.getImports()) {
|
for (ImportNode imp : m.getImports()) {
|
||||||
System.out.println(pad + " import " + imp.getModuleName());
|
System.out.println(pad + " import " + imp.moduleName());
|
||||||
}
|
}
|
||||||
for (FunctionNode fn : m.getFunctions()) {
|
for (FunctionNode fn : m.getFunctions()) {
|
||||||
print(fn, indent + 1);
|
print(fn, indent + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (n instanceof FunctionNode f) {
|
} else if (n instanceof FunctionNode f) {
|
||||||
System.out.println(pad + "function " + f.getName()
|
System.out.println(pad + "function " + f.name()
|
||||||
+ "(params=" + f.getParameters() + ", return=" + f.getReturnType() + ")");
|
+ "(params=" + f.parameters() + ", return=" + f.returnType() + ")");
|
||||||
for (StatementNode stmt : f.getBody()) {
|
for (StatementNode stmt : f.body()) {
|
||||||
print(stmt, indent + 1);
|
print(stmt, indent + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,21 +39,21 @@ public class ASTPrinter {
|
|||||||
System.out.println(pad + "declare " + d.getName() + ":" + d.getType() + init);
|
System.out.println(pad + "declare " + d.getName() + ":" + d.getType() + init);
|
||||||
|
|
||||||
} else if (n instanceof AssignmentNode a) {
|
} else if (n instanceof AssignmentNode a) {
|
||||||
System.out.println(pad + a.getVariable() + " = " + a.getValue());
|
System.out.println(pad + a.variable() + " = " + a.value());
|
||||||
|
|
||||||
} else if (n instanceof IfNode i) {
|
} else if (n instanceof IfNode i) {
|
||||||
System.out.println(pad + "if " + i.getCondition());
|
System.out.println(pad + "if " + i.condition());
|
||||||
for (StatementNode stmt : i.getThenBranch()) {
|
for (StatementNode stmt : i.thenBranch()) {
|
||||||
print(stmt, indent + 1);
|
print(stmt, indent + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (n instanceof LoopNode l) {
|
} else if (n instanceof LoopNode l) {
|
||||||
System.out.println(pad + "loop {");
|
System.out.println(pad + "loop {");
|
||||||
print(l.getInitializer(), indent + 1);
|
print(l.initializer(), indent + 1);
|
||||||
System.out.println(pad + " condition: " + l.getCondition());
|
System.out.println(pad + " condition: " + l.condition());
|
||||||
System.out.println(pad + " update: " + l.getUpdate());
|
System.out.println(pad + " update: " + l.update());
|
||||||
System.out.println(pad + " body {");
|
System.out.println(pad + " body {");
|
||||||
for (StatementNode stmt : l.getBody()) {
|
for (StatementNode stmt : l.body()) {
|
||||||
print(stmt, indent + 2);
|
print(stmt, indent + 2);
|
||||||
}
|
}
|
||||||
System.out.println(pad + " }");
|
System.out.println(pad + " }");
|
||||||
@ -65,7 +64,7 @@ public class ASTPrinter {
|
|||||||
r.getExpression().map(e -> " " + e).orElse(""));
|
r.getExpression().map(e -> " " + e).orElse(""));
|
||||||
|
|
||||||
} else if (n instanceof ExpressionStatementNode es) {
|
} else if (n instanceof ExpressionStatementNode es) {
|
||||||
System.out.println(pad + es.getExpression());
|
System.out.println(pad + es.expression());
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// 回退:直接调用 toString()
|
// 回退:直接调用 toString()
|
||||||
|
|||||||
@ -1,25 +1,9 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/ast/AssignmentNode.java
|
|
||||||
package org.jcnc.snow.compiler.parser.ast;
|
package org.jcnc.snow.compiler.parser.ast;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 赋值语句节点,例如 x = expr。
|
* 赋值语句节点,例如 x = expr。
|
||||||
*/
|
*/
|
||||||
public class AssignmentNode implements StatementNode {
|
public record AssignmentNode(String variable, ExpressionNode value) implements StatementNode {
|
||||||
private final String variable;
|
|
||||||
private final ExpressionNode value;
|
|
||||||
|
|
||||||
public AssignmentNode(String variable, ExpressionNode value) {
|
|
||||||
this.variable = variable;
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getVariable() {
|
|
||||||
return variable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ExpressionNode getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/ast/BinaryExpressionNode.java
|
|
||||||
package org.jcnc.snow.compiler.parser.ast;
|
package org.jcnc.snow.compiler.parser.ast;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/ast/CallExpressionNode.java
|
|
||||||
package org.jcnc.snow.compiler.parser.ast;
|
package org.jcnc.snow.compiler.parser.ast;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -6,17 +5,7 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* 函数调用表达式节点:callee(args…)。
|
* 函数调用表达式节点:callee(args…)。
|
||||||
*/
|
*/
|
||||||
public class CallExpressionNode implements ExpressionNode {
|
public record CallExpressionNode(ExpressionNode callee, List<ExpressionNode> arguments) implements ExpressionNode {
|
||||||
private final ExpressionNode callee;
|
|
||||||
private final List<ExpressionNode> arguments;
|
|
||||||
|
|
||||||
public CallExpressionNode(ExpressionNode callee, List<ExpressionNode> arguments) {
|
|
||||||
this.callee = callee;
|
|
||||||
this.arguments = arguments;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ExpressionNode getCallee() { return callee; }
|
|
||||||
public List<ExpressionNode> getArguments() { return arguments; }
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/ast/DeclarationNode.java
|
|
||||||
package org.jcnc.snow.compiler.parser.ast;
|
package org.jcnc.snow.compiler.parser.ast;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/ast/ExpressionNode.java
|
|
||||||
package org.jcnc.snow.compiler.parser.ast;
|
package org.jcnc.snow.compiler.parser.ast;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,15 +1,7 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/ast/ExpressionStatementNode.java
|
|
||||||
package org.jcnc.snow.compiler.parser.ast;
|
package org.jcnc.snow.compiler.parser.ast;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 单独的表达式语句节点(如函数调用、赋值等)。
|
* 单独的表达式语句节点(如函数调用、赋值等)。
|
||||||
*/
|
*/
|
||||||
public class ExpressionStatementNode implements StatementNode {
|
public record ExpressionStatementNode(ExpressionNode expression) implements StatementNode {
|
||||||
private final ExpressionNode expression;
|
|
||||||
|
|
||||||
public ExpressionStatementNode(ExpressionNode expression) {
|
|
||||||
this.expression = expression;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ExpressionNode getExpression() { return expression; }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/ast/FunctionNode.java
|
|
||||||
package org.jcnc.snow.compiler.parser.ast;
|
package org.jcnc.snow.compiler.parser.ast;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -6,22 +5,6 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* 函数定义节点:包含函数名、参数列表、返回类型和函数体语句列表。
|
* 函数定义节点:包含函数名、参数列表、返回类型和函数体语句列表。
|
||||||
*/
|
*/
|
||||||
public class FunctionNode implements Node {
|
public record FunctionNode(String name, List<ParameterNode> parameters, String returnType,
|
||||||
private final String name;
|
List<StatementNode> body) implements Node {
|
||||||
private final List<ParameterNode> parameters;
|
|
||||||
private final String returnType;
|
|
||||||
private final List<StatementNode> body;
|
|
||||||
|
|
||||||
public FunctionNode(String name, List<ParameterNode> parameters,
|
|
||||||
String returnType, List<StatementNode> body) {
|
|
||||||
this.name = name;
|
|
||||||
this.parameters = parameters;
|
|
||||||
this.returnType = returnType;
|
|
||||||
this.body = body;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() { return name; }
|
|
||||||
public List<ParameterNode> getParameters() { return parameters; }
|
|
||||||
public String getReturnType() { return returnType; }
|
|
||||||
public List<StatementNode> getBody() { return body; }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,17 +1,9 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/ast/IdentifierNode.java
|
|
||||||
package org.jcnc.snow.compiler.parser.ast;
|
package org.jcnc.snow.compiler.parser.ast;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 标识符表达式节点。
|
* 标识符表达式节点。
|
||||||
*/
|
*/
|
||||||
public class IdentifierNode implements ExpressionNode {
|
public record IdentifierNode(String name) implements ExpressionNode {
|
||||||
private final String name;
|
|
||||||
|
|
||||||
public IdentifierNode(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() { return name; }
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return name;
|
return name;
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/ast/IfNode.java
|
|
||||||
package org.jcnc.snow.compiler.parser.ast;
|
package org.jcnc.snow.compiler.parser.ast;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -6,15 +5,5 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* if 语句节点:包含条件表达式和 then 分支语句列表。
|
* if 语句节点:包含条件表达式和 then 分支语句列表。
|
||||||
*/
|
*/
|
||||||
public class IfNode implements StatementNode {
|
public record IfNode(ExpressionNode condition, List<StatementNode> thenBranch) implements StatementNode {
|
||||||
private final ExpressionNode condition;
|
|
||||||
private final List<StatementNode> thenBranch;
|
|
||||||
|
|
||||||
public IfNode(ExpressionNode condition, List<StatementNode> thenBranch) {
|
|
||||||
this.condition = condition;
|
|
||||||
this.thenBranch = thenBranch;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ExpressionNode getCondition() { return condition; }
|
|
||||||
public List<StatementNode> getThenBranch() { return thenBranch; }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,15 +1,7 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/ast/ImportNode.java
|
|
||||||
package org.jcnc.snow.compiler.parser.ast;
|
package org.jcnc.snow.compiler.parser.ast;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* import 语句节点:仅保存被导入模块名。
|
* import 语句节点:仅保存被导入模块名。
|
||||||
*/
|
*/
|
||||||
public class ImportNode implements Node {
|
public record ImportNode(String moduleName) implements Node {
|
||||||
private final String moduleName;
|
|
||||||
|
|
||||||
public ImportNode(String moduleName) {
|
|
||||||
this.moduleName = moduleName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getModuleName() { return moduleName; }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/ast/LoopNode.java
|
|
||||||
package org.jcnc.snow.compiler.parser.ast;
|
package org.jcnc.snow.compiler.parser.ast;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -6,24 +5,6 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* loop 语句节点:包含初始化语句、条件表达式、更新语句和循环体。
|
* loop 语句节点:包含初始化语句、条件表达式、更新语句和循环体。
|
||||||
*/
|
*/
|
||||||
public class LoopNode implements StatementNode {
|
public record LoopNode(StatementNode initializer, ExpressionNode condition, StatementNode update,
|
||||||
private final StatementNode initializer;
|
List<StatementNode> body) implements StatementNode {
|
||||||
private final ExpressionNode condition;
|
|
||||||
private final StatementNode update;
|
|
||||||
private final List<StatementNode> body;
|
|
||||||
|
|
||||||
public LoopNode(StatementNode initializer,
|
|
||||||
ExpressionNode condition,
|
|
||||||
StatementNode update,
|
|
||||||
List<StatementNode> body) {
|
|
||||||
this.initializer = initializer;
|
|
||||||
this.condition = condition;
|
|
||||||
this.update = update;
|
|
||||||
this.body = body;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StatementNode getInitializer() { return initializer; }
|
|
||||||
public ExpressionNode getCondition() { return condition; }
|
|
||||||
public StatementNode getUpdate() { return update; }
|
|
||||||
public List<StatementNode> getBody() { return body; }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,20 +1,9 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/ast/MemberExpressionNode.java
|
|
||||||
package org.jcnc.snow.compiler.parser.ast;
|
package org.jcnc.snow.compiler.parser.ast;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 成员访问表达式节点,如 obj.prop。
|
* 成员访问表达式节点,如 obj.prop。
|
||||||
*/
|
*/
|
||||||
public class MemberExpressionNode implements ExpressionNode {
|
public record MemberExpressionNode(ExpressionNode object, String member) implements ExpressionNode {
|
||||||
private final ExpressionNode object;
|
|
||||||
private final String member;
|
|
||||||
|
|
||||||
public MemberExpressionNode(ExpressionNode object, String member) {
|
|
||||||
this.object = object;
|
|
||||||
this.member = member;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ExpressionNode getObject() { return object; }
|
|
||||||
public String getMember() { return member; }
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return object + "." + member;
|
return object + "." + member;
|
||||||
|
|||||||
@ -37,11 +37,11 @@ public class ModuleNode implements Node {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
StringJoiner importJoiner = new StringJoiner(", ");
|
StringJoiner importJoiner = new StringJoiner(", ");
|
||||||
for (ImportNode imp : imports) {
|
for (ImportNode imp : imports) {
|
||||||
importJoiner.add(imp.getModuleName());
|
importJoiner.add(imp.moduleName());
|
||||||
}
|
}
|
||||||
StringJoiner funcJoiner = new StringJoiner(", ");
|
StringJoiner funcJoiner = new StringJoiner(", ");
|
||||||
for (FunctionNode fn : functions) {
|
for (FunctionNode fn : functions) {
|
||||||
funcJoiner.add(fn.getName());
|
funcJoiner.add(fn.name());
|
||||||
}
|
}
|
||||||
return "Module(name=" + name
|
return "Module(name=" + name
|
||||||
+ ", imports=[" + importJoiner.toString() + "]"
|
+ ", imports=[" + importJoiner.toString() + "]"
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/ast/Node.java
|
|
||||||
package org.jcnc.snow.compiler.parser.ast;
|
package org.jcnc.snow.compiler.parser.ast;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,17 +1,9 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/ast/NumberLiteralNode.java
|
|
||||||
package org.jcnc.snow.compiler.parser.ast;
|
package org.jcnc.snow.compiler.parser.ast;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数字字面量表达式节点。
|
* 数字字面量表达式节点。
|
||||||
*/
|
*/
|
||||||
public class NumberLiteralNode implements ExpressionNode {
|
public record NumberLiteralNode(String value) implements ExpressionNode {
|
||||||
private final String value;
|
|
||||||
|
|
||||||
public NumberLiteralNode(String value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getValue() { return value; }
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
|||||||
@ -1,25 +1,9 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/ast/ParameterNode.java
|
|
||||||
package org.jcnc.snow.compiler.parser.ast;
|
package org.jcnc.snow.compiler.parser.ast;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 函数参数节点:包含参数名和类型。
|
* 函数参数节点:包含参数名和类型。
|
||||||
*/
|
*/
|
||||||
public class ParameterNode implements Node {
|
public record ParameterNode(String name, String type) implements Node {
|
||||||
private final String name;
|
|
||||||
private final String type;
|
|
||||||
|
|
||||||
public ParameterNode(String name, String type) {
|
|
||||||
this.name = name;
|
|
||||||
this.type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回参数的字符串表示,例如 "num1:int",便于列表打印。
|
* 返回参数的字符串表示,例如 "num1:int",便于列表打印。
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/ast/ReturnNode.java
|
|
||||||
package org.jcnc.snow.compiler.parser.ast;
|
package org.jcnc.snow.compiler.parser.ast;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/ast/StatementNode.java
|
|
||||||
package org.jcnc.snow.compiler.parser.ast;
|
package org.jcnc.snow.compiler.parser.ast;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,20 +1,11 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/ast/StringLiteralNode.java
|
|
||||||
package org.jcnc.snow.compiler.parser.ast;
|
package org.jcnc.snow.compiler.parser.ast;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 字符串字面量表达式节点,如 "hello"。
|
* 字符串字面量表达式节点,如 "hello"。
|
||||||
|
*
|
||||||
|
* @param value 不包含引号的字符串内容
|
||||||
*/
|
*/
|
||||||
public class StringLiteralNode implements ExpressionNode {
|
public record StringLiteralNode(String value) implements ExpressionNode {
|
||||||
/** 不包含引号的字符串内容 */
|
|
||||||
private final String value;
|
|
||||||
|
|
||||||
public StringLiteralNode(String value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 打印时在两端加上引号,
|
* 打印时在两端加上引号,
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/context/ParseException.java
|
|
||||||
package org.jcnc.snow.compiler.parser.context;
|
package org.jcnc.snow.compiler.parser.context;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/context/ParserContext.java
|
|
||||||
package org.jcnc.snow.compiler.parser.context;
|
package org.jcnc.snow.compiler.parser.context;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.lexer.token.Token;
|
import org.jcnc.snow.compiler.lexer.token.Token;
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/context/TokenStream.java
|
|
||||||
package org.jcnc.snow.compiler.parser.context;
|
package org.jcnc.snow.compiler.parser.context;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.lexer.token.Token;
|
import org.jcnc.snow.compiler.lexer.token.Token;
|
||||||
@ -73,6 +72,6 @@ public class TokenStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAtEnd() {
|
public boolean isAtEnd() {
|
||||||
return peek().getType() == TokenType.EOF;
|
return peek().getType() != TokenType.EOF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/expression/BinaryOperatorParselet.java
|
|
||||||
package org.jcnc.snow.compiler.parser.expression;
|
package org.jcnc.snow.compiler.parser.expression;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.parser.ast.BinaryExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.BinaryExpressionNode;
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/expression/CallParselet.java
|
|
||||||
package org.jcnc.snow.compiler.parser.expression;
|
package org.jcnc.snow.compiler.parser.expression;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.parser.ast.CallExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.CallExpressionNode;
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/expression/ExpressionParser.java
|
|
||||||
package org.jcnc.snow.compiler.parser.expression;
|
package org.jcnc.snow.compiler.parser.expression;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.parser.ast.ExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.ExpressionNode;
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/expression/GroupingParselet.java
|
|
||||||
package org.jcnc.snow.compiler.parser.expression;
|
package org.jcnc.snow.compiler.parser.expression;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.lexer.token.Token;
|
import org.jcnc.snow.compiler.lexer.token.Token;
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/expression/IdentifierParselet.java
|
|
||||||
package org.jcnc.snow.compiler.parser.expression;
|
package org.jcnc.snow.compiler.parser.expression;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.lexer.token.Token;
|
import org.jcnc.snow.compiler.lexer.token.Token;
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/expression/MemberParselet.java
|
|
||||||
package org.jcnc.snow.compiler.parser.expression;
|
package org.jcnc.snow.compiler.parser.expression;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.lexer.token.TokenType;
|
import org.jcnc.snow.compiler.lexer.token.TokenType;
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/expression/NumberLiteralParselet.java
|
|
||||||
package org.jcnc.snow.compiler.parser.expression;
|
package org.jcnc.snow.compiler.parser.expression;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.lexer.token.Token;
|
import org.jcnc.snow.compiler.lexer.token.Token;
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/expression/PrattExpressionParser.java
|
|
||||||
package org.jcnc.snow.compiler.parser.expression;
|
package org.jcnc.snow.compiler.parser.expression;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.lexer.token.Token;
|
import org.jcnc.snow.compiler.lexer.token.Token;
|
||||||
@ -51,7 +50,7 @@ public class PrattExpressionParser implements ExpressionParser {
|
|||||||
}
|
}
|
||||||
ExpressionNode left = prefix.parse(ctx, token);
|
ExpressionNode left = prefix.parse(ctx, token);
|
||||||
|
|
||||||
while (!ctx.getTokens().isAtEnd() &&
|
while (ctx.getTokens().isAtEnd() &&
|
||||||
prec.ordinal() < nextPrecedence(ctx)) {
|
prec.ordinal() < nextPrecedence(ctx)) {
|
||||||
String lex = ctx.getTokens().peek().getLexeme();
|
String lex = ctx.getTokens().peek().getLexeme();
|
||||||
InfixParselet infix = infixes.get(lex);
|
InfixParselet infix = infixes.get(lex);
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
package org.jcnc.snow.compiler.parser.expression;// File: src/main/java/org/jcnc/snow/compiler/parser/expression/Precedence.java
|
package org.jcnc.snow.compiler.parser.expression;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 运算符优先级枚举,用于 Pratt 算法比较。
|
* 运算符优先级枚举,用于 Pratt 算法比较。
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/expression/PrefixParselet.java
|
|
||||||
package org.jcnc.snow.compiler.parser.expression;
|
package org.jcnc.snow.compiler.parser.expression;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.parser.ast.ExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.ExpressionNode;
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/expression/StringLiteralParselet.java
|
|
||||||
package org.jcnc.snow.compiler.parser.expression;
|
package org.jcnc.snow.compiler.parser.expression;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.lexer.token.Token;
|
import org.jcnc.snow.compiler.lexer.token.Token;
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/factory/StatementParserFactory.java
|
|
||||||
package org.jcnc.snow.compiler.parser.factory;
|
package org.jcnc.snow.compiler.parser.factory;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.parser.statement.*;
|
import org.jcnc.snow.compiler.parser.statement.*;
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/factory/TopLevelParserFactory.java
|
|
||||||
package org.jcnc.snow.compiler.parser.factory;
|
package org.jcnc.snow.compiler.parser.factory;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.parser.TopLevelParser;
|
import org.jcnc.snow.compiler.parser.TopLevelParser;
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/function/FunctionParser.java
|
|
||||||
package org.jcnc.snow.compiler.parser.function;
|
package org.jcnc.snow.compiler.parser.function;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.lexer.token.TokenType;
|
import org.jcnc.snow.compiler.lexer.token.TokenType;
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/module/ImportParser.java
|
|
||||||
package org.jcnc.snow.compiler.parser.module;
|
package org.jcnc.snow.compiler.parser.module;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.lexer.token.TokenType;
|
import org.jcnc.snow.compiler.lexer.token.TokenType;
|
||||||
@ -21,17 +20,13 @@ public class ImportParser {
|
|||||||
ctx.getTokens().expect(":");
|
ctx.getTokens().expect(":");
|
||||||
List<ImportNode> imports = new ArrayList<>();
|
List<ImportNode> imports = new ArrayList<>();
|
||||||
// 读取第一个模块名
|
// 读取第一个模块名
|
||||||
String name = ctx.getTokens()
|
|
||||||
.expectType(TokenType.IDENTIFIER)
|
|
||||||
.getLexeme();
|
|
||||||
imports.add(new ImportNode(name));
|
|
||||||
// 继续读取逗号分隔的模块名
|
// 继续读取逗号分隔的模块名
|
||||||
while (ctx.getTokens().match(",")) {
|
do {
|
||||||
String mod = ctx.getTokens()
|
String mod = ctx.getTokens()
|
||||||
.expectType(TokenType.IDENTIFIER)
|
.expectType(TokenType.IDENTIFIER)
|
||||||
.getLexeme();
|
.getLexeme();
|
||||||
imports.add(new ImportNode(mod));
|
imports.add(new ImportNode(mod));
|
||||||
}
|
} while (ctx.getTokens().match(","));
|
||||||
// 消费行尾
|
// 消费行尾
|
||||||
ctx.getTokens().expectType(TokenType.NEWLINE);
|
ctx.getTokens().expectType(TokenType.NEWLINE);
|
||||||
return imports;
|
return imports;
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/module/ModuleParser.java
|
|
||||||
package org.jcnc.snow.compiler.parser.module;
|
package org.jcnc.snow.compiler.parser.module;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.lexer.token.TokenType;
|
import org.jcnc.snow.compiler.lexer.token.TokenType;
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/statement/DeclarationStatementParser.java
|
|
||||||
package org.jcnc.snow.compiler.parser.statement;
|
package org.jcnc.snow.compiler.parser.statement;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.lexer.token.TokenType;
|
import org.jcnc.snow.compiler.lexer.token.TokenType;
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/statement/ExpressionStatementParser.java
|
|
||||||
package org.jcnc.snow.compiler.parser.statement;
|
package org.jcnc.snow.compiler.parser.statement;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.lexer.token.TokenType;
|
import org.jcnc.snow.compiler.lexer.token.TokenType;
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/statement/IfStatementParser.java
|
|
||||||
package org.jcnc.snow.compiler.parser.statement;
|
package org.jcnc.snow.compiler.parser.statement;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.lexer.token.TokenType;
|
import org.jcnc.snow.compiler.lexer.token.TokenType;
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/statement/LoopStatementParser.java
|
|
||||||
package org.jcnc.snow.compiler.parser.statement;
|
package org.jcnc.snow.compiler.parser.statement;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.lexer.token.TokenType;
|
import org.jcnc.snow.compiler.lexer.token.TokenType;
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/statement/ReturnStatementParser.java
|
|
||||||
package org.jcnc.snow.compiler.parser.statement;
|
package org.jcnc.snow.compiler.parser.statement;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.lexer.token.TokenType;
|
import org.jcnc.snow.compiler.lexer.token.TokenType;
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// File: src/main/java/org/jcnc/snow/compiler/parser/statement/StatementParser.java
|
|
||||||
package org.jcnc.snow.compiler.parser.statement;
|
package org.jcnc.snow.compiler.parser.statement;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.parser.context.ParserContext;
|
import org.jcnc.snow.compiler.parser.context.ParserContext;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user