使用ANTLR4解析SQL CREATE TABLE语句



Lexer文件代码如下:

lexer grammar CreateLexer;
CREATE
   : 'create' | 'CREATE'
   ;
NUMBER_OF_SHARDS:'number_of_shards' | 'NUMBER_OF_SHARDS';

NUMBER_OF_REPLICAS:'number_of_replicas' | 'NUMBER_OF_REPLICAS';

ID
  : ( 'a' .. 'z' | 'A' .. 'Z' | '_' | 'u4e00' .. 'u9fa5' | '-')+
  ;

INT
  : [0-9]+
  ;

NEWLINE
  : 'r'? 'n' -> skip
  ;

WS
  : [trn]+ -> skip
  ;

INDEX
  : 'index' | 'INDEX'
  ;
TABLE:'table';

解析器文件代码也如下:

parser grammar CreateParser;
options
   { tokenVocab = CreateLexer; }
stat
   : create_clause
   ;
create_clause
   : CREATE INDEX index_name shards? replicas?
   ;
index_name
   : (ID)*(INT)*
   ;
shards
   : NUMBER_OF_SHARDS INT
   ;
replicas
   : NUMBER_OF_REPLICAS INT
   ;

这是我的测试代码演示了我如何使用上面的模块:

String sql = "create index A number_of_shards 1 number_of_replicas 1";
CreateLexer createLexer = new CreateLexer(new ANTLRInputStream(sql));
createLexer.removeErrorListeners();
CreateParser parser = new CreateParser(new CommonTokenStream(createLexer));
ParseTree tree = parser.stat();
System.out.println(tree.toStringTree(parser));

当我运行上面的测试代码时,我得到了一个错误:

line 1:7 missing INDEX at 'index'
(stat (create_clause create <missing INDEX> (index_name index A) (shards number_of_shards 1) (replicas number_of_replicas 1)))

之后,我在paser文件的create_clause中用TABLE替换了INDEX,并在测试代码中用TABLE替换了INDEX

测试代码:

String sql = "create table A number_of_shards 1 number_of_replicas 1";

paser文件:

create_clause
   : CREATE TABLE index_name shards? replicas?
   ;

我再次运行它,它仍然得到相同的错误:

line 1:7 missing 'table' at 'table'
(stat (create_clause create <missing 'table'> (index_name table A) (shards number_of_shards 1) (replicas number_of_replicas 1)))

然而,在我删除语法分析器文件中的关键字TABLE后,如下所示:

create_clause
   : CREATE index_name shards? replicas?
   ;

奇怪的事情发生了,我没有错误:

(stat (create_clause create (index_name table A) (shards number_of_shards 1) (replicas number_of_replicas 1)))

有人能告诉我为什么像CREATE TABLE这样的SQL语句不能被解析吗?我错过什么了吗?提前感谢!

Antlr通常首先根据文本匹配长度,然后根据语法中的顺序来匹配lexer规则。因此,您的INDEXTABLE规则永远不会匹配。相反,文本以ID标记呈现。

通过删除对显式INDEX令牌的要求,就消除了错误的原因。

一般来说,总是转储令牌流,这样您就可以看到lexer实际在做什么。

相关内容

  • 没有找到相关文章

最新更新