Как я могу захватить точки с помощью ANTLR4? [Дубликат]

[[1] * 4] * 3

или даже:

[[1, 1, 1, 1]] * 3

Создает список, который ссылается на внутренний [1,1,1,1] 3 раза - не три копии внутреннего списка, поэтому в любое время, когда вы изменяете список (в любом позиция), вы увидите изменение три раза.

Это то же самое, что и в этом примере:

>>> inner = [1,1,1,1]
>>> outer = [inner]*3
>>> outer
[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]
>>> inner[0] = 5
>>> outer
[[5, 1, 1, 1], [5, 1, 1, 1], [5, 1, 1, 1]]

, где это, вероятно, немного менее удивительно.

4
задан tripatheea 13 May 2014 в 20:41
поделиться

1 ответ

Строка "keyup" помечена как токен NAME: это проблема.

Вы должны понимать, что лексер работает независимо от анализатора. Если синтаксический анализатор пытается сопоставить токен KEYPRESS, лексер не «слушает» его, а просто строит токен, следуя правилам:

  1. соответствует правилу, которое потребляет большинство символов
  2. , если существует больше правил, совпадающих с одинаковым количеством символов, выберите тот, который определен первым

Принимая во внимание эти правила и порядок ваших правил :

NAME : [A-Za-z_][A-Za-z_0-9]* ;

INT : [0-9]+ ;

KEY : [a-z] | [0-9] | 'shift' | 'ctrl' | 'alt' | 'meta' | 'space' | 'left' | 'right' | 'up' | 'down' | 'minus' | 'equals' | 'backspace' | 'openbracket' | 'closebracket' | 'backslash' | 'semicolon' | 'quote' | 'enter' | 'comma' | 'period' | 'slash' ;

KEYPRESS : 'keyup' | 'keydown' ;

маркер NAME будет создан до большей части альтернатив KEY, и все альтернативы KEYPRESS будут созданы.

И поскольку INT соответствует одной или нескольким цифрам и определен до KEY, который также имеет альтернативу с одной цифрой, ясно, что лексер никогда не будет генерировать KEY или KEYPRESS токен.

Если вы переместите правило NAME и INT ниже правил KEY и KEYPRESS, то большинство токенов будут построены так, как вы ожидаете, это мое предположение.

EDIT

Возможное решение будет выглядеть так:

KEY : [a-z] | 'shift' | 'ctrl' | 'alt' | 'meta' | 'space' | 'left' | 'right' | 'up' | 'down' | 'minus' | 'equals' | 'backspace' | 'openbracket' | 'closebracket' | 'backslash' | 'semicolon' | 'quote' | 'enter' | 'comma' | 'period' | 'slash' ;

KEYPRESS : 'keyup' | 'keydown' ;

NAME : [A-Za-z_][A-Za-z_0-9]* ;

SINGLE_DIGIT : [0-9] ;

INT : [0-9]+ ;

Т.е. Я удалил альтернативу [0-9] из KEY и ввел правило SINGLE_DIGIT (которое помещено перед правилом INT!).

Теперь создайте дополнительный парсер rules:

integer : INT | SINGLE_DIGIT ;

key : KEY | SINGLE_DIGIT ;

и изменить все вхождения INT внутри правил синтаксического анализа на integer (не вызывать ваше правило int: это зарезервированное слово) и изменить все KEY к key.

И вы также можете сделать что-то похожее на NAME и альтернативу [a-z] в KEY (т. е. один символ нижнего регистра теперь никогда не будет обозначаться как NAME ], всегда как KEY).

7
ответ дан Bart Kiers 20 August 2018 в 22:30
поделиться
  • 1
    Большое спасибо! Это сработало! Однако теперь, когда у меня есть KEY перед NAME и INT, такие вещи, как leftFlipper name=a x=16 y=2 orientation=0, выдает ошибку, потому что теперь имя соответствует KEY, пока оно не соответствует NAME. – tripatheea 13 May 2014 в 20:40
  • 2
    @AashishTripathee, действительно, одна цифра теперь not будет соответствовать как INT, а как KEY. – Bart Kiers 13 May 2014 в 20:41
  • 3
    @AashishTripathee проверить мой EDIT – Bart Kiers 13 May 2014 в 20:46
  • 4
    Это сработало! Большое спасибо! – tripatheea 14 May 2014 в 05:18
  • 5
    Ты спас мой бекон. Благодаря! – yoshi 10 February 2016 в 09:50