带十进制数的ANTLR4语法问题

带十进制数的ANTLR4语法问题,antlr4,Antlr4,我不熟悉ANTLR并使用ANTLR4(4.7.2 Jar文件)。我目前正在研究Oracle解析器。 我对十进制数有意见。我只保留了相关部分。 我的语法文件如下 现在,当我解析下面的语句时,就可以了。“.1”在我的情况下是一个有效数字。 开始一个数字:=.1;结束 我还没有展示语法,但以下是我在Oracle中的有效案例 a NUMBER:= .1; // with Space after operator a NUMBER:=1.1; // without Space after operator

我不熟悉ANTLR并使用ANTLR4(4.7.2 Jar文件)。我目前正在研究Oracle解析器。 我对十进制数有意见。我只保留了相关部分。 我的语法文件如下

现在,当我解析下面的语句时,就可以了。“.1”在我的情况下是一个有效数字。 开始一个数字:=.1;结束

我还没有展示语法,但以下是我在Oracle中的有效案例

a NUMBER:= .1; // with Space after operator
a NUMBER:=1.1; // without Space after operator
a NUMBER:=1; // without Space after operator
a NUMER:= 3; // with Space after operator
现在我需要创建一个表空间,如下所示。 创建表空间tbs_01数据文件+数据/BR/CONTROLFILE/Current.260.750

这里,数字260和750与点一起标记(根据数字文字的定义)。我希望这是两个由点分隔的独立数字(并分配给filenumber和化身号resp,如语法所示)

我该怎么做? 我试过使用_input.LA(-1)!='.}?等等,但对我来说不正常。 我尝试了前面提到的许多其他步骤(大多数解决方案是针对ANTLR3的,而不是针对ANTLR4的)。在LEXER中有没有一种简单的方法可以做到这一点?我不想编写解析器规则来拆分十进制数字

grammar Oracle;

parse
 : ( sql_statements | error )* EOF
 ;

error
 : UNEXPECTED_CHAR 
 { 
    throw new RuntimeException("UNEXPECTED_CHAR=" + $UNEXPECTED_CHAR.text);
 }
 ;

sql_statements 
: 'CREATE' 'TABLESPACE' tablespace_name 'DATAFILE' fully_qualified_file_name ';'
| 'BEGIN' var1 'NUMBER' ':=' num1 ';' 'END' ';'
;

tablespace_name : IDENTIFIER;
fully_qualified_file_name : K_PLUS_SIGN diskgroup_name K_SOLIDUS db_name K_SOLIDUS file_type K_SOLIDUS file_type_tag '.' filenumber '.' incarnation_number;
diskgroup_name : IDENTIFIER;
db_name : IDENTIFIER;
file_type : IDENTIFIER;
file_type_tag : IDENTIFIER;
filenumber : NUMERIC_LITERAL;
incarnation_number : NUMERIC_LITERAL;

var1 : IDENTIFIER;
num1 : NUMERIC_LITERAL;

IDENTIFIER : [a-zA-Z_] ([a-zA-Z] | '$' | '_' | '#' | DIGIT)* ;
K_PLUS_SIGN : '+';
K_SOLIDUS : '/';
NUMERIC_LITERAL
 : DIGIT+ ( '.' DIGIT+ )? ( E ('+'|'-')? DIGIT+ )? ('D' | 'F')?
 | '.' DIGIT+ ( E ('+'|'-')? DIGIT+ )? ('D' | 'F')?
 ;

SPACES : [ \u000B\t\r\n] -> skip;
WS : [ \t\r\n]+ -> skip;
UNEXPECTED_CHAR : . ;

fragment DIGIT : [0-9];
fragment A : [aA];
fragment B : [bB];
fragment C : [cC];
fragment D : [dD];
fragment E : [eE];
fragment F : [fF];
fragment G : [gG];
fragment H : [hH];
fragment I : [iI];
fragment J : [jJ];
fragment K : [kK];
fragment L : [lL];
fragment M : [mM];
fragment N : [nN];
fragment O : [oO];
fragment P : [pP];
fragment Q : [qQ];
fragment R : [rR];
fragment S : [sS];
fragment T : [tT];
fragment U : [uU];
fragment V : [vV];
fragment W : [wW];
fragment X : [xX];
fragment Y : [yY];
fragment Z : [zZ];

您的Dsl具有自然的模糊性:在某些情况下,数字是整数,而在另一些情况下,数字是小数

如果Dsl提供了足够的保护条件,则可用于隔离实例。例如,在给定的Dsl中,十进制数字似乎总是出现在
:=
之间警卫

...
K_ASSIGN : ':=' -> pushMode(Decimals);
K_SEMI : ';' ;
NUMERIC_LITERAL : DIGIT+ ;
...
mode Decimals;
    D_SEMI : ';' -> type(K_SEMI), popMode ;
    NUMERIC: 
        DIGIT+ ( '.' DIGIT+ )? ( E ('+'|'-')? DIGIT+ )? 'D' 
        | 'F')? 
        | '.' DIGIT+ ( E ('+'|'-')? DIGIT+ )? ('D' | 'F')?
     -> type(NUMERIC_LITERAL);

感谢@GRosenberg的快速回复。当我尝试插入此插件时,我面临许多问题。1) lexer命令push不存在或当前目标-->不支持-->将“push”修改为“pushMode”2)lexer语法中只允许使用词法模式-->这真的很累人。必须将我的整个语法拆分为解析器和lexer,并且必须将lexer规则添加到lexer文件中。3) lexer rule NUMERIC中的命令必须是单个最外层alt-->的最后一个元素,是否将整个“NUMERIC”内容(从[0-9]开始到“F”)放入?在括号内)。谢谢你提供的信息。嗨@GRosenberg,我也试图以类似的方式实现负数,但很困难。它要么分裂成一个负数,要么不分裂成负数。例如,a:=a+1应该是,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,a:=a-1应该是,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,a:?Oracle确实支持很多有空格和无空格的数字加减方法。简短回答:是的,有一种相对简单的方法来处理这个问题。较长的回答:“StackOverflow”方法是在单独的问题帖子中提出新的/不同的问题。当然,我们会发布一个新问题。因为我觉得它和我更新的语法有关,所以我把它放在这里。