java - antlr4数组实现: getting values of elements

标签 java antlr4

我正在尝试在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/

相关文章:

java - 当需要随机数时如何设置限制(1 或 2)?

java - 将鼠标单击时的图像添加到 JPanel

java - Spring Config 将字符串映射到对象

java - 通过 ANTLR 4 仅使用 java 文件的注释 (/** ..... */) 部分并跳过其余部分

java - Antlr4 - 表示检查任意数量的标记的句法谓词

antlr4:如何知道在给定上下文的情况下选择了哪个选项

java - 有条件地在 jooq 准备好的语句中包含子句

powershell - 是否有 PowerShell 5 或更高版本的语言规范文档

java - ANTLR4 无法正确管理左递归

java - 无法在网页上定位元素