Erstellen einer Phrasenanalyse in Java 8 (Teil 1)

Einführung

Ich habe einen einfachen Phrasenanalysator zur Verwendung in meinem eigenen Java-Konsolenprogramm erstellt. Für die Phrasenanalyse ist es einfacher, verschiedene Bibliotheken zu verwenden. Da sie jedoch am Arbeitsplatz verwendet werden, an dem das Herunterladen von externen Websites verboten ist, habe ich sie mit meiner Java8-Funktion von Grund auf neu erstellt.

Beim Erstellen verweise ich auf Implementieren einer einfachen Phrasenanalyse in Java.

wichtiger Punkt

Bedarf

Zunächst müssen die Anforderungen für den Phrasenanalysator erstellt werden.

Programmstil

Bitte beachten Sie, dass es sich um einen Oleore-Stil handelt, der von der allgemeinen Beschreibung von Java abweicht. Es gibt die folgenden Gründe.

Token.java


package console;

final class Token {
    enum Kinds {
        Unknown,
        Empty,
        Ampersand,          // "&"
        Assign,             // "="
        Plus,               // "+"
        Minus,              // "-"
        Asterisk,           // "*"
        Slash,              // "/"
        Separator,          // ","
        LeftParenthesis,    // "("
        RightParenthesis,   // ")"
        LeftCurlyBracket,   // "{"
        RightCurlyBracket,  // "}"
        LeftSquareBracket,  // "["
        RightSquareBracket, // "]"
        Colon,              // ":"
        BackSlash,          // "\"
        DoubleQuote,        // """
        SingleQuote,        // "'"
        String,
    }

    static Token create(char c) {
        final String s = Character.toString(c);
        switch(c) {
            case '&'  : return new Token(s, Kinds.Ampersand         );
            case '='  : return new Token(s, Kinds.Assign            );
            case '+'  : return new Token(s, Kinds.Plus              );
            case '-'  : return new Token(s, Kinds.Minus             );
            case '*'  : return new Token(s, Kinds.Asterisk          );
            case '/'  : return new Token(s, Kinds.Slash             );
            case ','  : // down through
            case ' '  : return new Token(s, Kinds.Separator         );
            case '('  : return new Token(s, Kinds.LeftParenthesis   );
            case ')'  : return new Token(s, Kinds.RightParenthesis  );
            case '{'  : return new Token(s, Kinds.LeftCurlyBracket  );
            case '}'  : return new Token(s, Kinds.RightCurlyBracket );
            case '['  : return new Token(s, Kinds.LeftSquareBracket );
            case ']'  : return new Token(s, Kinds.RightSquareBracket);
            case ':'  : return new Token(s, Kinds.Colon             );
            case '\\' : return new Token(s, Kinds.BackSlash         );
            case '\"' : return new Token(s, Kinds.DoubleQuote       );
            case '\'' : return new Token(s, Kinds.SingleQuote       );
        }
        return unknown_;
    }

    static Token create(String s) {
        if ( s == null  ||  s.trim().isEmpty() ) { return empty_; }
        //
        if ( s.length() == 1 ) {
            Token t = Token.create(s.charAt(0));
            if ( t.kind() != Kinds.Unknown ) { return t; }
        }
        return new Token(s.trim(), Kinds.String);
    }

    final String value()     { return value_; }
    final Kinds  kind()      { return kind_; }
    final String kindName()  { return kind_.toString(); }
    public String toString() {
        return String.format("[%-14s: \"%s\"]", kindName(), value());
    }

    private Token(String s, Kinds k) {
        kind_  = k;
        value_ = s;
    }

    private static Token empty_   = new Token("", Kinds.Empty);                // empty token
    private static Token unknown_ = new Token("**Unknown**", Kinds.Unknown);   // unknown token

    private final Kinds  kind_;
    private final String value_;
}

Token-Klasse Zuerst wird der vollständige Text der grundlegenden Token-Klasse angezeigt. oder Leerzeichen Was tun, wenn ein Symbol versehentlich als Zeichenfolge übergeben wird? Es handelt sich um eine kurze Quelle, daher halte ich es für unnötig, dies zu erklären, aber ~~ ich werde es vergessen ~~ Ich werde jeden Teil der Quelle kurz erklären.

Token-Typ

