ANTLR4: Как установить другой контекст в правиле для одного и того же тега? - PullRequest
1 голос
/ 24 мая 2019

У меня есть такая грамматика:

grammar SearchQuery;

queryDeclaration                        : predicateGroupItem predicateGroupItemWithBooleanOperator* ;
predicateGroupItemWithBooleanOperator   : groupOperator predicateGroupItem ;
predicateGroupItem                      : LEFT_BRACKET variable variableDelimiter
                                                expression expressionWithBoolean* RIGHT_BRACKET ;

variable                                : VARIABLE_STRING ;
variableDelimiter                       : VAR_DELIMITER  ;

expressionWithBoolean                   : boolOperator expression ;

expression                              : value ;

value                                   : polygonType;

boolOperator                            : or
                                        ;

or                                      : OR ;

groupOperator                           : AND ;

polygonType                             : POLYGON LEFT_BRACKET pointList (POLYGON_DELIMITER pointList)* RIGHT_BRACKET ;
longType                                : LONG ;
doubleType                              : DOUBLE ;

pointList                               : point
                                        | LEFT_BRACKET point ( POLYGON_DELIMITER point)* RIGHT_BRACKET
                                        ;

point                                   : latitude longitude ;

latitude                                : longType
                                        | doubleType
                                        ;

longitude                               : longType
                                        | doubleType
                                        ;

POLYGON                                 : [pP] [oO] [lL] [yY] [gG] [oO] [nN] ;


LONG                                    : DIGIT+ ;

DOUBLE                                  : DIGIT+ '.' DIGIT*
                                        | '.' DIGIT+
                                        ;

AND                                     : [aA] [nN] [dD] ;
OR                                      : COMMA
                                        | [oO] [rR]
                                        ;

VARIABLE_STRING                         : [a-zA-Z0-9.]+ ;
COMMA                                   : ',' ;
POLYGON_DELIMITER                       : ';' ;
VAR_DELIMITER                           : ':' ;

RIGHT_BRACKET                           : ')' ;
LEFT_BRACKET                            : '(' ;

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

fragment DIGIT                          : [0-9] ;

Проблема в том, что я не могу использовать тег COMMA с разными правилами одновременно в polygonType , pointList rules (Iнужно использовать COMMA за исключением POLYGON_DELIMITER) и boolOperator rule (используется COMMA). Другими словами, если мы изменим POLYGON_DELIMITER на COMMA и протестируем такую ​​грамматику со значением, подобным этому

(polygons: polygon(20 30.4, 23.4 23),
           polygon(20 30.4, 23.4 23),
           polygon(20 30.4, 23.4 23))

мы получим ошибку

mismatch input: ',' expecting {',', ')'}

Я буду рад, если кто-нибудь поможет мне разобраться в проблеме.

PS Если мы не изменим текущую грамматику, то значение для тестирования это

(poligons: polygon(20 30.4; 23.4 23),
           polygon(20 30.4; 23.4 23),
           polygon(20 30.4; 23.4 23))

1 Ответ

1 голос
/ 24 мая 2019

Из-за этих правил:

OR                                      : COMMA
                                        | [oO] [rR]
                                        ;

COMMA                                   : ',' ;

лексер никогда не будет выдавать токен COMMA, поскольку он уже соответствует токену OR. И поскольку OR определено до COMMA, оно получает приоритет.

Вот что на самом деле означает сообщение об ошибке mismatch input: ',' expecting {',', ')'}. Другими словами: mismatch input: OR expecting {COMMA, RIGHT_BRACKET}

Что вы должны сделать (если оператор ИЛИ может иметь значение «или» или «,»), это позволить правилу синтаксического анализа or соответствовать COMMA:

or                                      : OR
                                        | COMMA
                                        ;

OR                                      : [oO] [rR]
                                        ;

COMMA                                   : ',' ;
...