Получить оригинальный текст правила Antlr - PullRequest
6 голосов
/ 16 сентября 2011

Я новичок в ANTLR и хочу вычислить SHA1-хэш символов.

Моя упрощенная грамматика примера:

grammar Example;

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

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

Поскольку лексер удаляет все пробелы, различные строки callABC, call /* DEF */ ABC, к сожалению, получают одно и то же значение SHA1-Hash.

Можно ли получить «оригинальный» текст правила между начальным и конечным токеном со всеми пропущенными пробелами и текстом других каналов?

(Одна возможность, которая приходит мне в голову, - это включить все символы в правило WS - и COMMENT -lexer, но есть еще много правил, так что это не очень практично.)

Я использую стандартный ANTLRInputStream для подачи Lexer, но я не знаю, как получить исходный текст.

1 Ответ

4 голосов
/ 16 сентября 2011

Вместо skip(), набравшего токен 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();
  }
}

, который выведет на консоль следующее:

call ABC
[48, -45, 113, 5, -52, -128, -78, 75, -52, -97, -35, 25, -55, 59, -85, 96, -58, 58, -96, 10]

call /* DEF */ ABC
[-57, -2, -115, -104, 77, -37, 4, 93, 116, -123, -47, -4, 33, 42, -68, -95, -43, 91, 94, 77]

То есть: одно и то же правило синтаксического анализатора, но разные $text (и поэтому разные SHA1).

...