解析fortran风格的.op。运营商

时间:2014-04-17 19:10:36

标签: antlr4

我试图为受到Fortran启发的DSL编写ANTLR4语法。我在使用经典" .op。"操作符:

if (1.and.1) then

其中" 1" s应该被解释为整数。我查看了OpenFortranParser的洞察力,但我无法理解它。

最初,我在我的词法分析器中有适当的INTEGER和REAL定义。因此,第一个" 1"以上总是被解析为REAL,无论我尝试过什么。我尝试将事物移动到解析器中,并且使我能够可靠地识别"。和。"以及它周围的数字作为适当的INTEGER或REAL。

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

...等...

我当然希望在这些陈述中识别变量名称:

if (a.and.b)

并拥有适当的ID规则。但是,在下面的小语法中,引号中的任何文字(例如'和','如果',所有单字符数字后缀)都不被接受为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;   

1 个答案:

答案 0 :(得分:1)

要消除DOT的歧义,请在DOT规则之前添加带谓词的词法分析器规则。

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;
}

}

但是,这不是您当前问题的真正根源。整数解析器规则有效地在词法分析器之外定义词法分析器常量,这就是“b”与ID不匹配的原因。

将其更改为

integer : INT ;

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

并且词法分析员会弄明白其余部分。