Информация об изменениях

Сообщение Re[2]: По Antlr подскажите... от 04.12.2015 6:15

Изменено 04.12.2015 7:09 Кондраций

Здравствуйте, maxkar, Вы писали:

M>Здравствуйте, Кондраций, Вы писали:


К>>Вопрос первый: можно ли как-то использовать '=', а не '=='. Можно конечно парсером выдирать всё выражения и разбирать далее руками, но не хочется.

К>>Вопрос второй на понимание (может смешной, но я в грамматиках лох): описанное выше проиходит от того, что ANTLR описывает контекстно-свободные грамматики?

M>Начну со второго вопроса. Описанное выше просиходит из-за того, что ANTLR не разбирает произвольные контекстные грамматики. Он разбирает LR(1) (или LALR, не помню уже) грамматики, которые являются подмножеством контекстно-свободных.


...

Спасибо, тут есть над чем подумать.

M>Обнаружение подобных ситуаций происходит уже на этапе компиляции грамматики. Парсер не сможет определить, как трактовать текущий терминал ('x' в последнем примере) ни по текущему состоянию, ни с использованием следующего символа. И вот эта ситуация называется 'reduce/reduce conflict'. (кстати, ант на reduce/reduce жалуется? Если я не угадал и там shift/reduce, нужно писать другой пример ).

Не, он жалуется на MismatchedTokenException, таких умных слов, как у Вас, он не говорил

M>По неточному фрагменту грамматики полезное решение угадать нельзя. Хорошо бы было посмотреть всю грамматику целиком. Если она не секретная, может выложите куда-нибудь?


Секретного ничего нет, она просто большая и с семантикой. Читать сложно. Я подготовил краткий пример.
Данный пример отрабатывает номально, но если заменить '==' на '=' в правиле лексера WhereOperator и в разбираемом тексте, то будет то, о чём я и говорил. Заходное правило — parse.

  Граматика
grammar Example;

options {
      language = CSharp3;
}


ID  :    ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
    ;

INT :    '0'..'9'+
    ;

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


QUOTE     :    '"';

QuotedString :    QUOTE (~QUOTE)* QUOTE ;

quotedString :    QuotedString; // Выделено правило парсера для того, чтобы можно было вставить свой код (symantyc action)


where : 'where' '(' (whereRec (',' whereRec)*)?  ')';

WhereOperator    :    '==' | '<>' | '>' | '<' | '>=' | '<=';


whereRec :  
    ID  WhereOperator  (  quotedString | INT  )  
    ;


assign    :    ID '=' (quotedString | INT | ID) where? ;

parse    :
    assign+
 ;

  Пример

var1 = 11
var2 = "string" where( var1 > 3, varN == 4)
var3 = var1
Re[2]: По Antlr подскажите...
Здравствуйте, maxkar, Вы писали:

M>Здравствуйте, Кондраций, Вы писали:


К>>Вопрос первый: можно ли как-то использовать '=', а не '=='. Можно конечно парсером выдирать всё выражения и разбирать далее руками, но не хочется.

К>>Вопрос второй на понимание (может смешной, но я в грамматиках лох): описанное выше проиходит от того, что ANTLR описывает контекстно-свободные грамматики?

M>Начну со второго вопроса. Описанное выше просиходит из-за того, что ANTLR не разбирает произвольные контекстные грамматики. Он разбирает LR(1) (или LALR, не помню уже) грамматики, которые являются подмножеством контекстно-свободных.


...

Спасибо, тут есть над чем подумать.

M>Обнаружение подобных ситуаций происходит уже на этапе компиляции грамматики. Парсер не сможет определить, как трактовать текущий терминал ('x' в последнем примере) ни по текущему состоянию, ни с использованием следующего символа. И вот эта ситуация называется 'reduce/reduce conflict'. (кстати, ант на reduce/reduce жалуется? Если я не угадал и там shift/reduce, нужно писать другой пример ).

Не, он жалуется на MismatchedTokenException, таких умных слов, как у Вас, он не говорил

M>По неточному фрагменту грамматики полезное решение угадать нельзя. Хорошо бы было посмотреть всю грамматику целиком. Если она не секретная, может выложите куда-нибудь?


Секретного ничего нет, она просто большая и с семантикой. Читать сложно. Я подготовил краткий пример.
Данный пример отрабатывает номально, но если заменить '==' на '=' в правиле лексера WhereOperator и в разбираемом тексте, то будет то, о чём я и говорил. Заходное правило — parse.

  Граматика
grammar Example;

options {
      language = CSharp3;
}


ID  :    ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
    ;

INT :    '0'..'9'+
    ;

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


QUOTE     :    '"';

QuotedString :    QUOTE (~QUOTE)* QUOTE ;

quotedString :    QuotedString; // Выделено правило парсера для того, чтобы можно было вставить свой код (symantyc action)


where : 'where' '(' (whereRec (',' whereRec)*)?  ')';

WhereOperator    :    '==' | '<>' | '>' | '<' | '>=' | '<=';


whereRec :  
    ID  WhereOperator  (  quotedString | INT  )  
    ;


assign    :    ID '=' (quotedString | INT | ID) where? ;

parse    :
    assign+
 ;

  Пример

var1 = 11
var2 = "string" where( var1 > 3, varN == 4)
var3 = var1


У меня и было такое хотение, чтобы при выполнении правила парсера where лексер определял, что втретившийся знак '=' — это WhereOperator. Но лексер работает перед парсером...

Обходной путь наверное таков:
WhereOperator    :    '<>' | '>' | '<' | '>=' | '<=';

whereRec :  
    ID  (WhereOperator | '=' ) (  quotedString | INT  )  
    ;

Парсер не ругается. Наверное, так и сделаю.