我想解析如下查询表达式:
人名=%John%
(人名= John%,地址=%Ontario%)
人员Fullname_3 =“ John C. Smith”
但是我对Antlr4完全陌生,甚至无法弄清楚如何解析单个TABLE FIELD = QUERY子句。当我在Go中将以下语法作为目标运行时,我得到了
line 1:7 mismatched input 'Name' expecting {'not', '(', FIELDNAME}
用于简单的查询
人名= John
为什么语法无法通过解析fieldsearch-> field EQ searchterm-> FIELDNAME来解析FIELDNAME?
我想我在这里误解了有关Antlr Grammars的工作原理的一些基本知识,但是怎么办?
/* 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
;
答案 0 :(得分:1)
尝试使用grun Mdb tokens -tokens
查看为该输入生成的令牌。它会告诉您,输入由两个表名组成,一个等号,然后是另一个表名。为了匹配您的语法,它必须是一个表名,一个字段名,一个等号和一个 string 。
第一个问题是TABLENAME
和FIELDNAME
具有完全相同的定义。如果两个词法分析器规则会在当前输入上产生相同长度的匹配项,则ANTLR会首选语法中的第一个。因此它将永远不会产生FIELDNAME
令牌。要解决此问题,只需用单个ID
规则替换这两个规则。如果需要,可以保留解析器规则tableName : ID ;
和fieldName : ID ;
。
另一个问题更为直接:John
根本不符合您的字符串规则,因为它不在引号中。如果确实希望允许John
作为有效搜索词,则可能希望将其定义为searchterm : STRING | ID ;
,而不是仅允许STRING
。