[英]Why my antlr lexer java class is “code too large”?
这是 Antlr 中的词法分析器(对不起,文件很长):
lexer grammar SqlServerDialectLexer;
/* T-SQL words */
AND: 'AND';
BIGINT: 'BIGINT';
BIT: 'BIT';
CASE: 'CASE';
CHAR: 'CHAR';
COUNT: 'COUNT';
CREATE: 'CREATE';
CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP';
DATETIME: 'DATETIME';
DECLARE: 'DECLARE';
ELSE: 'ELSE';
END: 'END';
FLOAT: 'FLOAT';
FROM: 'FROM';
GO: 'GO';
IMAGE: 'IMAGE';
INNER: 'INNER';
INSERT: 'INSERT';
INT: 'INT';
INTO: 'INTO';
IS: 'IS';
JOIN: 'JOIN';
NOT: 'NOT';
NULL: 'NULL';
NUMERIC: 'NUMERIC';
NVARCHAR: 'NVARCHAR';
ON: 'ON';
OR: 'OR';
SELECT: 'SELECT';
SET: 'SET';
SMALLINT: 'SMALLINT';
TABLE: 'TABLE';
THEN: 'THEN';
TINYINT: 'TINYINT';
UPDATE: 'UPDATE';
USE: 'USE';
VALUES: 'VALUES';
VARCHAR: 'VARCHAR';
WHEN: 'WHEN';
WHERE: 'WHERE';
QUOTE: '\'' { textMode = !textMode; };
QUOTED: {textMode}?=> ~('\'')*;
EQUALS: '=';
NOT_EQUALS: '!=';
SEMICOLON: ';';
COMMA: ',';
OPEN: '(';
CLOSE: ')';
VARIABLE: '@' NAME;
NAME:
( LETTER | '#' | '_' ) ( LETTER | NUMBER | '#' | '_' | '.' )*
;
NUMBER: DIGIT+;
fragment LETTER: 'a'..'z' | 'A'..'Z';
fragment DIGIT: '0'..'9';
SPACE
:
( ' ' | '\t' | '\n' | '\r' )+
{ skip(); }
;
JDK 1.6 说code too large
,无法编译。 为什么以及如何解决问题?
实际上我不会说这是一个大语法,并且它不能产生合理大小的代码肯定是有原因的。
我认为问题与此规则直接相关:
QUOTED: {textMode}?=> ~('\'')*;
是否有任何特殊原因让您希望将 QUOTED 部分作为一个单独的标记,而不是将其与引号结合在一起,因为 Bart 也将其放在他的语法中? 这也会使textMode
变量过时。
删除 QUOTE 并将 QUOTED 替换为
QUOTED: '\'' (~'\'')* '\'';
即使不拆分语法,也很可能会解决问题。
把你的语法分成几个复合语法。 小心你把什么放在哪里。 例如,您不想将NAME
规则放在您的顶级语法中,并将关键字放入导入的语法中: NAME
会“覆盖”匹配的关键字。
这有效:
lexer grammar A;
SELECT: 'SELECT';
SET: 'SET';
SMALLINT: 'SMALLINT';
TABLE: 'TABLE';
THEN: 'THEN';
TINYINT: 'TINYINT';
UPDATE: 'UPDATE';
USE: 'USE';
VALUES: 'VALUES';
VARCHAR: 'VARCHAR';
WHEN: 'WHEN';
WHERE: 'WHERE';
QUOTED: '\'' ('\'\'' | ~'\'')* '\'';
EQUALS: '=';
NOT_EQUALS: '!=';
SEMICOLON: ';';
COMMA: ',';
OPEN: '(';
CLOSE: ')';
VARIABLE: '@' NAME;
NAME:
( LETTER | '#' | '_' ) ( LETTER | NUMBER | '#' | '_' | '.' )*
;
NUMBER: DIGIT+;
fragment LETTER: 'a'..'z' | 'A'..'Z';
fragment DIGIT: '0'..'9';
SPACE
:
( ' ' | '\t' | '\n' | '\r' )+
{ skip(); }
;
lexer grammar SqlServerDialectLexer;
import A;
AND: 'AND';
BIGINT: 'BIGINT';
BIT: 'BIT';
CASE: 'CASE';
CHAR: 'CHAR';
COUNT: 'COUNT';
CREATE: 'CREATE';
CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP';
DATETIME: 'DATETIME';
DECLARE: 'DECLARE';
ELSE: 'ELSE';
END: 'END';
FLOAT: 'FLOAT';
FROM: 'FROM';
GO: 'GO';
IMAGE: 'IMAGE';
INNER: 'INNER';
INSERT: 'INSERT';
INT: 'INT';
INTO: 'INTO';
IS: 'IS';
JOIN: 'JOIN';
NOT: 'NOT';
NULL: 'NULL';
NUMERIC: 'NUMERIC';
NVARCHAR: 'NVARCHAR';
ON: 'ON';
OR: 'OR';
它编译得很好:
java -cp antlr-3.3.jar org.antlr.Tool SqlServerDialectLexer.g
javac -cp antlr-3.3.jar *.java
如您所见,在“top-lexer”上调用org.antlr.Tool
就足够了:ANTLR 自动为导入的语法生成类。 如果您要导入更多语法,请执行以下操作:
import A, B, C;
Gunther 是正确的:改变QUOTED
规则就足够了。 不过我会留下我的答案,因为当您要添加更多关键字或添加很多解析器规则(SQL 语法不可避免)时,您很可能会再次偶然发现“代码太大”错误。 在这种情况下,您可以使用我提出的解决方案。
如果您要接受答案,请接受 Gunther 的。
唔。 我不认为您可以使用导入语句将其进一步分解为单独的文件?
显然有人写了一个后处理器来自动拆分,但我还没有尝试过。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.