这个ANTLR语法有什么问题?

时间:2018-11-10 18:24:09

标签: antlr antlr4 context-free-grammar

我想解析如下查询表达式:

  

人名=%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
;

1 个答案:

答案 0 :(得分:1)

尝试使用grun Mdb tokens -tokens查看为该输入生成的令牌。它会告诉您,输入由两个表名组成,一个等号,然后是另一个表名。为了匹配您的语法,它必须是一个表名,一个字段名,一个等号和一个 string

第一个问题是TABLENAMEFIELDNAME具有完全相同的定义。如果两个词法分析器规则会在当前输入上产生相同长度的匹配项,则ANTLR会首选语法中的第一个。因此它将永远不会产生FIELDNAME令牌。要解决此问题,只需用单个ID规则替换这两个规则。如果需要,可以保留解析器规则tableName : ID ;fieldName : ID ;

另一个问题更为直接:John根本不符合您的字符串规则,因为它不在引号中。如果确实希望允许John作为有效搜索词,则可能希望将其定义为searchterm : STRING | ID ;,而不是仅允许STRING