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))))
Était-ce utile?

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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top