Разбор javado c с antlr python - PullRequest
1 голос
/ 07 марта 2020

Я пытаюсь разобрать javado c, используя python3 antlr4 runtime. Грамматика была получена из здесь . Код Parser и Lexer был сгенерирован с помощью этой документации. Как я могу сгенерировать дерево из кода и парсера, лексер?

import antlr4


from grammars.javadoc.JavadocParser import JavadocParser
from grammars.javadoc.JavadocLexer import JavadocLexer
from grammars.javadoc.JavadocParserListener import JavadocParserListener


class MyJavaDocListener(JavadocParserListener):
  def enterDocumentation(self, ctx:JavadocParser.DocumentationContext):
    print(ctx.getRuleContext().start.line)
    print(ctx.getRuleContext().stop.line)
    print(ctx.getText())


if __name__ == '__main__':

  code = "class X{/**Some random comment*/public int testM(){return 42;}}"
  input_stream = antlr4.InputStream(code)
  lexer = JavadocLexer(input_stream)
  stream = antlr4.CommonTokenStream(lexer)
  parser = JavadocParser(stream)

  tree = parser.what?

  doclistener = MyJavaDocListener()
  walker = antlr4.ParseTreeWalker()
  walker.walk(doclistener, tree)




1 Ответ

2 голосов
/ 07 марта 2020

Используемая вами грамматика работает только на самом Javado c, а не на целом Java исходном файле, содержащем Javadocs.

Вы используете его следующим образом:

code = "/**Some random comment*/"
input_stream = antlr4.InputStream(code)
lexer = JavadocLexer(input_stream)
stream = antlr4.CommonTokenStream(lexer)
parser = JavadocParser(stream)

# Call the `documentation` function. All parser rules are mapped to functions.
tree = parser.documentation()

doclistener = MyJavaDocListener()
walker = antlr4.ParseTreeWalker()
walker.walk(doclistener, tree)

Если вы хотите извлечь их из Java исходных файлов, вам сначала нужно проанализировать их с помощью Java грамматики / синтаксического анализатора.

Вы можете использовать существующую Java9 грамматику и изменить последний лексер правил:

COMMENT
    :   '/*' .*? '*/' -> channel(HIDDEN)
    ;

LINE_COMMENT
    :   '//' ~[\r\n]* -> channel(HIDDEN)
    ;

в это:

JAVADOC_COMMENT
    :   '/**' .*? '*/' -> channel(HIDDEN)
    ;

COMMENT
    :   '/*' .*? '*/' -> skip
    ;

LINE_COMMENT
    :   '//' ~[\r\n]* -> skip
    ;

Затем создайте пользовательский слушатель, который прослушивает, когда происходит событие enterMethodDeclaration, и затем получаете предыдущий токен из поток токенов и посмотрите, является ли этот токен скрытым JAVADOC_COMMENT токеном.

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

class JavaDocListener(Java9Listener):

    # methodDeclaration
    #   :   methodModifier* methodHeader methodBody
    #   ;
    def enterMethodDeclaration(self, ctx: Java9Parser.MethodDeclarationContext):
        previous_token_index = ctx.getSourceInterval()[0] - 1
        previous_token = ctx.parser.getTokenStream().tokens[previous_token_index]
        method_name = ctx.methodHeader().methodDeclarator().identifier().getText()
        javadoc = previous_token.text if previous_token.type == Java9Lexer.JAVADOC_COMMENT else None
        print('method: {}, javadoc: {}'.format(method_name, javadoc))


if __name__ == '__main__':

    code = """
        public class X {

          public static String mu() { return null; }

          /**
           * Some random comment
           */
          public int testM() {
            return 42;
          }
        }
    """
    input_stream = antlr4.InputStream(code)
    parser = Java9Parser(antlr4.CommonTokenStream(Java9Lexer(input_stream)))

    tree = parser.ordinaryCompilation()

    doc_listener = JavaDocListener()
    walker = antlr4.ParseTreeWalker()
    walker.walk(doc_listener, tree)

, которое напечатает:

method: mu, javadoc: None
method: testM, javadoc: /**
           * Some random comment
           */
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...