我正在尝试在antlr4中实现数组,但我不知道如何在初始化数组时获取数组的多个元素,如下所示:
int array[] = {1, 2};
我正在考虑将它们放入像这样的 HashMap 中,键是索引:
public Map<Integer, Value> array_memory = new HashMap<Integer, Value>();
以下是我遵循的语法:
grammar GaleugParserNew;
/*
* PARSER RULES
*/
declare_var
: INTEGER ID '[' (INT)? ']' (ASSIGN '{' array_init '}')? SCOL
;
array_init
: INT ',' array_init
| INT
;
/*
* LEXER RULES
*/
SCOL : ';';
ASSIGN : '=';
INTEGER : 'int';
INT : [0-9]+;
我有一个变量可以计算declare_var访问array_init索引的次数。但我不知道如何访问具有多个元素的 array_init。
这是我的declare_var访客:
@Override
public Value visitDeclareArray(GaleugParserNewParser.DeclareArrayContext ctx){
String id = ctx.ID().getText(); //gets array name
String size = ctx.INT().getText(); //get string version of array size
int x = Integer.parseInt(size); //convert size(String) to int
Value elem = this.visit(ctx.array_init());
return Value.VOID;
}
这是我的 array_init 访问者:
@Override
public Value visitArray_init(GaleugParserNewParser.Array_initContext ctx){
index += 1;
return new Value(Double.valueOf(ctx.getText()));
}
如果您对如何访问 array_init 引用变量数量有任何建议,我想听听。谢谢你!
最佳答案
为什么?I was thinking of placing them in a HashMap like this, the key being the index:
public Map<Integer, Value> array_memory = new HashMap<Integer, Value>();
List<Value>
也可以,对吧?无需自己跟踪索引。
通过递归调用 array_init
规则,您的思考变得更加复杂:
array_init
: INT ',' array_init
| INT
;
我会这样做:
array_init
: INT ( ',' INT )*
;
然后你可以做这样的事情:
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.TerminalNode;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
String source = "int array[] = {1, 2};";
GaleugParserNewLexer lexer = new GaleugParserNewLexer(CharStreams.fromString(source));
GaleugParserNewParser parser = new GaleugParserNewParser(new CommonTokenStream(lexer));
Value value = new EvalVisitor().visit(parser.declare_var());
System.out.println(value);
}
}
class Value {
final Object value;
public Value(Object value) {
this.value = value;
}
@Override
public String toString() {
return String.valueOf(this.value);
}
}
class EvalVisitor extends GaleugParserNewBaseVisitor<Value> {
@Override
public Value visitDeclare_var(GaleugParserNewParser.Declare_varContext ctx) {
List<Value> numbers = new ArrayList<>();
if (ctx.array_init() != null) {
for (TerminalNode tokenNode : ctx.array_init().INT()) {
numbers.add(new Value(Integer.valueOf(tokenNode.getText())));
}
}
return new Value(numbers);
}
}
如果您运行此 Main
类,以下内容将打印到您的控制台:
[1, 2]
编辑
But what if I'm not specifically looking for INT, rather I would like to look for any tokens inside a grammar containing all of the data types in my language? what should i use instead of TerminalNode?
就像 1-2-3 一样简单,定义语法如下:
array_init
: expr ( ',' expr )*
;
expr
: '(' expr ')' #nestedExpr
| lhs=expr '+' rhs=expr #addExpr
| INT #intExpr
| ID #idExpr
;
然后做这样的事情:
import org.antlr.v4.runtime.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Main {
public static void main(String[] args) {
String source = "int array[] = { 123456789, (1 + 2), Q };";
GaleugParserNewLexer lexer = new GaleugParserNewLexer(CharStreams.fromString(source));
GaleugParserNewParser parser = new GaleugParserNewParser(new CommonTokenStream(lexer));
Map<String, Value> memory = new HashMap<String, Value>(){{
put("Q", new Value(42));
}};
Value value = new EvalVisitor(memory).visit(parser.declare_var());
System.out.println(value);
}
}
class Value {
final Object value;
public Value(Object value) {
this.value = value;
}
int asInt() {
return (Integer) value;
}
@Override
public String toString() {
return String.valueOf(this.value);
}
}
class EvalVisitor extends GaleugParserNewBaseVisitor<Value> {
final Map<String, Value> memory;
EvalVisitor(Map<String, Value> memory) {
this.memory = memory;
}
@Override
public Value visitDeclare_var(GaleugParserNewParser.Declare_varContext ctx) {
List<Value> numbers = new ArrayList<>();
if (ctx.array_init() != null) {
for (GaleugParserNewParser.ExprContext expr : ctx.array_init().expr()) {
numbers.add(super.visit(expr));
}
}
return new Value(numbers);
}
@Override
public Value visitIntExpr(GaleugParserNewParser.IntExprContext ctx) {
return new Value(Integer.valueOf(ctx.getText()));
}
@Override
public Value visitAddExpr(GaleugParserNewParser.AddExprContext ctx) {
return new Value(super.visit(ctx.lhs).asInt() + super.visit(ctx.rhs).asInt());
}
@Override
public Value visitNestedExpr(GaleugParserNewParser.NestedExprContext ctx) {
return super.visit(ctx.expr());
}
@Override
public Value visitIdExpr(GaleugParserNewParser.IdExprContext ctx) {
return this.memory.get(ctx.getText());
}
}
将打印:
[123456789, 3, 42]
关于java - antlr4数组实现: getting values of elements,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49586618/