évaluateur d'expression récursive en utilisant Java
-
28-09-2019 - |
Question
Je vais écrire un évaluateur d'expression qui ne fait que l'addition et la soustraction. J'ai un algorithme simple à faire; mais, j'ai des problèmes de mise en œuvre.
Je considérais une expression comme (il est une chaîne)
"(" <expression1> <operator> <expression2> ")"
Voici mon algorithme
String evaluate( String expression )
if expression is digit
return expression
else if expression is "(" <expression1> <operator> <expression2> ")"
cut the brackets out of it
expression1 = evaluate( <expression1> )
operator = <operator>
expression2 = evaluate( <expression2> )
if operator is +
expression1 + expression2
else if operator is -
expression1 - expression2
Mon problème est l'analyse <expression1>
, <operator>
et <expression2>
de l'expression. Comment puis je faire ça?
Note: Je ne demande pas un code. Tout ce que je besoin est une idée de le faire.
Merci,
-Ali
La solution
Mon problème est parsing
, Opérateur <> et de la expression
Ne pas faire cela, alors :) Quand vous voyez un support d'ouverture, faites votre appel récursif à l'expression. A la fin de l'expresssion, que ce soit vous trouvez un autre opérateur (et donc vous n'êtes pas à la fin de l'expression après tout), ou un droit support, auquel cas vous revenez de l'évaluer.
Autres conseils
Soit vous utilisez un générateur d'analyseurs tels que JavaCUP ou ANTLR . Rédiger une BNF de votre expression et générer un analyseur. Voici une grammaire exemple qui vous aider à démarrer:
Expression ::= Digit
| LeftBracket Expression Plus Expression RightBracket
| LeftBracket Expression Minus Expression RightBracket
| LeftBracket Expression RightBracket
Une façon de le faire vous-même serait de chercher la première )
backtrack à l'aspect le plus proche de (
« aki » à la parenthèse libre expression entre les deux, tout simplement divisé sur les symboles de l'opérateur et d'évaluer.
Je recommande de changer l'entrée infix dans Postfix, puis l'évaluer, plutôt que de réduire l'expression infix sage. Il existe déjà des algorithmes bien définis pour cela et il ne vient pas avec les imbrications multiples-parenthèses inhérentes d'analyse syntaxique des problèmes.
Jetez un oeil à la algorithme de triage pour convertir postfix / RPN puis évaluer à l'aide d'une pile en utilisant Postfix opérations . C'est rapide (O (n)) et fiable.
HTH
Utilisez un StringTokenizer pour diviser votre chaîne d'entrée en parenthèses, les opérateurs et les numéros, puis itérer sur vos jetons, en faisant un appel récursif pour tous ouverts parens, et en sortant de votre méthode pour chaque parenthèse fermante.
Je sais que vous n'avez pas demandé le code, mais cela fonctionne pour l'entrée valide:
public static int eval(String expr) {
StringTokenizer st = new StringTokenizer(expr, "()+- ", true);
return eval(st);
}
private static int eval(StringTokenizer st) {
int result = 0;
String tok;
boolean addition = true;
while ((tok = getNextToken(st)) != null) {
if (")".equals(tok))
return result;
else if ("(".equals(tok))
result = eval(st);
else if ("+".equals(tok))
addition = true;
else if ("-".equals(tok))
addition = false;
else if (addition)
result += Integer.parseInt(tok);
else
result -= Integer.parseInt(tok);
}
return result;
}
private static String getNextToken(StringTokenizer st) {
while (st.hasMoreTokens()) {
String tok = st.nextToken().trim();
if (tok.length() > 0)
return tok;
}
return null;
}
Il aurait besoin d'une meilleure gestion des entrées invalides, mais vous voyez l'idée ...
Je suggère de prendre une approche qui ressemble plus à celui décrit dans cette ancienne, mais (en mon avis) de la série d'articles pertinents sur la conception du compilateur. Je trouve que l'approche de l'utilisation de petites fonctions / méthodes que les parties parse de l'expression très efficace.
Cette approche vous permet de décomposer votre méthode d'analyse en plusieurs sous-méthodes dont le nom et l'ordre d'exécution suit de près la EBNF vous pouvez utiliser pour décrire les expressions à analyser.
Peut-être créer des expressions régulières pour expression et opérateur et utiliser ensuite correspondant pour identifier et briser votre contenu.