Что не так с этой грамматикой ANTLR? - PullRequest
0 голосов
/ 10 ноября 2018

Я хочу разобрать выражения запроса, которые выглядят так:

Личное имя =% Джон%

(Имя человека = Джон% и Адрес =% Онтарио%)

Person Fullname_3 = "Джон С. Смит"

Но я совершенно новичок в Antlr4 и даже не могу понять, как разобрать одно предложение TABLE FIELD = QUERY. Когда я запускаю приведенную ниже грамматику в Go как цель, я получаю

line 1:7 mismatched input 'Name' expecting {'not', '(', FIELDNAME} 

для простого запроса, подобного

Личное имя = Джон

Почему грамматика не может проанализировать FIELDNAME с помощью синтаксического анализа fieldsearch-> field EQ searchterm-> FIELDNAME?

Полагаю, я неправильно понимаю кое-что очень фундаментальное о том, как работают грамматики Antlr, но что?

/* ANTLR Grammar for Minidb Query Language */

grammar Mdb;

start : searchclause EOF ;

searchclause
    : table expr
    ;

expr
    : fieldsearch
    | unop fieldsearch
    | LPAREN expr relop expr RPAREN
    ;

unop
    : NOT
    ;

relop
    : AND
    | OR
    ;

fieldsearch
    : field EQ searchterm
    ;

field
    : FIELDNAME
    ;

table
    : TABLENAME
    ;

searchterm
    : STRING
    ;

AND
    : 'and'
    ;

OR
    : 'or'
    ;

NOT
    : 'not'
    ;
EQ
    : '='
    ;

LPAREN
    : '('
    ;

RPAREN
    : ')'
    ;

fragment VALID_ID_START
    : ('a' .. 'z') | ('A' .. 'Z') | '_'
    ;

fragment VALID_ID_CHAR
    : VALID_ID_START | ('0' .. '9')
    ;

TABLENAME
    : VALID_ID_START VALID_ID_CHAR*
    ;

FIELDNAME
    : VALID_ID_START VALID_ID_CHAR*
    ;

STRING: '"' ~('\n'|'"')* ('"' | { panic("syntax-error - unterminated string literal") } ) ;

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

1 Ответ

0 голосов
/ 10 ноября 2018

Попробуйте посмотреть токены, созданные для этого входа, используя grun Mdb tokens -tokens. Он скажет вам, что входные данные состоят из двух имен таблиц, знака равенства и другого имени таблицы. Чтобы соответствовать вашей грамматике, это должно быть имя таблицы, имя поля , знак равенства и строка .

Первая проблема заключается в том, что TABLENAME и FIELDNAME имеют одно и то же определение. В тех случаях, когда два правила лексера приводят к совпадению одинаковой длины на текущем входе, ANTLR предпочитает то, которое стоит первым в грамматике. Так что он никогда не выдаст токен FIELDNAME. Чтобы это исправить, просто замените оба этих правила одним правилом ID. При желании вы можете ввести правила синтаксического анализа tableName : ID ; и fieldName : ID ;, если хотите сохранить имена.

Другая проблема более проста: John просто не соответствует вашим правилам для строки, поскольку она не в кавычках. Если вы хотите разрешить John в качестве допустимого поискового термина, вы можете определить его как searchterm : STRING | ID ; вместо того, чтобы разрешать только STRING s.

...