gpt4 book ai didi

antlr - ANTLR 中的浮点文字和范围参数

转载 作者:行者123 更新时间:2023-12-02 07:47:22 27 4
gpt4 key购买 nike

我正在开发 D 语言的解析器,当我尝试添加“切片”运算符规则时遇到了麻烦。你可以找到它的ANTLR语法here 。基本上问题是,如果词法分析器遇到这样的字符串:“1..2”,它就会完全丢失,并且最终成为单个浮点值,因此像“a[10..”这样的字符串的后缀表达式规则。 11]"最终成为带有 ExpLiteralReal 参数的 ExpArrIndex 对象。有人可以解释一下数字文字到底有什么问题吗? (据我所知,它在这些 token 周围的某个地方失败了)

最佳答案

当您在 float 内遇到 ".." 时,您可以通过发出两个标记(IntRange 标记)来实现此目的规则。您需要重写词法分析器中的两个方法才能完成此操作。

包含 Dee 语法一小部分的演示:

grammar Dee;

@lexer::members {

java.util.Queue<Token> tokens = new java.util.LinkedList<Token>();

public void offer(int ttype, String ttext) {
this.emit(new CommonToken(ttype, ttext));
}

@Override
public void emit(Token t) {
state.token = t;
tokens.offer(t);
}

@Override
public Token nextToken() {
super.nextToken();
return tokens.isEmpty() ? Token.EOF_TOKEN : tokens.poll();
}
}
parse
: (t=. {System.out.printf("\%-15s '\%s'\n", tokenNames[$t.type], $t.text);})* EOF
;

Range
: '..'
;

IntegerLiteral
: Integer IntSuffix?
;

FloatLiteral
: Float ImaginarySuffix?
;

// skipping
Space
: ' ' {skip();}
;

// fragments
fragment Float
: d=DecimalDigits ( options {greedy = true; } : FloatTypeSuffix
| '..' {offer(IntegerLiteral, $d.text); offer(Range, "..");}
| '.' DecimalDigits DecimalExponent?
)
| '.' DecimalDigits DecimalExponent?
;

fragment DecimalExponent : 'e' | 'E' | 'e+' | 'E+' | 'e-' | 'E-' DecimalDigits;
fragment DecimalDigits : ('0'..'9'|'_')+ ;
fragment FloatTypeSuffix : 'f' | 'F' | 'L';
fragment ImaginarySuffix : 'i';
fragment IntSuffix : 'L'|'u'|'U'|'Lu'|'LU'|'uL'|'UL' ;
fragment Integer : Decimal| Binary| Octal| Hexadecimal ;
fragment Decimal : '0' | '1'..'9' (DecimalDigit | '_')* ;
fragment Binary : ('0b' | '0B') ('0' | '1' | '_')+ ;
fragment Octal : '0' (OctalDigit | '_')+ ;
fragment Hexadecimal : ('0x' | '0X') (HexDigit | '_')+;
fragment DecimalDigit : '0'..'9' ;
fragment OctalDigit : '0'..'7' ;
fragment HexDigit : ('0'..'9'|'a'..'f'|'A'..'F') ;

使用类测试语法:

import org.antlr.runtime.*;

public class Main {
public static void main(String[] args) throws Exception {
DeeLexer lexer = new DeeLexer(new ANTLRStringStream("1..2 .. 33.33 ..21.0"));
DeeParser parser = new DeeParser(new CommonTokenStream(lexer));
parser.parse();
}
}

当您运行 Main 时,会产生以下输出:

IntegerLiteral  '1'
Range '..'
IntegerLiteral '2'
Range '..'
FloatLiteral '33.33'
Range '..'
FloatLiteral '21.0'

编辑

是的,正如您在评论中指出的那样,词法分析器规则只能发出 1 个单个标记。 但是,正如您自己已经尝试过的那样,语义谓词确实可以用于强制词法分析器在字符流中向前查看,以确保实际上存在 ".."在尝试匹配 FloatLiteral 之前在 IntegerLiteral 标记之后。

以下语法将产生与第一个演示相同的标记。

grammar Dee;

parse
: (t=. {System.out.printf("\%-15s '\%s'\n", tokenNames[$t.type], $t.text);})* EOF
;

Range
: '..'
;

Number
: (IntegerLiteral Range)=> IntegerLiteral {$type=IntegerLiteral;}
| (FloatLiteral)=> FloatLiteral {$type=FloatLiteral;}
| IntegerLiteral {$type=IntegerLiteral;}
;

// skipping
Space
: ' ' {skip();}
;

// fragments
fragment DecimalExponent : 'e' | 'E' | 'e+' | 'E+' | 'e-' | 'E-' DecimalDigits;
fragment DecimalDigits : ('0'..'9'|'_')+ ;
fragment FloatLiteral : Float ImaginarySuffix?;
fragment IntegerLiteral : Integer IntSuffix?;
fragment FloatTypeSuffix : 'f' | 'F' | 'L';
fragment ImaginarySuffix : 'i';
fragment IntSuffix : 'L'|'u'|'U'|'Lu'|'LU'|'uL'|'UL' ;
fragment Integer : Decimal| Binary| Octal| Hexadecimal ;
fragment Decimal : '0' | '1'..'9' (DecimalDigit | '_')* ;
fragment Binary : ('0b' | '0B') ('0' | '1' | '_')+ ;
fragment Octal : '0' (OctalDigit | '_')+ ;
fragment Hexadecimal : ('0x' | '0X') (HexDigit | '_')+;
fragment DecimalDigit : '0'..'9' ;
fragment OctalDigit : '0'..'7' ;
fragment HexDigit : ('0'..'9'|'a'..'f'|'A'..'F') ;
fragment Float
: d=DecimalDigits ( options {greedy = true; } : FloatTypeSuffix
| '.' DecimalDigits DecimalExponent?
)
| '.' DecimalDigits DecimalExponent?
;

关于antlr - ANTLR 中的浮点文字和范围参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8639783/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com