【问题标题】:Get original text of an Antlr rule获取 Antlr 规则的原始文本
【发布时间】:2011-09-16 11:14:50
【问题描述】:

我是 ANTLR 初学者,想计算符号的 SHA1-Hash。

我的简化示例语法:

grammar Example;

method @after{calculateSha1($text); }: 'call' ID;

ID: 'A'..'Z'+;
WS: (' '|'\n'|'\r')+ {skip(); }
COMMENT: '/*' (options {greedy=false;}: .)* '*/' {$channel=HIDDEN}

随着词法分析器删除所有空格,不同的字符串 callABCcall /* DEF */ ABC 不幸地得到相同的 SHA1-Hash 值。

是否可以在开始和结束标记之间获取规则的“原始”文本以及所有跳过的空格和其他通道的文本?

(我想到的一种可能性是在WS- 和COMMENT-lexer 规则中加入所有字符,但是还有更多规则,所以这不是很实用。)

我使用标准的 ANTLRInputStream 来输入 Lexer,但我不知道如何接收原始文本。

【问题讨论】:

    标签: java antlr antlr3


    【解决方案1】:

    而不是skip()-ping WS 令牌,也将其放在HIDDEN 频道上:

    grammar Example;
    
    @parser::members {
      void calculateSha1(String text) {
        try {
          java.security.MessageDigest md = java.security.MessageDigest.getInstance("SHA-1");
          byte[] sha1 = md.digest(text.getBytes());
          System.out.println(text + "\n" + java.util.Arrays.toString(sha1) + "\n");
        } catch(Exception e) {
          e.printStackTrace();
        }
      }
    }
    
    parse 
      :  method+ EOF
      ;
    
    method
    @after{calculateSha1($text);}
      :  'call' ID
      ;
    
    ID      : 'A'..'Z'+;
    WS      : (' ' | '\t' | '\n' | '\r')+ {$channel=HIDDEN;};
    COMMENT : '/*' .* '*/' {$channel=HIDDEN;};
    

    上面的语法可以用:

    import org.antlr.runtime.*;
    
    public class Main {
      public static void main(String[] args) throws Exception {
        String source = "call ABC call /* DEF */ ABC";
        ExampleLexer lexer = new ExampleLexer(new ANTLRStringStream(source));
        ExampleParser parser = new ExampleParser(new CommonTokenStream(lexer));
        parser.parse();
      }
    }
    

    这会将以下内容打印到控制台:

    呼叫 ABC
    [48, -45, 113, 5, -52, -128, -78, 75, -52, -97, -35, 25, -55, 59, -85, 96, -58, 58, -96, 10]
    
    调用 /* DEF */ ABC
    [-57, -2, -115, -104, 77, -37, 4, 93, 116, -123, -47, -4, 33, 42, -68, -95, -43, 91, 94, 77]

    即:相同的解析器规则,但 $text 不同(因此 SHA1 不同)。

    【讨论】:

    • 非常感谢您提供的 ANTLR 知识! :-) 我没有意识到频道外令牌也用于构造 $text。
    • @Sonson,是的,如果你 skip() 他们,他们真的会从词法分析器中删除(因此也从 $text 中删除),但是将它们放在不同的通道上(隐藏或自定义channel) 只会导致解析器规则在它们“轮询”词法分析器以获取新的Token 时跳过它们。从解析器规则中获取$text,也会在其他通道上考虑Tokens。不客气。
    • @SomeGuy 请注意,这些问题与 ANTLR4 有关,而此问题和答案与 ANTLR3 有关。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-22
    • 2012-03-05
    • 2012-03-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多