我试图为受到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;
答案 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')? ;
并且词法分析员会弄明白其余部分。