Что не так с этой грамматикой ANTLR?

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

Имя человека =% John%

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

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
;

person Eric '3ToedSloth'    schedule 10.11.2018    source источник


Ответы (1)


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

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

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

person sepp2k    schedule 10.11.2018
comment
Отличный ответ, теперь я понимаю проблему. Большое спасибо! - person Eric '3ToedSloth'; 11.11.2018