Registrieren Sie den Tokentyp im Aufzählungstyp. Dies ist eine Markierung, die in späteren Syntaxanalysen verwendet wird, sodass die Zeichen und Elemente nicht unbedingt eine Eins-zu-Eins-Entsprechung aufweisen müssen.

    enum Kinds {
        Unknown,
        Empty,
        Ampersand,          // "&"
        Assign,             // "="
        Plus,               // "+"
        //Unterwegs weggelassen
        String,
    }

Fabrikmethode

Verwenden Sie die Factory-Methode, um ein Token für das Symbol zu erstellen. Vom Phrasenanalysator wird der gelesene Zeichentyp (Zeichentyp) direkt übergeben, um ihn von der Zeichenfolgen-Token-Factory zu trennen. Wenn ein Zeichen übergeben wird, das von der switch-Anweisung nicht abgefangen werden kann, wird das zuvor erstellte unbekannte Token zurückgegeben. Da Token ein unveränderliches Objekt ist, kann sein Inhalt nicht geändert werden. Daher können Sie die vorab erstellten Objekte sicher wiederverwenden. Wie oben erwähnt, gibt es keine Eins-zu-Eins-Entsprechung zwischen Aufzählungstypen und Zeichen: Kommas und Leerzeichen. (Beide werden als Kinds.Separator erstellt.)

    static Token create(char c) {
        final String s = Character.toString(c);
        switch(c) {
            case '&'  : return new Token(s, Kinds.Ampersand         );
            case '='  : return new Token(s, Kinds.Assign            );
            case '+'  : return new Token(s, Kinds.Plus              );
            case '-'  : return new Token(s, Kinds.Minus             );
            case '*'  : return new Token(s, Kinds.Asterisk          );
            case '/'  : return new Token(s, Kinds.Slash             );
            case ','  : // down through
            case ' '  : return new Token(s, Kinds.Separator         );
            case '('  : return new Token(s, Kinds.LeftParenthesis   );
            case ')'  : return new Token(s, Kinds.RightParenthesis  );
            case '{'  : return new Token(s, Kinds.LeftCurlyBracket  );
            case '}'  : return new Token(s, Kinds.RightCurlyBracket );
            case '['  : return new Token(s, Kinds.LeftSquareBracket );
            case ']'  : return new Token(s, Kinds.RightSquareBracket);
            case ':'  : return new Token(s, Kinds.Colon             );
            case '\\' : return new Token(s, Kinds.BackSlash         );
            case '\"' : return new Token(s, Kinds.DoubleQuote       );
            case '\'' : return new Token(s, Kinds.SingleQuote       );
        }
        return unknown_;
    }

    private static Token unknown_ = new Token("**Unknown**", Kinds.Unknown);   // unknown token

Als nächstes folgt die Factory-Methode für String-Token. Dies ist ein Phrasenanalysator, der bis zum Ende des Strings liest und ihn dann an die Factory weiterleitet. Im Gegensatz zum Symbol-Token ist er also überladen, um ein String-Argument anzunehmen. Wenn eine leere Zeichenfolge (einschließlich einer Zeichenfolge mit nur Leerzeichen) oder null übergeben wird, wird das zuvor erstellte leere Token zurückgegeben. Dies vermeidet zusätzliche Fehlerprüfungen beim Anrufer. Das Ein-Buchstaben-Symbol soll im Zeichen-Typ übergeben werden. Wenn die übergebene Zeichenfolge jedoch nur als Zeichen besteht, wird die Fabrik des Symbol-Tokens aufgerufen, wenn sie als Zeichenfolge übergeben wird. .. Bei einer Zeichenfolge, die von der Symbol-Token-Factory nicht unterstützt werden kann, wird ein unbekanntes Token zurückgegeben. Erstellen Sie es in diesem Fall erneut als Zeichenfolgen-Token.

Obwohl die Erklärung verwechselt ist, wird der Konstruktor außerdem als privat deklariert, sodass das Objekt nur über die Factory-Methode erstellt wird.

    static Token create(String s) {
        if ( s == null  ||  s.trim().isEmpty() ) { return empty_; }
        //Was tun, wenn Sie einen Fehler machen und das Symbol als Zeichenfolge übergeben wird?
        if ( s.length() == 1 ) {
            Token t = Token.create(s.charAt(0));
            if ( t.kind() != Kinds.Unknown ) { return t; }
        }
        return new Token(s.trim(), Kinds.String);
    }

    private Token(String s, Kinds k) {
        kind_  = k;
        value_ = s;
    }

    private static Token empty_   = new Token("", Kinds.Empty);                // empty token

Anfrage

Es gibt zwei Arten von Token: einen aufgezählten Elementtyp und eine Zeichenfolgendarstellung des Elements ("kind" wird für kinds.Plus zurückgegeben).

    final String value()     { return value_; }
    final Kinds  kind()      { return kind_; }
    final String kindName()  { return kind_.toString(); }

    public String toString() {
        return String.format("[%-14s: \"%s\"]", kindName(), value());
    }

Zusammenfassung

Dies ist das Ende der Erklärung der Token-Klasse.

Eigentlich habe ich die Anzahl der Symbol-Token aus dem tatsächlich erstellten Programm erhöht, aber selbst auf dieser Ebene fand ich es ärgerlich, den Aufzählungstyp und die Factory-Switch-Anweisung zu synchronisieren. Ich habe darüber nachgedacht, diesen Teil für allgemeine Zwecke umzugestalten, aber ich habe mich entschlossen, auf diese Zeit zu verzichten, da es aus Zeitgründen schwierig ist, die Anzahl der Klassen zu erhöhen.

Das nächste Mal wird es der Hauptteil des Phrasenanalysators sein.

Erstellen einer Phrasenanalyse mit Java 8 (Teil 2) Gepostet.

Recommended Posts

Führen Sie eine Phrasenanalyse in Java 8 durch (Teil 2).
Erstellen einer Phrasenanalyse in Java 8 (Teil 1)
1 Implementieren Sie eine einfache Phrasenanalyse in Java
Erstellen einer Matrixklasse in Java Teil 1
Morphologische Analyse in Java mit Kuromoji
Erstellen einer Klasse für eine Matrix in Java Teil 2 - Über eine Matrix (lineare Algebra) -
Verwenden Sie OpenCV_Contrib (ArUco) mit Java! (Teil 2-Programmierung)
[Erstellen] Ein Memorandum über das Codieren in Java
Partisierung in Java
Änderungen in Java 11
Janken in Java
Java-Übung Teil 1
Umfangsrate in Java
FizzBuzz in Java
Verwenden Sie OpenCV_Contrib (ArUco) mit Java! (Teil 1-Build) (OpenCV-3.4.4)
Was ich in Java gelernt habe (Teil 2) Was sind Variablen?
NLP4J Morphologische Analyse in Java (unter Verwendung von Kuromoji)
[LeJOS] Programmieren wir mindstorm-EV3 mit Java [Umgebungskonstruktion Teil 2]
Interpreter-Implementierung durch Java
Machen Sie einen Blackjack mit Java
Janken App in Java
Einschränkungsprogrammierung in Java
Setzen Sie Java8 in Centos7
NVL-artiger Typ in Java
"Hallo Welt" in Java
Aufrufbare Schnittstelle in Java
Ein kurzer Überblick über Java, das in Klasse 4 gelernt wurde
Kommentare in der Java-Quelle
Azure funktioniert in Java
Formatieren Sie XML in Java
Einfache HTML-Spezialchars in Java
Boyer-Moore-Implementierung in Java
Verwenden Sie OpenCV mit Java
WebApi-Memorandum mit Java
Was ich in Java gelernt habe (Teil 3) Anweisung zur Ausführung von Anweisungen
Typbestimmung in Java
Befehle in Java ausführen (Ping)
Implementierung der Heap-Sortierung (in Java)
Zabbix API in Java
ASCII-Kunst in Java
Listen in Java vergleichen
POST JSON in Java
Java studieren ~ Teil 8 ~ Besetzung
Ein kurzer Überblick über Java, das in Klasse 3 gelernt wurde
Fehler in Java ausdrücken
Ein kurzer Überblick über Java, das in Klasse 2 gelernt wurde
Erstellen Sie JSON in Java
Was ist neu in Java 8?
Verwenden Sie PreparedStatement in Java
Was ist neu in Java 9,10,11
Parallele Ausführung in Java
JSON in Java und Jackson Teil 1 Gibt JSON vom Server zurück
[LeJOS] Programmieren wir mindstorm-EV3 mit Java [Umgebungskonstruktion erster Teil]
Protokollaggregation und -analyse (Arbeiten mit AWS Athena in Java)
Was ich in Java gelernt habe (Teil 4) Bedingte Verzweigung und Wiederholung
45 Techniken zur Optimierung der Java-Leistung (Teil 1)
Versuchen Sie es mit RocksDB mit Java
Lesen Sie Binärdateien in Java 1
Vermeiden Sie den Fehler, den Yuma in Java gemacht hat
Holen Sie sich EXIF-Informationen in Java