Как я могу обнаружить пробелы в моем дереве разбора в Antlr4?

Когда правило соответствует в antlr4, и вы получаете текст этого правила, пробел обычно удаляется лексером с помощью

WS: [ \n\t\r]+ -> skip;

Можно ли спросить у посетителя дерева разбора «Пропустило ли это правило какой-либо пробел?»

Например.

WS: [ \n\t\r]+ -> skip;
ALPHA: [a-z];
NUMERIC: [0-9];

myrule: (ALPHA | NUMERIC)+;

Затем в госте (я использую C ++):

antlrcpp::Any MyVisitor::visitMyrule(dlParser::MyruleContext *ctx) {
if (ctx->didSkipSomeWhitespace()) {
/* There was whitespace */
} else {
/* There was no whitespace */
}
return false;
}

Так:

f56fhj => no whitespace
o9f g66ff o => whitespace

Я попытался получить индексы начала / остановки токена, чтобы я мог сравнить длину текста с количеством введенных в него символов, но стоп-токен не всегда доступен, и если это так, то значения не выровняйте с ожидаемыми индексами, и, кажется, не просто получить доступ к исходным символам ввода, которые сформировали токен.

1

Решение

В этом случае вы не должны skip эти космические жетоны. Таким образом, парсеры не знают о них. Вместо этого вы должны поместить эти пробелы в другой канал (HIDDEN, например). Таким образом, парсер не использует эти HIDDEN токены, но токены присутствуют в потоке токенов и доступны в вашем коде.

Небольшая демонстрация в Java (у меня не работает C ++):

grammar IntList;

list
: '[' ( list_item ( ',' list_item )* )? ']' EOF
;

list_item
: INT
;

INT
: '0'
| [1-9] [0-9]*
;

SPACES
: [ \t\f\r\n] -> channel(HIDDEN)
;

Запуск класса:

import org.antlr.v4.runtime.*;

public class Main {

public static void main(String[] args) {

String source = "[1,    2,3,\t4,5]";

IntListLexer lexer = new IntListLexer(CharStreams.fromString(source));
CommonTokenStream tokens = new CommonTokenStream(lexer);
IntListParser parser = new IntListParser(tokens);

new SpaceInspectionVisitor(tokens).visit(parser.list());
}
}

class SpaceInspectionVisitor extends IntListBaseVisitor<Object> {

private final CommonTokenStream tokens;

SpaceInspectionVisitor(CommonTokenStream tokens) {
this.tokens = tokens;
}

@Override
public Object visitList_item(IntListParser.List_itemContext ctx) {
Token previous = tokens.get(ctx.start.getTokenIndex() - 1);
System.out.printf("token: '%s', previous == SPACES: %s\n", ctx.getText(), previous.getType() == IntListLexer.SPACES);
return null;
}
}

выведет на вашу консоль следующее:

token: '1', previous == SPACES: false
token: '2', previous == SPACES: true
token: '3', previous == SPACES: false
token: '4', previous == SPACES: true
token: '5', previous == SPACES: false
3

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector