JavaCC Problème - Le code généré ne trouve pas toutes les erreurs d'analyse
-
19-09-2019 - |
Question
Tout a commencé avec JavaCC. Mais j'ai un comportement étrange avec elle. Je veux vérifier l'entrée int la forme de jetons (lettres et chiffres) sont Wich concaténé avec des signes (+, -, /) et Wich peut contenir entre parenthèses. J'espère que était compréhensible:)
Dans la principale méthode est une chaîne, qui devrait produire une erreur, car il a une ouverture, mais deux parenthèse fermante, mais je ne suis pas une exception parse -> Pourquoi
Quelqu'un at-il la moindre idée pourquoi je ne comprends pas l'exception?
Je luttais avec des conflits de gauche et de récursion choix avec mon essai initial, mais a réussi à obtenir sur eux. Peut-être que j'introduit le problème?!
Oh - et peut-être ma solution est pas très bon - ignorer ce fait ... ou mieux, donner quelques conseils ;-)
Fichier: CodeParser.jj
options {
STATIC=false;
}
PARSER_BEGIN(CodeParser)
package com.testing;
import java.io.StringReader;
import java.io.Reader;
public class CodeParser {
public CodeParser(String s)
{
this((Reader)(new StringReader(s)));
}
public static void main(String args[])
{
try
{
/** String has one open, but two closing parenthesis --> should produce parse error */
String s = "A+BC+-(2XXL+A/-B))";
CodeParser parser = new CodeParser(s);
parser.expression();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
PARSER_END(CodeParser)
TOKEN:
{
<code : ("-")?(["A"-"Z", "0"-"9"])+ >
| <op : ("+"|"/") >
| <not : ("-") >
| <lparenthesis : ("(") >
| <rparenthesis : (")") >
}
void expression() :
{
}
{
negated_expression() | parenthesis_expression() | LOOKAHEAD(2) operator_expression() | <code>
}
void negated_expression() :
{
}
{
<not>parenthesis_expression()
}
void parenthesis_expression() :
{
}
{
<lparenthesis>expression()<rparenthesis>
}
void operator_expression() :
{
}
{
<code><op>expression()
}
Edition - 16/11/2009
Maintenant, j'ai donné ANTLR essayer.
J'ai changé quelques termes pour mieux correspondre à mon domaine de problème. Je suis venu avec le code suivant (en utilisant les réponses sur ce site), qui semble faire le travail maintenant:
grammar Code;
CODE : ('A'..'Z'|'0'..'9')+;
OP : '+'|'/';
start : terms EOF;
terms : term (OP term)*;
term : '-'? CODE
| '-'? '(' terms ')';
Et la façon ... ANTLRWORKS est un excellent outil pour le débogage / visualisant! m'a beaucoup aidé.
Informations complémentaires
Au-dessus correspond à un code des choses comme:
(-Z19+-Z07+((FV+((M005+(M272/M276))/((M278/M273/M642)+-M005)))/(FW+(M005+(M273/M278/M642)))))+(-Z19+-Z07+((FV+((M005+(M272/M276))/((M278/M273/M642/M651)+-M005)))/(FW+(M0))))
La solution
Qu'est-ce que kgregory dit est la bonne réponse. Vous pouvez le voir si vous construisez la grammaire avec l'option DEBUG_PARSER puis exécutez-le:
$ javacc -debug_parser -output_directory=com/testing/ CodeParser.jj && javac com/testing/*.java && java -cp . com.testing.CodeParser Java Compiler Compiler Version 5.0 (Parser Generator) (type "javacc" with no arguments for help) Reading from file CodeParser.jj . . . File "TokenMgrError.java" is being rebuilt. File "ParseException.java" is being rebuilt. File "Token.java" is being rebuilt. File "SimpleCharStream.java" is being rebuilt. Parser generated successfully. Call: expression Call: operator_expression Consumed token: <<code>: "A" at line 1 column 1> Consumed token: <<op>: "+" at line 1 column 2> Call: expression Call: operator_expression Consumed token: <<code>: "BC" at line 1 column 3> Consumed token: <<op>: "+" at line 1 column 5> Call: expression Call: negated_expression Consumed token: <"-" at line 1 column 6> Call: parenthesis_expression Consumed token: <"(" at line 1 column 7> Call: expression Call: operator_expression Consumed token: <<code>: "2XXL" at line 1 column 8> Consumed token: <<op>: "+" at line 1 column 12> Call: expression Call: operator_expression Consumed token: <<code>: "A" at line 1 column 13> Consumed token: <<op>: "/" at line 1 column 14> Call: expression Consumed token: <<code>: "-B" at line 1 column 15> Return: expression Return: operator_expression Return: expression Return: operator_expression Return: expression Consumed token: <")" at line 1 column 17> Return: parenthesis_expression Return: negated_expression Return: expression Return: operator_expression Return: expression Return: operator_expression Return: expression
Voir cela? Le dernier jeton consommé est le deuxième dernier caractère - la deuxième à la dernière parenthèse.
Si vous voulez que l'exception, encore une fois, comme kgregory dit, vous pouvez ajouter une nouvelle production de haut niveau appelé « fichier » ou « données » ou quelque chose et à la fin avec un jeton. De cette façon, tout ballants parens comme cela provoquerait une erreur. Voici une grammaire qui fait que:
options { STATIC=false; } PARSER_BEGIN(CodeParser) package com.testing; import java.io.StringReader; import java.io.Reader; public class CodeParser { public CodeParser(String s) { this((Reader)(new StringReader(s))); } public static void main(String args[]) { try { /** String has one open, but two closing parenthesis --> should produce parse error */ String s = "A+BC+-(2XXL+A/-B))"; CodeParser parser = new CodeParser(s); parser.file(); } catch(Exception e) { e.printStackTrace(); } } } PARSER_END(CodeParser) TOKEN: { <code : ("-")?(["A"-"Z", "0"-"9"])+ > | <op : ("+"|"/") > | <not : ("-") > | <lparenthesis : ("(") > | <rparenthesis : (")") > } void file() : {} { expression() <EOF> } void expression() : { } { negated_expression() | parenthesis_expression() | LOOKAHEAD(2) operator_expression() | <code> } void negated_expression() : { } { <not>parenthesis_expression() } void parenthesis_expression() : { } { <lparenthesis>expression()<rparenthesis> } void operator_expression() : { } { <code><op>expression() }
Et une course exemple:
$ javacc -debug_parser -output_directory=com/testing/ CodeParser.jj && javac com/testing/*.java && java -cp . com.testing.CodeParser Java Compiler Compiler Version 5.0 (Parser Generator) (type "javacc" with no arguments for help) Reading from file CodeParser.jj . . . File "TokenMgrError.java" is being rebuilt. File "ParseException.java" is being rebuilt. File "Token.java" is being rebuilt. File "SimpleCharStream.java" is being rebuilt. Parser generated successfully. Call: file Call: expression Call: operator_expression Consumed token: <<code>: "A" at line 1 column 1> Consumed token: <<op>: "+" at line 1 column 2> Call: expression Call: operator_expression Consumed token: <<code>: "BC" at line 1 column 3> Consumed token: <<op>: "+" at line 1 column 5> Call: expression Call: negated_expression Consumed token: <"-" at line 1 column 6> Call: parenthesis_expression Consumed token: <"(" at line 1 column 7> Call: expression Call: operator_expression Consumed token: <<code>: "2XXL" at line 1 column 8> Consumed token: <<op>: "+" at line 1 column 12> Call: expression Call: operator_expression Consumed token: <<code>: "A" at line 1 column 13> Consumed token: <<op>: "/" at line 1 column 14> Call: expression Consumed token: <<code>: "-B" at line 1 column 15> Return: expression Return: operator_expression Return: expression Return: operator_expression Return: expression Consumed token: <")" at line 1 column 17> Return: parenthesis_expression Return: negated_expression Return: expression Return: operator_expression Return: expression Return: operator_expression Return: expression Return: file com.testing.ParseException: Encountered " ")" ") "" at line 1, column 18. Was expecting: <EOF> at com.testing.CodeParser.generateParseException(CodeParser.java:354) at com.testing.CodeParser.jj_consume_token(CodeParser.java:238) at com.testing.CodeParser.file(CodeParser.java:34) at com.testing.CodeParser.main(CodeParser.java:22)
Voila! Une exception.
Autres conseils
De la Java CC FAQ :
4.7 J'ai ajouté une spécification LookAhead et l'avertissement partais; est-ce que cela signifie que je résolu le problème?
Non. JavaCC ne rapportera pas les avertissements de conflit de choix si vous utilisez une spécification LookAhead. absence d'un avertissement ne signifie pas que vous avez résolu le problème correctement, il signifie simplement que vous avez ajouté une spécification LookAhead .
Je commencerais en essayant de se débarrasser du conflit sans utiliser d'abord préanalyse.
Le problème est que vous ne recevez pas l'erreur lors de l'utilisation de l'analyseur, correct? Non que le générateur d'analyseur prétend que la grammaire est incorrecte (qui semble être la discussion dans l'autre réponse).
Si tel est le cas, alors je pense que vous voyez le problème parce que l'analyseur correspond correctement expression la production, ne tient pas compte alors entrée ultérieure. Je ne l'ai pas utilisé JavaCC depuis longtemps, mais IIRC il ne génère pas d'erreur pour ne pas atteindre la fin du cours d'eau.
La plupart ont une production grammaires de haut niveau explicite pour correspondre au fichier entier, en regardant quelque chose comme ça (je suis sûr que la syntaxe est erronée, comme je l'ai dit, il a été longtemps):
input : ( expression ) *
Ou, il y a probablement un jeton EOF que vous pouvez utiliser, si vous voulez traiter une seule expression.