Это меня бесит, я просто не могу найти решение. У меня есть грамматика для поисковых запросов, и я хотел бы соответствовать любому поисковому запросу в запросе, составленном из печатных букв, за исключением специальных символов "(", ")". Строки, заключенные в кавычки, обрабатываются отдельно и работают.
Вот несколько рабочая грамматика:
/* ANTLR Grammar for Minidb Query Language */
grammar Mdb;
start
: searchclause EOF
;
searchclause
: table expr
;
expr
: fieldsearch
| searchop fieldsearch
| unop expr
| expr relop expr
| lparen expr relop expr rparen
;
lparen
: '('
;
rparen
: ')'
;
unop
: NOT
;
relop
: AND
| OR
;
searchop
: NO
| EVERY
;
fieldsearch
: field EQ searchterm
;
field
: ID
;
table
: ID
;
searchterm
:
| STRING
| ID+
| DIGIT+
| DIGIT+ ID+
;
STRING
: '"' ~('\n'|'"')* ('"' )
;
AND
: 'and'
;
OR
: 'or'
;
NOT
: 'not'
;
NO
: 'no'
;
EVERY
: 'every'
;
EQ
: '='
;
fragment VALID_ID_START
: ('a' .. 'z') | ('A' .. 'Z') | '_'
;
fragment VALID_ID_CHAR
: VALID_ID_START | ('0' .. '9')
;
ID
: VALID_ID_START VALID_ID_CHAR*
;
DIGIT
: ('0' .. '9')
;
/*
NOT_SPECIAL
: ~(' ' | '\t' | '\n' | '\r' | '\'' | '"' | ';' | '.' | '=' | '(' | ')' )
; */
WS
: [ \r\n\t] + -> skip
;
Проблема в том, что searchterm слишком ограничен. Он должен соответствовать любому символу в закомментированном NOT_SPECIAL, то есть, допустимые запросы будут:
Person Name=%
Person Address=^%Street%%%$^&*@^
Но всякий раз, когда я пытаюсь каким-либо образом вставить NOT_SPECIAL в определение searchterm, это не работает. Я пытался вставить это буквально в правило, тоже (комментируя NOT_SPECIAL) и многие другие вещи, но это просто не работает. В большинстве моих попыток грамматика просто жаловалась на посторонний ввод после «=» и говорила, что ожидает EOF. Но я также не могу поместить EOF в NOT_SPECIAL.
Можно ли как-то просто проанализировать каждый текст после "=" в правиле fieldsearch, пока не появится пробел или ")", "("?
N.B. Правило STRING работает нормально, но пользователь не обязан каждый раз использовать кавычки, потому что это инструмент командной строки, и его нужно будет экранировать.
Целевой язык - Go.