J'ai créé un analyseur de phrases simple à utiliser dans mon propre programme de console Java. Pour l'analyse de phrases, il est plus facile d'utiliser diverses bibliothèques, mais comme il est utilisé sur le lieu de travail où le téléchargement à partir de sites externes est interdit, je l'ai créé à partir de zéro en utilisant la fonction Java8 que j'ai.
En le créant, je me réfère à Implémentation d'une analyse de phrase simple en Java.
Tout d'abord, les exigences pour l'analyseur de phrases à créer.
--Implémenter uniquement les fonctions Java 8.
Comme il n'est pas utilisé pour l'analyse syntaxique d'un langage de programme à part entière, seule une simple analyse de phrase (à peu près à mi-chemin entre la ligne de commande Windows et le shell Unix) est effectuée.
Implémenté uniquement des symboles à une lettre et des chaînes pouvant être des jetons.
Veuillez noter qu'il s'agit d'un style oléore qui s'écarte de la description générale de Java. Il y a les raisons suivantes.
Tout d'abord, je vais vous montrer le texte complet de la classe de jeton de base.
Token.java
package console;
final class Token {
enum Kinds {
Unknown,
Empty,
Ampersand, // "&"
Assign, // "="
Plus, // "+"
Minus, // "-"
Asterisk, // "*"
Slash, // "/"
Separator, // ","ou caractère vide
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_; }
//Que faire si vous faites une erreur et que le symbole est passé sous forme de chaîne
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_;
}
C'est une source courte, donc je ne pense pas qu'il soit nécessaire de l'expliquer, mais ~~ Je l'oublierai ~~ Je vais expliquer brièvement chaque partie de la source.
Enregistrez le type de jeton dans le type d'énumération. Il s'agit d'un marqueur qui sera utilisé dans une analyse syntaxique ultérieure, de sorte que les caractères et les éléments ne doivent pas nécessairement avoir une correspondance biunivoque.
enum Kinds {
Unknown,
Empty,
Ampersand, // "&"
Assign, // "="
Plus, // "+"
//Omis en chemin
String,
}
Utilisez la méthode de fabrique pour créer un jeton pour le symbole. À partir de l'analyseur de phrases, le type de caractère lu (type char) est transmis directement pour le séparer de la fabrique de jetons de chaîne de caractères. Si un caractère qui ne peut pas être intercepté par l'instruction switch est passé, le jeton inconnu créé à l'avance est renvoyé. Étant donné que Token est un objet immuable, son contenu ne peut pas être modifié. Par conséquent, vous pouvez réutiliser les objets pré-créés en toute confiance. Comme mentionné ci-dessus, il n'y a pas de correspondance univoque entre les types d'énumération et les caractères: virgules et espaces. (Les deux sont créés en tant que Kinds.Separator)
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
Vient ensuite la méthode de fabrique de jetons de chaîne. Il s'agit d'un analyseur de phrases qui lit jusqu'à la fin de la chaîne, puis la transmet à l'usine, donc contrairement au jeton de symbole, il est surchargé pour accepter un argument String. Si une chaîne de caractères vide (y compris une chaîne de caractères avec uniquement des espaces) ou null est passée, le jeton vide créé à l'avance est renvoyé. Cela évite une vérification supplémentaire des erreurs sur l'appelant. Le symbole à une lettre est censé être passé en type char, mais comme assurance lorsqu'il est passé en type chaîne, si la chaîne transmise ne contient qu'un seul caractère, la fabrique du jeton de symbole est appelée. .. Dans le cas d'une chaîne de caractères qui ne peut pas être prise en charge par la fabrique de jetons de symboles, un jeton inconnu est renvoyé, donc dans ce cas, créez-le à nouveau en tant que jeton de chaîne de caractères.
De plus, bien que l'explication soit mélangée, le constructeur est déclaré privé de sorte que l'objet est créé uniquement via la méthode factory.
static Token create(String s) {
if ( s == null || s.trim().isEmpty() ) { return empty_; }
//Que faire si vous faites une erreur et que le symbole est passé sous forme de chaîne
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
Il existe deux types de jetons: un type d'élément énuméré et une représentation sous forme de chaîne de l'élément ("Plus" est renvoyé pour kinds.Plus).
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());
}
C'est la fin de l'explication de la classe de jeton.
En fait, j'ai augmenté le nombre de jetons de symboles du programme que j'ai créé, mais même à ce niveau, j'ai trouvé ennuyeux de synchroniser le type d'énumération et l'instruction de commutation d'usine. J'ai pensé à remodeler cette partie à des fins générales, mais en raison du temps et des efforts nécessaires pour augmenter le nombre de cours, j'ai décidé de renoncer à cette fois.
La prochaine fois, ce sera le corps principal de l'analyseur de phrases.
→ Création d'une analyse de phrase avec Java 8 (Partie 2) Publié.
Recommended Posts