Как разрешить лексеру анализировать определенные c части кода из java? - PullRequest
2 голосов
/ 05 августа 2020

В настоящее время я создаю компилятор с antlr4, который должен разрешить анализ кода java.

Как разрешить:

public void =(Integer value) => java { this.value = value; }

, что код между java { } не анализируется antlr, но в моем парсере должен быть посетитель.

В настоящее время у меня

javaStatementBody: KWJAVA LCURLY .*? RCURLY

, но это явно не работает и. *? анализирует весь файл.

Пожалуйста, не отвечайте «используйте кавычки», это не будет моим решением, потому что я хочу разрешить выделение java кода.

1 Ответ

2 голосов
/ 05 августа 2020

Вы можете создать отдельные грамматики лексера и парсера, чтобы вы могли использовать лексические режимы . Всякий раз, когда лексер «видит» ввод java {, он переходит к JAVA_MODE. А в режиме Java вы токенизируете комментарии, строковые и символьные литералы. Также в этом режиме вы встречаете {, вы получаете sh тот же JAVA_MODE, чтобы лексер знал, что он вложен один раз. И когда вы сталкиваетесь с }, вы извлекаете режим из стека (что приводит либо к возврату в режим по умолчанию, либо к тому, чтобы оставаться в режиме Java, но на один уровень меньше).

Быстрый демо:

IslandLexer.g4

lexer grammar IslandLexer;

JAVA_START
 : 'java' SPACES '{' -> pushMode(JAVA_MODE)
 ;

OTHER
 : .
 ;

fragment SPACES : [ \t\r\n]+;

mode JAVA_MODE;

  JAVA_CHAR          : '\'' ( ~[\\'\r\n] | '\\' [tbnrf'\\] ) '\'';
  JAVA_STRING        : '"' ( ~[\\"\r\n] | '\\' [tbnrf"\\] )* '"';
  JAVA_LINE_COMMENT  : '//' ~[\r\n]*;
  JAVA_BLOCK_COMMENT : '/*' .*? '*/';
  JAVA_OPEN_BRACE    : '{' -> pushMode(JAVA_MODE);
  JAVA_CLOSE_BRACE   : '}' -> popMode;
  JAVA_OTHER         : ~[{}];

IslandParser.g4

parser grammar IslandParser;

options { tokenVocab=IslandLexer; }

parse
 : unit* EOF
 ;

unit
 : base_language
 | java_janguage
 ;

base_language
 : OTHER+
 ;

java_janguage
 : JAVA_START java_atom+
 ;

java_atom
 : JAVA_CHAR
 | JAVA_STRING
 | JAVA_LINE_COMMENT
 | JAVA_BLOCK_COMMENT
 | JAVA_OPEN_BRACE
 | JAVA_CLOSE_BRACE
 | JAVA_OTHER
 ;

Протестируйте его с помощью следующего кода:

String source = "foo \n" +
        "\n" +
        "java { \n" +
        "  char foo() { \n" +
        "    /* a quote in a comment \\\" */ \n" +
        "    String s = \"java {...}\"; \n" +
        "    return '}'; \n" +
        "  }\n" +
        "}\n" +
        "\n" +
        "bar";

IslandLexer lexer = new IslandLexer(CharStreams.fromString(source));
IslandParser parser = new IslandParser(new CommonTokenStream(lexer));
System.out.println(parser.parse().toStringTree(parser));

, который является следующее дерево синтаксического анализа:

введите описание изображения здесь

...