Antlr4 解析fortran style.op。操作员

Antlr4 解析fortran style.op。操作员,antlr4,Antlr4,我正试图为一个受fortran启发的DSL编写一个ANTLR4语法。我在“ole classic”方面遇到困难。op.“运算符: if (1.and.1) then 其中,两个“1”都应解释为整数。我查看了OpenFortranParser以获得洞察力,但我无法理解它 最初,我在lexer中对INTEGER和REAL有合适的定义。因此,不管我怎么做,上面的第一个“1”总是解析为实数。我尝试将东西移动到解析器中,并使它能够可靠地识别“.”和“.”以及它周围的数字作为适当的整数或实数 if (1.

我正试图为一个受fortran启发的DSL编写一个ANTLR4语法。我在“ole classic”方面遇到困难。op.“运算符:

if (1.and.1) then
其中,两个“1”都应解释为整数。我查看了OpenFortranParser以获得洞察力,但我无法理解它

最初,我在lexer中对INTEGER和REAL有合适的定义。因此,不管我怎么做,上面的第一个“1”总是解析为实数。我尝试将东西移动到解析器中,并使它能够可靠地识别“.”和“.”以及它周围的数字作为适当的整数或实数

if (1.and.1)   # INT/INT
if (1..and..1) # REAL/REAL
……等等

我当然想在这样的语句中识别变量名:

if (a.and.b)
在下面的小语法中,引号中的任何文字(例如,'和','如果',所有单字符数字后缀)都不被接受为ID,我得到一个错误;接受任何其他符合ID的字符串:

if (a.and.b)  # errs, as 'b' is valid INTEGER suffix
if (a.and.c)  # OK
对这种行为的任何见解,或关于如何解析.op的更好建议。fortran中的运算符将不胜感激--谢谢

grammar Foo;

start  : ('if' expr | ID)+ ;

DOT : '.' ;

DIGITS: [0-9]+;

ID : [a-zA-Z0-9][a-zA-Z0-9_]* ;

andOp : DOT 'and' DOT ;

SIGN : [+-];

expr     
    : ID
    | expr andOp expr
    | numeric
    | '(' expr ')'
    ;

integer : DIGITS ('q'|'Q'|'l'|'L'|'h'|'H'|'b'|'B'|'i'|'I')? ;

real    
    : DIGITS DOT DIGITS? (('e'|'E') SIGN? DIGITS)? ('d' | 'D')?
    |        DOT DIGITS  (('e'|'E') SIGN? DIGITS)? ('d' | 'D')?
    ;

numeric : integer | real;

EOLN  : '\r'? '\n' -> skip;

WS    :  [ \t]+ -> skip;   

为了消除点的歧义,在点规则之前添加一个带谓词的词法规则

DIT : DOT { isDIT() }? ;
DOT : '.' ;
更改“andOp”

andOp : DIT 'and' DIT ;
然后添加一个谓词方法

@lexer::members {

public boolean isDIT() {
    int offset = _tokenStartCharIndex;
    String r = _input.getText(Interval.of(offset-4, offset));
    String s = _input.getText(Interval.of(offset, offset+4));
    if (".and.".equals(s) || ".and.".equals(r)) {
        return true;
    }
    return false;
}

}
但是,这并不是你当前问题的根源。整数解析器规则在lexer之外有效地定义lexer常量,这就是为什么“b”与ID不匹配的原因

换成

integer : INT ;

INT:  DIGITS ('q'|'Q'|'l'|'L'|'h'|'H'|'b'|'B'|'i'|'I')? ;
lexer将计算出其余的部分。

使用ANTLR4,
('q'|'q'|'l'|'l'|'h'|'h'|'b'|'i'|'i')
可以写成
[qllhbbii]