Antlr4禁用空格以匹配字符前缀

时间:2014-05-28 01:43:44

标签: parsing antlr antlr4

我是编写语法的新手,我读过大约一半的Antlr4:权威指南,我想我会对我正在研究的语法有所了解。我被困在一些听起来很基本但事实证明比我想象的更难的事情上。

我正在尝试解析smali(android反汇编)类声明。它看起来像这样:

.class public Lcom/packageName/example;

smali中的规则是所有完全限定的类都以L为前缀,然后包部分用/分隔,然后类名是{{{}之前的最后一部分。 1}}。

所以我有一个普通;在我的词法分析器部分,但是我在解析WS : [ \t\r\n]+ -> skip ;时如何禁用它。我想要将其停用,以便在没有fullyQualifiedClass的情况下返回第一个classPackageComponent,但如果忘记L,则会显示L。包名称相同,包名称与其Error: 'L' expected'分隔符之间不能有空格。我知道问题是我的Parser甚至没有看到WS角色,因为Lexer只是抛弃它们。我该如何处理这个问题?渠道是答案吗?我还没有完成这一章,但其他SO帖子表明它可能是。

我的语法代码不正确:

/

1 个答案:

答案 0 :(得分:1)

首先要解决几个问题:

  1. Lexer和Parser在很大程度上是分开的:Parser无法修改 Lexer的操作
  2. Parser应该处理令牌,而不是角色或角色 字符串 - Lexer无法看到Parser中发生了什么,所以 你失去了Lexer进行某些优化的能力
  3. Lexer不会在令牌之间插入空格标记 识别
  4. 词法

    Class: '.class' ;
    Semi: ';' ; 
    Modifier: 'public' | 'private';
    Slash: '/' ;
    ClassPrefix : 'L' { isPrefix() }? ;
    Identifier :   Letter (Letter|JavaIDDigit)* ;
    WS : [ \t\r\n]+ -> skip ;
    ...
    

    Lexing .class public Lcom/packageName/example;(如果isPrefix()总是返回false)将生成令牌流:

    Class, Modifier, Identifier, Slash, Identifier, Slash, Identifier, Semi
    

    这就是Parser所看到的。因此,解析器规则变为

    classDeclaration : Class Modifier fullyQualifiedClass ;
    fullyQualifiedClass: ClassPrefix? (Identifier Slash)* Identifier Semi ;
    

    ClassPrefix的问题在于没有可用于将其分离的自然分隔符。但是,有很多方法可以解决这个问题。

    也许最直接的方法是Lexer检查,每次Lexer看到一个' L'它是否处于类似名称的开头。那就是谓词' {isPrefix()}?打算这样做。查看herehere以获取谓词实现的示例。

    另一种方法是完全从Lexer中删除ClassPrefix规则,并在解析器规则操作中检测前缀,或者更好的是,在解析树的后续步骤中检测:

    fullyQualifiedClass: (Identifier Slash)* Identifier Semi ;
    

    标识符的第一个实例是一个包含令牌匹配的基础文本的令牌。可以调用生成的解析器类'YourParser'.FullyQualifiedClassContext.Identifier()的每个实例,以按从左到右的顺序返回标识符标记的List。检查最左边的前缀并相应处理。