Как получить тип, не используя слишком много if? - PullRequest
1 голос
/ 09 ноября 2019

Вот мой файл g4

grammar sql;

singleStatement
    : CREATE TIMESERIES dataType
    ;


CREATE: 'CREATE';

TIMESERIES: 'TIMESERIES';

dataType
    : INT32 | INT64 | FLOAT | DOUBLE | BOOLEAN | TEXT
    ;

INT32: 'INT32';

INT64: 'INT64';

FLOAT: 'FLOAT';

DOUBLE: 'DOUBLE';

BOOLEAN: 'BOOLEAN';

TEXT: 'TEXT';

WS
    : [ \r\n\t]+ -> channel(HIDDEN)
    ;

Это слушатель. Я написал это случайно, Пожалуйста, игнорируйте имя класса и другие тривиальные вещи.

package com.boris.sql;

import com.boris.sql.sqlParser.SingleStatementContext;

public class Hello extends sqlBaseListener {

  @Override
  public void enterSingleStatement(SingleStatementContext ctx) {
    super.enterSingleStatement(ctx);
    if (ctx.dataType().BOOLEAN() != null) {
      System.out.println(ctx.dataType().BOOLEAN().getText());
    }

    if (ctx.dataType().FLOAT() != null) {
      System.out.println(ctx.dataType().FLOAT().getText());
    }

    if(ctx.dataType().DOUBLE() != null) {
      System.out.println(ctx.dataType().DOUBLE().getText());
    }

    if(ctx.dataType().INT32() != null) {
      System.out.println(ctx.dataType().INT32().getText());
    }

    if(ctx.dataType().INT64() != null) {
      System.out.println(ctx.dataType().INT64().getText());
    }

    if(ctx.dataType().TEXT() != null) {
      System.out.println(ctx.dataType().TEXT().getText());
    }

  }
}

Программа-драйвер для запуска простого примера,

package com.boris.sql;

import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeWalker;

public class Driver {

  public static void main(String[] args) {
    String query = "CREATE TIMESERIES INT32";
    sqlLexer lexer = new sqlLexer(new ANTLRInputStream(query));
    CommonTokenStream tokns = new CommonTokenStream(lexer);
    sqlParser parser = new sqlParser(tokns);
    ParseTree tree = parser.singleStatement();
    ParseTreeWalker walker = new ParseTreeWalker();
    walker.walk(new Hello(), tree);
  }
}

Да, как вы можете видеть, яполучить правильный результат "INT32". Я знаю методы «ввода», используемые для входа в узлы и выполнения каких-либо действий при обходе дерева. Но я стараюсь не использовать слишком много if. У вас есть другие способы получить dataType?


Класс sqlBaseListener генерируется anltr4, вы должны знать anltr4, чтобы понять его.

Ответы [ 3 ]

2 голосов
/ 09 ноября 2019

Вы звоните getText() независимо от того, какой у вас тип, поэтому вам не нужно проверять тип. Вы можете просто позвонить всегда звонить getText. Поскольку dataType полностью состоит из одного токена, вы можете просто позвонить ctx.dataType().getText() и получить тот же результат, что и в текущем коде.

Если вы хотите по-разному относиться к различным альтернативам, не используя if, вы могли бы назвать альтернативы и затем определить различные enter методы для каждого типа:

dataType
    : INT32 #TypeInt32
    | INT64 #TypeInt64
    | FloatType #Float
    ...
    ;

И затем в слушателе:

@Override
public void enterTypeInt32(TypeInt32Context ctx) {
    System.out.println("It's a 32-bit integer!");
}

@Override
public void enterTypeInt64(TypeInt64Context ctx) {
    System.out.println("It's a 64-bit integer!");
}

@Override
public void enterTypeFloat(TypeFloatContext ctx) {
    System.out.println("It's a single-precision float!");
}
1 голос
/ 10 ноября 2019

Вот еще одна альтернатива. Измените свое правило, чтобы назначить соответствующий токен переменной-члену контекста:

dataType
    : type = INT32
    | type = INT64
    | type = FLOAT
    | type = DOUBLE
    | type = BOOLEAN
    | type = TEXT
;

Затем используйте этот член в операторе switch для другой обработки:

  @Override
  public void enterDataType(DataTypeContext ctx) {
    switch (ctx.type.getType()) {
      case INT32:
        System.out.println("It's a 32-bit integer!");
        break;
      case INT64:
        System.out.println("It's a 64-bit integer!");
        break;
      ...
    }
  }

Это, вероятно, самое простое решениеи легко улучшать позже, если необходимо.

0 голосов
/ 09 ноября 2019

"ctx.dataType (). BOOLEAN ()", "ctx.dataType (). FLOAT ()" ... возвращает другой тип класса, вы должны создать родительский класс A, использовать "ctx.dataType.A() .getTxt () ", полиморфизм. Тогда другой тип экземпляра класса присваивается родительскому классу A, избегайте использования слишком многих if if !!

...