Analysieren von Java-Quellcode mit AST (Abstract Syntax Tree) mithilfe von ANTLR und Python

1. Zuallererst

Dieses Mal möchte ich erklären, wie man mit ANTLR und Python Java-Quellcode mit AST (Abstract Syntax Tree) analysiert. Der Grund für Python ist, dass Python einfacher ist und ich heutzutage nur verrückt nach Python bin. Ich habe es schon einmal in Java gemacht, diesmal ist es also wie Python. Wenn es eine Java-Anfrage gibt, möchte ich einen Artikel über Qiita schreiben. Die Ziele dieses Artikels sind die folgenden drei Punkte.

overviewAstForJavaByAntlr.jpg

1.1. Was ist AST (Abstract Syntax Tree)?

Abstrakter Syntaxbaum in Wikipedia Wird (teilweise) wie folgt erklärt.

Ein abstrakter Syntaxbaum (AST) ist ein gewöhnlicher Syntaxbaum (auch als konkreter Syntaxbaum oder Analysebaum bezeichnet), der Informationen entfernt, die nicht mit der Bedeutung der Sprache zusammenhängen, und nur Informationen extrahiert, die für die Bedeutung relevant sind. Es ist eine (abstrakte) baumstrukturierte Datenstruktur.

[Abstrakter Syntaxbaum mit Google-Bild](https://www.google.com/search?client=firefox-b&biw=1314&bih=959&tbm=isch&sa=1&ei=ATyOW9_CN8it8QXrhIGwCQ&q=%E6%8A%BD%E8%B1%1 E6% A7% 8B% E6% 96% 87% E6% 9C% A8 & oq =% E6% 8A% BD% E8% B1% A1% E6% A7% 8B% E6% 96% 87% E6% 9C% A8 & gs_l = img 3..0j0i24k1l4.4434.5025.0.5921.5.5.0.0.0.0.78.375.5.5.0 .... 0 ... 1c.1.64.img..0.2.152 .... 0.6gcyAKZr7NM) Ich denke, Sie können ein Bild bekommen. Es ist jedoch immer noch schwierig.

Um es einfach auszudrücken, ich denke die folgenden drei Punkte.

1.2 Was ist ANTLR?

ANTLR (http://www.antlr.org/) ist ein Tool, das eine Grammatikdatei (g4-Datei) als Eingabe verwendet und automatisch eine Funktion generiert, die zum Parsen abstrakter Syntaxbäume erforderlich ist, einen sogenannten Analysator. Da die Grammatikdatei nicht von der Programmiersprache des Analysators abhängt, ist es möglich, einen Analysator für mehrere Programmiersprachen zu generieren. Dieses Mal werden wir den Analysatorcode für Python generieren.

Die Hauptkomponenten des Analysators sind unten aufgeführt.

Lexer: Phrasenanalyse

Erklärung von Phrasenanalyse in Wikipedia (Teil) Ist wie folgt.

Die Phrasenanalyse (Lexikalische Analyse) ist die erste Hälfte der Syntaxanalyse im weiteren Sinne, bei der Zeichenketten wie Sätze in natürlicher Sprache und Quellcode in der Programmiersprache und im engeren Sinne der zweiten Hälfte analysiert werden. Dies ist ein Verfahren zum Erhalten einer Folge von "Token" (Phrasen), die die kleinste Einheit (Beendigungssymbol) in der syntaktischen Analyse darstellt. Das Programm, das die Phrasenanalyse durchführt, ist ein Phrasenanalysator. Siehe Morphologische Analyse für die Analyse von Phrasen in natürlicher Sprache.

es ist schwierig. Einfach ausgedrückt, wird überprüft, ob es in einer Zeichenfolge geschrieben ist, die als Programmiersprachenspezifikation verwendet werden kann. In Python sind beispielsweise die Wörter "from", "def", "elif" usw. als Syntax verfügbar, in Java können diese Wörter jedoch nicht als Syntax verwendet werden. Lexer erledigt das für Sie. Da Lexer den Spezifikationen der Grammatikdatei folgt, wird grundsätzlich der von ANTLR generierte Lexer verwendet.

Parser: Syntaxanalyse

Erklärung von Syntaxanalyse in Wikipedia (teilweise) Ist wie folgt.

Die syntaktische Analyse (syntaktische Analyse oder Analyse) unterteilt eine feste Zeichenkette ohne Noten wie Sätze, insbesondere Markups, in morphologische Elemente in natürlicher Sprache und dazwischen. Es ist ein Verfahren zum Klären (Analysieren) einer syntaktischen (syntaktischen) Beziehung, z. B. einer Beziehung (modifikationsmodifiziert usw.). Natürliche Sprache ist einer der Hauptpunkte bei der Verarbeitung natürlicher Sprache, und bei formalen Sprachen wie Programmiersprachen wird ein Syntaxbaum gemäß der formalen Grammatik erhalten. Der Mechanismus zur Durchführung der Syntaxanalyse wird als Syntaxanalysator (Parser) bezeichnet.

es ist schwierig. Wie der Wortlaut von "Syntaxanalyse" zeigt, ist es ein Prozess, den zu analysierenden Text zu lesen und ihn in einen Syntaxbaum zu zerlegen. Genau das stellen Sie sich vor. Da Parser den Spezifikationen der Grammatikdatei folgt, wird grundsätzlich der von ANTLR generierte Parser verwendet.

Listener: Ereignis-Listener

Lexer und Parser sind die Hauptprozesse, die bei der Verarbeitung natürlicher Sprache auftreten. Listener ist jedoch eine API, mit der Benutzer ihre eigenen Analysegeräte erstellen können. Welche Art von API ist der Hook-Punkt des Ereignisses, das auftritt, wenn der Knoten des Syntaxbaums wechselt. Am Beispiel von Java, das Gegenstand dieser Analyse ist, haben wir den Kontext der Klassendefinition eingegeben und der Kontext wurde beendet, wir haben den Kontext der Methodendefinition eingegeben und der Kontext wurde beendet und so weiter. Der von ANTLR automatisch generierte Listener ist nur standardmäßig implementiert. Im Gegensatz zu Lexer und Parser wird der generierte Listener also erweitert (vererbt) und verwendet.

2. ANTLR generiert automatisch einen Analysator

2.1 ANTLR erhalten

Die Möglichkeit, einen ANTLR-Analysator zu generieren, wird als Java-Programm bereitgestellt. Holen Sie sich http://www.antlr.org/download/antlr-runtime-4.7.1.jar und speichern Sie es in einem beliebigen Verzeichnis. Wenn Sie das JDK nicht installiert haben, installieren Sie es bitte.

2.2 Erhalten der Grammatikdatei (g4)

Eine Grammatikdatei (g4) für die Programmiersprache ist auf der GitHub-Seite von ANTLR verfügbar. Java hat für jede Version unterschiedliche Grammatikdateien. Dieses Mal erhalten Sie die Grammatikdatei für Java 8 unter https://github.com/antlr/grammars-v4/tree/master/java. Speichern Sie die erhaltenen Dateien (JavaLexer.g4, JavaParser.g4) in einem beliebigen Verzeichnis (Beispiel: Grammatik).

Vor der Generation


.
│  antlr-4.7.1-complete.jar
│
└─grammar
        JavaLexer.g4
        JavaParser.g4

2.3 Lexer, Parser, Standard-Listener-Generierung

Der Befehl zum Generieren von Leexer, Parser und Listener für Python3 mit ANTLR wird unten gezeigt. Geben Sie die Programmiersprache des Analysators mit der Option -Dlanguage an. Beachten Sie, dass Python 3 und Python 2 für Python unterschiedlich sind.

Befehle zum Generieren von Lexer, Parser, Listener für Python3


java -jar antlr-4.7.1-complete.jar -Dlanguage=Python3 grammar\*.g4

Nach der Generation


.
│  antlr-4.7.1-complete.jar
│
└─grammar
        JavaLexer.g4
        JavaParser.g4
        JavaLexer.interp
        JavaLexer.py
        JavaLexer.tokens
        JavaParser.interp
        JavaParser.py
        JavaParser.tokens
        JavaParserListener.py

Sie haben jetzt den für die Java-Quellcode-Analyse erforderlichen Analyzer-Quellcode (JavaLexer.py, JavaParser.py, JavaParserListener.py). Danach werden wir diese Datei verwenden, um unser eigenes Syntaxanalyseprogramm zu implementieren.

2.4. (Referenz) Generieren von Lexer, Parser und Standard-Listener für Java

Als Referenz werden die Befehle zum Generieren von Lexer, Parser und Linstener für Java unten gezeigt. Sie können ein Java-Paket mit der Option -package angeben.

Befehle zum Generieren von Lexer, Parser, Linstener für Java


// com.example.service.Ausgabe als Antlr-Paket
java -jar antlr-4.7.1-complete.jar -Dlanguage=Java -encoding utf-8 -package com.example.service.antlr grammar\*.g4

3. Erstellen Sie ein Syntaxanalyseprogramm

Installieren Sie "antlr4-python3-runtime", um ANTLR mit Python zu verwenden. Bitte beachten Sie, dass es separate Bibliotheken für Python2 und Python3 gibt.

Laufzeit von Antlr mit Pip installiert


antlr4-python3-runtime             4.7.1

Erstellen Sie wie oben erwähnt einen Listener für jeden Zweck, den Sie analysieren möchten. Dieses Mal möchte ich einen Listener erstellen, der die grundlegenden Informationen und Methodenaufrufe der Java-Klasse erhält.

3.1 Vom Hörer erfasste Informationen

3.2. Verzeichnisstruktur

Verzeichnisaufbau


C:/temp/sample
├─logs
│      utiltools.log
│
├─resources
│  └─logging
│          utiltools_log.conf
│
└─src
    │  ast_analyze_executor.py
    │
    └─ast
            ast_processor.py
            basic_info_listener.py
            JavaLexer.py
            JavaParser.py
            JavaParserListener.py
            __init__.py

JavaLexer.py, JavaParser.py und JavaParserListener.py kopieren die von ANTLR automatisch generierten Dateien so wie sie sind.

3.3. Hauptverarbeitung

Dies ist ein Prozess mit einer Hauptfunktion. Der Dateipfad wird direkt zur Erklärung geschrieben, aber bitte korrigieren Sie ihn entsprechend.

ast_analyze_executor.py


import logging.config
from ast.ast_processor import AstProcessor
from ast.basic_info_listener import BasicInfoListener


if __name__ == '__main__':
    logging_setting_path = '../resources/logging/utiltools_log.conf'
    logging.config.fileConfig(logging_setting_path)
    logger = logging.getLogger(__file__)

    target_file_path = 'C:/temp/Zu analysierende Datei.java'

    #★ Punkt 1
    ast_info = AstProcessor(logging, BasicInfoListener()).execute(target_file_path)

★ Punkt 1

Erstellen Sie nach dem Erstellen einer unabhängig implementierten Listener-Instanz eine später beschriebene Instanz von "AstProcessor". Führen Sie die Methode "execute" von "AstProcessor" mit dem Dateipfad der zu analysierenden Datei als Argument für die Analyse des Quellcodes aus. Der Rückgabewert der Methode "execute" ist das Analyseergebnis.

3.4. Prozess zum Ausführen des Listeners

Ich erklärte, dass es Listener ist, der seine eigene Analyseverarbeitung durchführt. Daher erstellen Sie normalerweise mehrere Listener entsprechend Ihrem Zweck. Der Prozess zum Ausführen von Listener ändert sich jedoch nicht. Daher werden wir den Prozess zum Ausführen von Listener für allgemeine Zwecke implementieren.

ast_processor.py


from antlr4 import FileStream, CommonTokenStream, ParseTreeWalker
from ast.JavaLexer import JavaLexer
from ast.JavaParser import JavaParser
from pprint import pformat


class AstProcessor:

    def __init__(self, logging, listener):
        self.logging = logging
        self.logger = logging.getLogger(self.__class__.__name__)
        self.listener = listener

    #★ Punkt 2
    def execute(self, input_source):
        parser = JavaParser(CommonTokenStream(JavaLexer(FileStream(input_source, encoding="utf-8"))))
        walker = ParseTreeWalker()
        walker.walk(self.listener, parser.compilationUnit())
        self.logger.debug('Display all data extracted by AST. \n' + pformat(self.listener.ast_info, width=160))
        return self.listener.ast_info

★ Punkt 2

Erstellen Sie eine Instanz von "JavaLexer" aus der zu analysierenden Datei und generieren Sie daraus eine Instanz von "JavaParser". Das Parsen erfolgt durch Aufrufen der "walk" -Methode der "ParseTreeWalker" -Instanz. Dieser Ablauf ist auch dann gleich, wenn die Listener-Verarbeitung unterschiedlich ist.

3.5. Verarbeitung des proprietären Listeners

In diesem Abschnitt wird beschrieben, wie Sie den ursprünglichen Listener implementieren, der der Schlüsselpunkt der Quellcode-Analyse ist. Es gibt jedoch nur drei Punkte.

basic_info_listener.py


from ast.JavaParserListener import JavaParserListener
from ast.JavaParser import JavaParser


#★ Punkt 3
class BasicInfoListener(JavaParserListener):

    #★ Punkt 4
    def __init__(self):
        self.call_methods = []
        self.ast_info = {
            'packageName': '',
            'className': '',
            'implements': [],
            'extends': '',
            'imports': [],
            'fields': [],
            'methods': []
        }

    #★ Punkt 5
    # Enter a parse tree produced by JavaParser#packageDeclaration.
    def enterPackageDeclaration(self, ctx:JavaParser.PackageDeclarationContext):
        self.ast_info['packageName'] = ctx.qualifiedName().getText()

    # Enter a parse tree produced by JavaParser#importDeclaration.
    def enterImportDeclaration(self, ctx:JavaParser.ImportDeclarationContext):
        import_class = ctx.qualifiedName().getText()
        self.ast_info['imports'].append(import_class)

    # Enter a parse tree produced by JavaParser#methodDeclaration.
    def enterMethodDeclaration(self, ctx:JavaParser.MethodDeclarationContext):

        print("{0} {1} {2}".format(ctx.start.line, ctx.start.column, ctx.getText()))
        self.call_methods = []

    # Exit a parse tree produced by JavaParser#methodDeclaration.
    def exitMethodDeclaration(self, ctx:JavaParser.MethodDeclarationContext):

        #★ Punkt 6
        c1 = ctx.getChild(0).getText()  # ---> return type
        c2 = ctx.getChild(1).getText()  # ---> method name
        # c3 = ctx.getChild(2).getText()  # ---> params
        params = self.parse_method_params_block(ctx.getChild(2))

        method_info = {
            'returnType': c1,
            'methodName': c2,
            'params': params,
            'callMethods': self.call_methods
        }
        self.ast_info['methods'].append(method_info)

    # Enter a parse tree produced by JavaParser#methodCall.
    def enterMethodCall(self, ctx:JavaParser.MethodCallContext):
        #★ Punkt 7
        line_number = str(ctx.start.line)
        column_number = str(ctx.start.column)
        self.call_methods.append(line_number + ' ' + column_number + ' ' + ctx.parentCtx.getText())

    # Enter a parse tree produced by JavaParser#classDeclaration.
    def enterClassDeclaration(self, ctx:JavaParser.ClassDeclarationContext):
        child_count = int(ctx.getChildCount())
        if child_count == 7:
            # class Foo extends Bar implements Hoge
            # c1 = ctx.getChild(0)  # ---> class
            c2 = ctx.getChild(1).getText()  # ---> class name
            # c3 = ctx.getChild(2)  # ---> extends
            c4 = ctx.getChild(3).getChild(0).getText()  # ---> extends class name
            # c5 = ctx.getChild(4)  # ---> implements
            # c7 = ctx.getChild(6)  # ---> method body
            self.ast_info['className'] = c2
            self.ast_info['implements'] = self.parse_implements_block(ctx.getChild(5))
            self.ast_info['extends'] = c4
        elif child_count == 5:
            # class Foo extends Bar
            # or
            # class Foo implements Hoge
            # c1 = ctx.getChild(0)  # ---> class
            c2 = ctx.getChild(1).getText()  # ---> class name
            c3 = ctx.getChild(2).getText()  # ---> extends or implements

            # c5 = ctx.getChild(4)  # ---> method body
            self.ast_info['className'] = c2
            if c3 == 'implements':
                self.ast_info['implements'] = self.parse_implements_block(ctx.getChild(3))
            elif c3 == 'extends':
                c4 = ctx.getChild(3).getChild(0).getText()  # ---> extends class name or implements class name
                self.ast_info['extends'] = c4
        elif child_count == 3:
            # class Foo
            # c1 = ctx.getChild(0)  # ---> class
            c2 = ctx.getChild(1).getText()  # ---> class name
            # c3 = ctx.getChild(2)  # ---> method body
            self.ast_info['className'] = c2

    # Enter a parse tree produced by JavaParser#fieldDeclaration.
    def enterFieldDeclaration(self, ctx:JavaParser.FieldDeclarationContext):
        field = {
            'fieldType': ctx.getChild(0).getText(),
            'fieldDefinition': ctx.getChild(1).getText()
        }
        self.ast_info['fields'].append(field)

    def parse_implements_block(self, ctx):
        implements_child_count = int(ctx.getChildCount())
        result = []
        if implements_child_count == 1:
            impl_class = ctx.getChild(0).getText()
            result.append(impl_class)
        elif implements_child_count > 1:
            for i in range(implements_child_count):
                if i % 2 == 0:
                    impl_class = ctx.getChild(i).getText()
                    result.append(impl_class)
        return result

    def parse_method_params_block(self, ctx):
        params_exist_check = int(ctx.getChildCount())
        result = []
        # () ---> 2
        # (Foo foo) ---> 3
        # (Foo foo, Bar bar) ---> 3
        # (Foo foo, Bar bar, int count) ---> 3
        if params_exist_check == 3:
            params_child_count = int(ctx.getChild(1).getChildCount())
            if params_child_count == 1:
                param_type = ctx.getChild(1).getChild(0).getChild(0).getText()
                param_name = ctx.getChild(1).getChild(0).getChild(1).getText()
                param_info = {
                    'paramType': param_type,
                    'paramName': param_name
                }
                result.append(param_info)
            elif params_child_count > 1:
                for i in range(params_child_count):
                    if i % 2 == 0:
                        param_type = ctx.getChild(1).getChild(i).getChild(0).getText()
                        param_name = ctx.getChild(1).getChild(i).getChild(1).getText()
                        param_info = {
                            'paramType': param_type,
                            'paramName': param_name
                        }
                        result.append(param_info)
        return result

★ Punkt 3

Erweitern (erben) Sie JavaParserListener, um Ihren eigenen Listener, BasicInfoListener, zu definieren.

★ Punkt 4

Definieren Sie "ast_info", um die Analyseergebnisse zu speichern. Bitte ändern Sie den Namen und den Inhalt der Immobilie entsprechend dem Zweck, den Sie analysieren möchten.

★ Punkt 5

Es überschreibt die in JavaParserListener definierte Hookpoint-Funktion und implementiert einen eigenen Parsing-Prozess. Beispielsweise wird "enterPackageDeclaration", wie der Name schon sagt, dort aufgerufen, wo die Paketdefinition des Java-Quellcodes beginnt. Das Argument "ctx" ist von einem anderen Typ, aber da es eine übergeordnete Klasse hat, kann jede Kontextklasse auf die grundlegenden Informationen zugreifen, die für die Syntaxanalyse erforderlich sind.

★ Punkt 6

Wie der Name von AST (Abstract Syntax Tree) andeutet, hat ctx eine Baumstruktur. Sie können mit der Funktion "getChild" auf die untergeordneten Knoten dieses Kontexts zugreifen. Der Inhalt der untergeordneten Knoten hängt vom Kontext ab.

★ Punkt 7

Normalerweise behält AST (Abstract Syntax Tree) keine konkreten Zeilennummern und Zeichenpositionen bei, aber ANTLR behält diese Informationen im Kontext bei. Auch diese Informationen sind nützlich, wenn Sie den Quellcode analysieren. Verwenden Sie sie daher nach Bedarf.

4. Testen

Eine Klasse von TEARASOLUNA 5.x-Beispielanwendungenを対象に解析を行ってみたいと思います。

TourInfoServiceImpl.java


/*
 * Copyright (C) 2013-2018 NTT DATA Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package org.terasoluna.tourreservation.domain.service.tourinfo;

import java.util.Collections;
import java.util.List;

import javax.inject.Inject;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.terasoluna.tourreservation.domain.model.TourInfo;
import org.terasoluna.tourreservation.domain.repository.tourinfo.TourInfoRepository;
import org.terasoluna.tourreservation.domain.repository.tourinfo.TourInfoSearchCriteria;

@Service
@Transactional
public class TourInfoServiceImpl implements TourInfoService {

    @Inject
    TourInfoRepository tourInfoRepository;

    @Override
    public Page<TourInfo> searchTour(TourInfoSearchCriteria criteria,
            Pageable pageable) {

        long total = tourInfoRepository.countBySearchCriteria(criteria);
        List<TourInfo> content;
        if (0 < total) {
            content = tourInfoRepository.findPageBySearchCriteria(criteria,
                    pageable);
        } else {
            content = Collections.emptyList();
        }

        Page<TourInfo> page = new PageImpl<TourInfo>(content, pageable, total);
        return page;
    }
}

Analyseergebnis


{'className': 'TourInfoServiceImpl',
 'extends': '',
 'fields': [{'fieldDefinition': 'tourInfoRepository', 'fieldType': 'TourInfoRepository'}],
 'implements': ['TourInfoService'],
 'imports': ['java.util.Collections',
             'java.util.List',
             'javax.inject.Inject',
             'org.springframework.data.domain.Page',
             'org.springframework.data.domain.PageImpl',
             'org.springframework.data.domain.Pageable',
             'org.springframework.stereotype.Service',
             'org.springframework.transaction.annotation.Transactional',
             'org.terasoluna.tourreservation.domain.model.TourInfo',
             'org.terasoluna.tourreservation.domain.repository.tourinfo.TourInfoRepository',
             'org.terasoluna.tourreservation.domain.repository.tourinfo.TourInfoSearchCriteria'],
 'methods': [{'callMethods': ['43 40 tourInfoRepository.countBySearchCriteria(criteria)',
                              '46 41 tourInfoRepository.findPageBySearchCriteria(criteria,pageable)',
                              '49 34 Collections.emptyList()'],
              'methodName': 'searchTour',
              'params': [{'paramName': 'criteria', 'paramType': 'TourInfoSearchCriteria'}, {'paramName': 'pageable', 'paramType': 'Pageable'}],
              'returnType': 'Page<TourInfo>'}],
 'packageName': 'org.terasoluna.tourreservation.domain.service.tourinfo'}

Wenn Sie sich die Analyseergebnisse ansehen, können Sie sehen, dass die Struktur der Klasse und der Verarbeitungsinhalt verstanden werden können.

5. Schließlich

Dieses Mal erklärte ich, wie man mit ANTLR und Python Java-Quellcode mit AST (Abstract Syntax Tree) analysiert. Ich hoffe, Sie verstehen, dass die Verwendung von ANTLR einfacher und strukturierter ist als die Textanalyse wie Grep. Obwohl in der Probe nicht erhalten, können auch die folgenden Informationen erhalten werden.

Durch die Integration der Syntaxanalyse mit ANTLR können Sie Tools und Anwendungen erstellen, die Quellcode als Eingabe verwenden.

exampleUsecaseOfUsingAntlr.jpg

6. Liste der Hakenpunktfunktionen (Referenz)

Als Referenz wird unten eine Liste der Listener-Hookpoint-Funktionen angezeigt.

Liste der Hakenpunktfunktionen (insgesamt 208)


def enterCompilationUnit(self, ctx:JavaParser.CompilationUnitContext):
def exitCompilationUnit(self, ctx:JavaParser.CompilationUnitContext):
def enterPackageDeclaration(self, ctx:JavaParser.PackageDeclarationContext):
def exitPackageDeclaration(self, ctx:JavaParser.PackageDeclarationContext):
def enterImportDeclaration(self, ctx:JavaParser.ImportDeclarationContext):
def exitImportDeclaration(self, ctx:JavaParser.ImportDeclarationContext):
def enterTypeDeclaration(self, ctx:JavaParser.TypeDeclarationContext):
def exitTypeDeclaration(self, ctx:JavaParser.TypeDeclarationContext):
def enterModifier(self, ctx:JavaParser.ModifierContext):
def exitModifier(self, ctx:JavaParser.ModifierContext):
def enterClassOrInterfaceModifier(self, ctx:JavaParser.ClassOrInterfaceModifierContext):
def exitClassOrInterfaceModifier(self, ctx:JavaParser.ClassOrInterfaceModifierContext):
def enterVariableModifier(self, ctx:JavaParser.VariableModifierContext):
def exitVariableModifier(self, ctx:JavaParser.VariableModifierContext):
def enterClassDeclaration(self, ctx:JavaParser.ClassDeclarationContext):
def exitClassDeclaration(self, ctx:JavaParser.ClassDeclarationContext):
def enterTypeParameters(self, ctx:JavaParser.TypeParametersContext):
def exitTypeParameters(self, ctx:JavaParser.TypeParametersContext):
def enterTypeParameter(self, ctx:JavaParser.TypeParameterContext):
def exitTypeParameter(self, ctx:JavaParser.TypeParameterContext):
def enterTypeBound(self, ctx:JavaParser.TypeBoundContext):
def exitTypeBound(self, ctx:JavaParser.TypeBoundContext):
def enterEnumDeclaration(self, ctx:JavaParser.EnumDeclarationContext):
def exitEnumDeclaration(self, ctx:JavaParser.EnumDeclarationContext):
def enterEnumConstants(self, ctx:JavaParser.EnumConstantsContext):
def exitEnumConstants(self, ctx:JavaParser.EnumConstantsContext):
def enterEnumConstant(self, ctx:JavaParser.EnumConstantContext):
def exitEnumConstant(self, ctx:JavaParser.EnumConstantContext):
def enterEnumBodyDeclarations(self, ctx:JavaParser.EnumBodyDeclarationsContext):
def exitEnumBodyDeclarations(self, ctx:JavaParser.EnumBodyDeclarationsContext):
def enterInterfaceDeclaration(self, ctx:JavaParser.InterfaceDeclarationContext):
def exitInterfaceDeclaration(self, ctx:JavaParser.InterfaceDeclarationContext):
def enterClassBody(self, ctx:JavaParser.ClassBodyContext):
def exitClassBody(self, ctx:JavaParser.ClassBodyContext):
def enterInterfaceBody(self, ctx:JavaParser.InterfaceBodyContext):
def exitInterfaceBody(self, ctx:JavaParser.InterfaceBodyContext):
def enterClassBodyDeclaration(self, ctx:JavaParser.ClassBodyDeclarationContext):
def exitClassBodyDeclaration(self, ctx:JavaParser.ClassBodyDeclarationContext):
def enterMemberDeclaration(self, ctx:JavaParser.MemberDeclarationContext):
def exitMemberDeclaration(self, ctx:JavaParser.MemberDeclarationContext):
def enterMethodDeclaration(self, ctx:JavaParser.MethodDeclarationContext):
def exitMethodDeclaration(self, ctx:JavaParser.MethodDeclarationContext):
def enterMethodBody(self, ctx:JavaParser.MethodBodyContext):
def exitMethodBody(self, ctx:JavaParser.MethodBodyContext):
def enterTypeTypeOrVoid(self, ctx:JavaParser.TypeTypeOrVoidContext):
def exitTypeTypeOrVoid(self, ctx:JavaParser.TypeTypeOrVoidContext):
def enterGenericMethodDeclaration(self, ctx:JavaParser.GenericMethodDeclarationContext):
def exitGenericMethodDeclaration(self, ctx:JavaParser.GenericMethodDeclarationContext):
def enterGenericConstructorDeclaration(self, ctx:JavaParser.GenericConstructorDeclarationContext):
def exitGenericConstructorDeclaration(self, ctx:JavaParser.GenericConstructorDeclarationContext):
def enterConstructorDeclaration(self, ctx:JavaParser.ConstructorDeclarationContext):
def exitConstructorDeclaration(self, ctx:JavaParser.ConstructorDeclarationContext):
def enterFieldDeclaration(self, ctx:JavaParser.FieldDeclarationContext):
def exitFieldDeclaration(self, ctx:JavaParser.FieldDeclarationContext):
def enterInterfaceBodyDeclaration(self, ctx:JavaParser.InterfaceBodyDeclarationContext):
def exitInterfaceBodyDeclaration(self, ctx:JavaParser.InterfaceBodyDeclarationContext):
def enterInterfaceMemberDeclaration(self, ctx:JavaParser.InterfaceMemberDeclarationContext):
def exitInterfaceMemberDeclaration(self, ctx:JavaParser.InterfaceMemberDeclarationContext):
def enterConstDeclaration(self, ctx:JavaParser.ConstDeclarationContext):
def exitConstDeclaration(self, ctx:JavaParser.ConstDeclarationContext):
def enterConstantDeclarator(self, ctx:JavaParser.ConstantDeclaratorContext):
def exitConstantDeclarator(self, ctx:JavaParser.ConstantDeclaratorContext):
def enterInterfaceMethodDeclaration(self, ctx:JavaParser.InterfaceMethodDeclarationContext):
def exitInterfaceMethodDeclaration(self, ctx:JavaParser.InterfaceMethodDeclarationContext):
def enterInterfaceMethodModifier(self, ctx:JavaParser.InterfaceMethodModifierContext):
def exitInterfaceMethodModifier(self, ctx:JavaParser.InterfaceMethodModifierContext):
def enterGenericInterfaceMethodDeclaration(self, ctx:JavaParser.GenericInterfaceMethodDeclarationContext):
def exitGenericInterfaceMethodDeclaration(self, ctx:JavaParser.GenericInterfaceMethodDeclarationContext):
def enterVariableDeclarators(self, ctx:JavaParser.VariableDeclaratorsContext):
def exitVariableDeclarators(self, ctx:JavaParser.VariableDeclaratorsContext):
def enterVariableDeclarator(self, ctx:JavaParser.VariableDeclaratorContext):
def exitVariableDeclarator(self, ctx:JavaParser.VariableDeclaratorContext):
def enterVariableDeclaratorId(self, ctx:JavaParser.VariableDeclaratorIdContext):
def exitVariableDeclaratorId(self, ctx:JavaParser.VariableDeclaratorIdContext):
def enterVariableInitializer(self, ctx:JavaParser.VariableInitializerContext):
def exitVariableInitializer(self, ctx:JavaParser.VariableInitializerContext):
def enterArrayInitializer(self, ctx:JavaParser.ArrayInitializerContext):
def exitArrayInitializer(self, ctx:JavaParser.ArrayInitializerContext):
def enterClassOrInterfaceType(self, ctx:JavaParser.ClassOrInterfaceTypeContext):
def exitClassOrInterfaceType(self, ctx:JavaParser.ClassOrInterfaceTypeContext):
def enterTypeArgument(self, ctx:JavaParser.TypeArgumentContext):
def exitTypeArgument(self, ctx:JavaParser.TypeArgumentContext):
def enterQualifiedNameList(self, ctx:JavaParser.QualifiedNameListContext):
def exitQualifiedNameList(self, ctx:JavaParser.QualifiedNameListContext):
def enterFormalParameters(self, ctx:JavaParser.FormalParametersContext):
def exitFormalParameters(self, ctx:JavaParser.FormalParametersContext):
def enterFormalParameterList(self, ctx:JavaParser.FormalParameterListContext):
def exitFormalParameterList(self, ctx:JavaParser.FormalParameterListContext):
def enterFormalParameter(self, ctx:JavaParser.FormalParameterContext):
def exitFormalParameter(self, ctx:JavaParser.FormalParameterContext):
def enterLastFormalParameter(self, ctx:JavaParser.LastFormalParameterContext):
def exitLastFormalParameter(self, ctx:JavaParser.LastFormalParameterContext):
def enterQualifiedName(self, ctx:JavaParser.QualifiedNameContext):
def exitQualifiedName(self, ctx:JavaParser.QualifiedNameContext):
def enterLiteral(self, ctx:JavaParser.LiteralContext):
def exitLiteral(self, ctx:JavaParser.LiteralContext):
def enterIntegerLiteral(self, ctx:JavaParser.IntegerLiteralContext):
def exitIntegerLiteral(self, ctx:JavaParser.IntegerLiteralContext):
def enterFloatLiteral(self, ctx:JavaParser.FloatLiteralContext):
def exitFloatLiteral(self, ctx:JavaParser.FloatLiteralContext):
def enterAnnotation(self, ctx:JavaParser.AnnotationContext):
def exitAnnotation(self, ctx:JavaParser.AnnotationContext):
def enterElementValuePairs(self, ctx:JavaParser.ElementValuePairsContext):
def exitElementValuePairs(self, ctx:JavaParser.ElementValuePairsContext):
def enterElementValuePair(self, ctx:JavaParser.ElementValuePairContext):
def exitElementValuePair(self, ctx:JavaParser.ElementValuePairContext):
def enterElementValue(self, ctx:JavaParser.ElementValueContext):
def exitElementValue(self, ctx:JavaParser.ElementValueContext):
def enterElementValueArrayInitializer(self, ctx:JavaParser.ElementValueArrayInitializerContext):
def exitElementValueArrayInitializer(self, ctx:JavaParser.ElementValueArrayInitializerContext):
def enterAnnotationTypeDeclaration(self, ctx:JavaParser.AnnotationTypeDeclarationContext):
def exitAnnotationTypeDeclaration(self, ctx:JavaParser.AnnotationTypeDeclarationContext):
def enterAnnotationTypeBody(self, ctx:JavaParser.AnnotationTypeBodyContext):
def exitAnnotationTypeBody(self, ctx:JavaParser.AnnotationTypeBodyContext):
def enterAnnotationTypeElementDeclaration(self, ctx:JavaParser.AnnotationTypeElementDeclarationContext):
def exitAnnotationTypeElementDeclaration(self, ctx:JavaParser.AnnotationTypeElementDeclarationContext):
def enterAnnotationTypeElementRest(self, ctx:JavaParser.AnnotationTypeElementRestContext):
def exitAnnotationTypeElementRest(self, ctx:JavaParser.AnnotationTypeElementRestContext):
def enterAnnotationMethodOrConstantRest(self, ctx:JavaParser.AnnotationMethodOrConstantRestContext):
def exitAnnotationMethodOrConstantRest(self, ctx:JavaParser.AnnotationMethodOrConstantRestContext):
def enterAnnotationMethodRest(self, ctx:JavaParser.AnnotationMethodRestContext):
def exitAnnotationMethodRest(self, ctx:JavaParser.AnnotationMethodRestContext):
def enterAnnotationConstantRest(self, ctx:JavaParser.AnnotationConstantRestContext):
def exitAnnotationConstantRest(self, ctx:JavaParser.AnnotationConstantRestContext):
def enterDefaultValue(self, ctx:JavaParser.DefaultValueContext):
def exitDefaultValue(self, ctx:JavaParser.DefaultValueContext):
def enterBlock(self, ctx:JavaParser.BlockContext):
def exitBlock(self, ctx:JavaParser.BlockContext):
def enterBlockStatement(self, ctx:JavaParser.BlockStatementContext):
def exitBlockStatement(self, ctx:JavaParser.BlockStatementContext):
def enterLocalVariableDeclaration(self, ctx:JavaParser.LocalVariableDeclarationContext):
def exitLocalVariableDeclaration(self, ctx:JavaParser.LocalVariableDeclarationContext):
def enterLocalTypeDeclaration(self, ctx:JavaParser.LocalTypeDeclarationContext):
def exitLocalTypeDeclaration(self, ctx:JavaParser.LocalTypeDeclarationContext):
def enterStatement(self, ctx:JavaParser.StatementContext):
def exitStatement(self, ctx:JavaParser.StatementContext):
def enterCatchClause(self, ctx:JavaParser.CatchClauseContext):
def exitCatchClause(self, ctx:JavaParser.CatchClauseContext):
def enterCatchType(self, ctx:JavaParser.CatchTypeContext):
def exitCatchType(self, ctx:JavaParser.CatchTypeContext):
def enterFinallyBlock(self, ctx:JavaParser.FinallyBlockContext):
def exitFinallyBlock(self, ctx:JavaParser.FinallyBlockContext):
def enterResourceSpecification(self, ctx:JavaParser.ResourceSpecificationContext):
def exitResourceSpecification(self, ctx:JavaParser.ResourceSpecificationContext):
def enterResources(self, ctx:JavaParser.ResourcesContext):
def exitResources(self, ctx:JavaParser.ResourcesContext):
def enterResource(self, ctx:JavaParser.ResourceContext):
def exitResource(self, ctx:JavaParser.ResourceContext):
def enterSwitchBlockStatementGroup(self, ctx:JavaParser.SwitchBlockStatementGroupContext):
def exitSwitchBlockStatementGroup(self, ctx:JavaParser.SwitchBlockStatementGroupContext):
def enterSwitchLabel(self, ctx:JavaParser.SwitchLabelContext):
def exitSwitchLabel(self, ctx:JavaParser.SwitchLabelContext):
def enterForControl(self, ctx:JavaParser.ForControlContext):
def exitForControl(self, ctx:JavaParser.ForControlContext):
def enterForInit(self, ctx:JavaParser.ForInitContext):
def exitForInit(self, ctx:JavaParser.ForInitContext):
def enterEnhancedForControl(self, ctx:JavaParser.EnhancedForControlContext):
def exitEnhancedForControl(self, ctx:JavaParser.EnhancedForControlContext):
def enterParExpression(self, ctx:JavaParser.ParExpressionContext):
def exitParExpression(self, ctx:JavaParser.ParExpressionContext):
def enterExpressionList(self, ctx:JavaParser.ExpressionListContext):
def exitExpressionList(self, ctx:JavaParser.ExpressionListContext):
def enterMethodCall(self, ctx:JavaParser.MethodCallContext):
def exitMethodCall(self, ctx:JavaParser.MethodCallContext):
def enterExpression(self, ctx:JavaParser.ExpressionContext):
def exitExpression(self, ctx:JavaParser.ExpressionContext):
def enterLambdaExpression(self, ctx:JavaParser.LambdaExpressionContext):
def exitLambdaExpression(self, ctx:JavaParser.LambdaExpressionContext):
def enterLambdaParameters(self, ctx:JavaParser.LambdaParametersContext):
def exitLambdaParameters(self, ctx:JavaParser.LambdaParametersContext):
def enterLambdaBody(self, ctx:JavaParser.LambdaBodyContext):
def exitLambdaBody(self, ctx:JavaParser.LambdaBodyContext):
def enterPrimary(self, ctx:JavaParser.PrimaryContext):
def exitPrimary(self, ctx:JavaParser.PrimaryContext):
def enterClassType(self, ctx:JavaParser.ClassTypeContext):
def exitClassType(self, ctx:JavaParser.ClassTypeContext):
def enterCreator(self, ctx:JavaParser.CreatorContext):
def exitCreator(self, ctx:JavaParser.CreatorContext):
def enterCreatedName(self, ctx:JavaParser.CreatedNameContext):
def exitCreatedName(self, ctx:JavaParser.CreatedNameContext):
def enterInnerCreator(self, ctx:JavaParser.InnerCreatorContext):
def exitInnerCreator(self, ctx:JavaParser.InnerCreatorContext):
def enterArrayCreatorRest(self, ctx:JavaParser.ArrayCreatorRestContext):
def exitArrayCreatorRest(self, ctx:JavaParser.ArrayCreatorRestContext):
def enterClassCreatorRest(self, ctx:JavaParser.ClassCreatorRestContext):
def exitClassCreatorRest(self, ctx:JavaParser.ClassCreatorRestContext):
def enterExplicitGenericInvocation(self, ctx:JavaParser.ExplicitGenericInvocationContext):
def exitExplicitGenericInvocation(self, ctx:JavaParser.ExplicitGenericInvocationContext):
def enterTypeArgumentsOrDiamond(self, ctx:JavaParser.TypeArgumentsOrDiamondContext):
def exitTypeArgumentsOrDiamond(self, ctx:JavaParser.TypeArgumentsOrDiamondContext):
def enterNonWildcardTypeArgumentsOrDiamond(self, ctx:JavaParser.NonWildcardTypeArgumentsOrDiamondContext):
def exitNonWildcardTypeArgumentsOrDiamond(self, ctx:JavaParser.NonWildcardTypeArgumentsOrDiamondContext):
def enterNonWildcardTypeArguments(self, ctx:JavaParser.NonWildcardTypeArgumentsContext):
def exitNonWildcardTypeArguments(self, ctx:JavaParser.NonWildcardTypeArgumentsContext):
def enterTypeList(self, ctx:JavaParser.TypeListContext):
def exitTypeList(self, ctx:JavaParser.TypeListContext):
def enterTypeType(self, ctx:JavaParser.TypeTypeContext):
def exitTypeType(self, ctx:JavaParser.TypeTypeContext):
def enterPrimitiveType(self, ctx:JavaParser.PrimitiveTypeContext):
def exitPrimitiveType(self, ctx:JavaParser.PrimitiveTypeContext):
def enterTypeArguments(self, ctx:JavaParser.TypeArgumentsContext):
def exitTypeArguments(self, ctx:JavaParser.TypeArgumentsContext):
def enterSuperSuffix(self, ctx:JavaParser.SuperSuffixContext):
def exitSuperSuffix(self, ctx:JavaParser.SuperSuffixContext):
def enterExplicitGenericInvocationSuffix(self, ctx:JavaParser.ExplicitGenericInvocationSuffixContext):
def exitExplicitGenericInvocationSuffix(self, ctx:JavaParser.ExplicitGenericInvocationSuffixContext):
def enterArguments(self, ctx:JavaParser.ArgumentsContext):
def exitArguments(self, ctx:JavaParser.ArgumentsContext):

Recommended Posts

Analysieren von Java-Quellcode mit AST (Abstract Syntax Tree) mithilfe von ANTLR und Python
So erstellen Sie eine Python- und Jupyter-Ausführungsumgebung mit VSCode
MessagePack-Versuchen Sie, Java und Python mit RPC zu verbinden
Strategie zur Monetarisierung mit Python Java
Compiler in Python: PL / 0 Abstract Syntax Tree (AST)
So erstellen Sie ein Python-Paket mit VS Code
[Python] Wie man mit Klassenvariablen mit Dekorator und Metaklasse spielt
[Python / Ruby] Mit Code verstehen Wie man Daten aus dem Internet abruft und in CSV schreibt
So aktualisieren Sie FC2-Blogs usw. mithilfe von XMLRPC mit Python
PyArmor ~ Einfache Möglichkeit, Python-Quellcode zu verschlüsseln und bereitzustellen ~
So melden Sie sich mit Python bei AtCoder an und senden automatisch
Erste Schritte mit Pythons Ast-Modul (Folgen des abstrakten Syntaxbaums)
So erhalten Sie mithilfe der Mastodon-API Follower und Follower von Python
So erstellen Sie eine Überwachungskamera (Überwachungskamera) mit Opencv und Python
Herstellen einer Verbindung zum Cloud Firestore über Google Cloud-Funktionen mit Python-Code
Umgang mit Fehlern bei der Installation von Python und Pip mit Choco
So aktualisieren Sie eine in Tableau gepackte Arbeitsmappen-Datenquelle mit Python
So zeigen Sie Bytes in Java und Python auf die gleiche Weise an
So installieren Sie Python mit Anaconda
Python: So verwenden Sie Async mit
[Einführung in Python] So analysieren Sie JSON
Erste Schritte mit Python
So berechnen Sie das Datum mit Python
[Circuit x Python] So erweitern und berechnen Sie Übertragungsfunktionen mit Lcapy
[Einführung in Python] So beurteilen Sie die Authentizität mit der if-Anweisung (True und None)
Umgang mit OAuth2-Fehlern bei Verwendung von Google APIs aus Python
So ermitteln Sie mit Python den Unterschied zwischen Datum und Uhrzeit in Sekunden
Python-Code zum Trainieren und Testen mit Custom Vision of Cognitive Service
So suchen Sie mit Pythons Astroquery und erhalten passende Bilder mit Skyview
So generieren Sie QR-Code und Barcode in Python und lesen ihn normal oder in Echtzeit mit OpenCV
So verpacken und verteilen Sie Python-Skripte
Von Python bis zur Verwendung von MeCab (und CaboCha)
Verwenden von Python und MeCab mit Azure Databricks
Unterschiede zwischen Python- und Java-Syntax
Fraktal zum Erstellen und Spielen mit Python
So arbeiten Sie mit BigQuery in Python
Wie man einen Taschentest mit Python macht
So zeigen Sie Python-Japanisch mit Lolipop an
Python: Verwendung von Einheimischen () und Globalen ()
Wie man mit Python-Flüchen Japanisch eingibt
[Python] Berechnen von MAE und RMSE
Verwendung von Python zip und Aufzählung
Ich verwende Tox und Python 3.3 mit Travis-CI
Verwendung ist und == in Python
So installieren Sie Python3 mit Docker Centos
So starten Sie das Python-Projekt im Jahr 2020 (Windows WSL und Mac Common)
Drei Dinge, von denen ich süchtig war, als ich Python und MySQL mit Docker verwendete
Verwendung von OAuth und API für Dienstkonten mit Google API Client für Python
Unterschiede beim Schreiben von externem Quellcode zwischen Ruby und Python
[Python] So erstellen Sie eine lokale Webserverumgebung mit SimpleHTTPServer und CGIHTTPServer
Hochladen mit Heroku, Flask, Python, Git (4)
Lesen einer CSV-Datei mit Python 2/3
Kratzen Sie das Essen mit Python und geben Sie es an CSV aus
Wie man Spaß am Programmieren mit Minecraft hat (Ruby, Python)
[REAPER] Wie man Reascript mit Python spielt