2015-11-13 3 views
1

В моей грамматике у меня есть эти правила LeXeR:ANTLR: правило Лексер ловля, что должно быть обработано правилом синтаксического анализа

DECIMAL_NUMBER: DIGITS? DOT_SYMBOL DIGITS; 

// Identifiers might start with a digit, even though it is discouraged. 
IDENTIFIER: LETTER_WHEN_UNQUOTED+; 

fragment LETTER_WHEN_UNQUOTED: 
    '0'..'9' 
    | 'A'..'Z' // Only upper case, as we use a case insensitive parser (insensitive only for ASCII). 
    | '$' 
    | '_' 
    | '\u0080'..'\uffff' 
; 

WHITESPACE: (' ' | '\t' | '\f' | '\r'| '\n') { $channel = HIDDEN; }; 

и это парсер правило:

qualified_identifier: IDENTIFIER '.' IDENTIFIER; 

Это прекрасно работает, за исключением один особый случай, как это:

... a.0b 

проблема здесь состоит в том, что +0,0 захвачен правилом десятичное_число, но я бы н чтобы игнорировать его, если есть цифры без цифр, которые следуют за любыми цифрами. Как это может быть сделано?

Я думал о проверяющем предикате, но это полностью нарушило бы разбор, если правило DECIMAL_NUMBER не соответствует ему. Еще одна мысль о том, что я должен добавить проверку действий для любого символа, следуя тому, что было согласовано до сих пор, а затем вручную генерирует токены, что кажется очень уродливым.

Можно ли пометить позицию после точки и вернуться к ней во входном потоке, когда мой код действия определяет, что это не десятичное число?

+0

Здесь некрасиво решение с ручным лексем поколения: https://github.com/ibre5041/plsql-parser/blob/master/parsers/PLSQLLexer .g # L114. Он анализирует ввод '1..5' как NUMBER INTERVAL NUMBER. Другим вариантом было бы вызвать «set_type (IDENTIFIER)» внутри действия правила DECIMAL_NUMBER. Если за цифрами следуют некоторые символы. – ibre5041

+0

Но это будет делать, например. '.0a' идентификатор, что неверно. Правильный способ заключается в создании последовательности токенов DOT IDENTIFIER. –

+0

да, вы правы – ibre5041

ответ

0

Правила десятичное_число должен быть продлен только матч, если у нас есть чистое десятичное число:

DECIMAL_NUMBER: 
    DIGITS DOT_SYMBOL DIGITS 
    | DOT_SYMBOL {if (!isAllDigits(ctx)) {FAILEDFLAG = ANTLR3_TRUE; return; }} DIGITS 
; 

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

Функция для проверки ввода заключается в следующем:

ANTLR3_BOOLEAN isAllDigits(pMySQLLexer ctx) 
    { 
    int i = 1; 
    while (1) 
    { 
     int input = LA(i++); 
     if (input == EOF || input == ' ' || input == '\t' || input == '\n' || input == '\r' || input == '\f') 
     return ANTLR3_TRUE; 

     // Need to check if any of the valid identifier chars comes here (which would make the entire string to an identifier). 
     // For the used values look up the IDENTIFIER lexer rule. 
     if ((input >= 'A' && input <= 'Z') || input == '$' || input == '_' || (input >= 0x80 && input <= 0xffff)) 
     return ANTLR3_FALSE; 

     // Everything else but digits is considered valid input for a new token. 
     if (input < '0' && input > '9') 
     return ANTLR3_TRUE; 
    } 
    } 
0

Если память обслуживается, лексер жадный (т.е. ищет самый длинный токен, который будет соответствовать в любой заданной точке входного потока. В галстуке порядок имеет значение. Я уверен, что ваше единственное решение - сделать (в моей грамматике, вот как я обрабатывал идентификаторы)

Посмотрите, что вы указали, поскольку IDENTIFIER может начинаться с номера (и требуется только для этого). чтобы быть одним или несколькими символами), то я считаю, что у вас есть двусмысленность лексера (это 1,2 точечный IDENTIFIER или DECIMAL_NUMBER). Вероятно, вам придется сломать, чтобы токен IDENTIFIER указывал две альтернативы (которые начинаются с одной или нескольких цифр , но требуется иметь по крайней мере несимметричный символ, а другой, который позволяет одному или нескольким некачать это характер. (возможно, вы справились с этим в реальной грамматике, и это просто упрощено для вопроса).