Frage

begann einfach mit JavaCC. Aber ich habe ein seltsames Verhalten mit ihm. Ich mag Eingabe von Zeichen (Buchstaben und Zahlen) int Form überprüfen Weichen mit Zeichen verkettet (+, -, /) und Weichen Klammern enthalten. Ich hoffe, das war verständlich:)

In der Haupt-Methode ist eine Zeichenfolge, die einen Fehler erzeugen sollen, weil es eine Öffnung, sondern zwei schließende Klammer, aber ich habe keine Parse Ausnahme erhalten -> Warum

Hat jemand eine Ahnung, warum ich nicht die Ausnahme bekommen Sie?

Ich kämpfe mit dem linken Rekursion und Wahl Konflikten mit meinem ersten Versuch, aber geschaffen, über sie zu bekommen. Vielleicht gibt eingeführt ich das Problem?!

Oh - und vielleicht ist meine Lösung nicht sehr gut - diese Tatsache ignorieren ... oder besser, einen Rat geben ;-)

Datei: 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()
 }

Bearbeiten - 11/16/2009

Nun gab ich ANTLR versuchen.

änderte ich einige Begriffe besser zu meinem Problem Domain entsprechen. Ich kam mit dem folgenden Code (mit den Antworten auf dieser Seite) auf, die die Arbeit jetzt zu tun scheint:

grammar Code;

CODE    :   ('A'..'Z'|'0'..'9')+;
OP  :   '+'|'/';

start   :   terms EOF;
terms   :   term (OP term)*;
term    :   '-'? CODE
    |   '-'? '(' terms ')';

Und übrigens ... ANTLRWorks ist ein großes Werkzeug für die Fehlersuche / Visualisierung! Hat mir sehr geholfen.

Weitere Informationen
Above-Code übereinstimmt Sachen wie:

(-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))))
War es hilfreich?

Lösung

Was kgregory sagt, ist die richtige Antwort. Sie können das sehen, wenn Sie die Grammatik mit der DEBUG_PARSER Option bauen und sie dann ausführen:

$ 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

Sehen Sie das? Der letzte Token verbraucht ist die zweite zum letzten Zeichen - die zweitletzte rechten Klammer.

Wenn Sie die Ausnahme wollen, wieder, wie kgregory sagte, eine neue Top-Level-Produktion „Datei“ oder „Daten“ oder etwas und lassen Sie ihn mit einem Token genannt hinzufügen könnte. Auf diese Weise alle baumelnden Pars wie dies würde einen Fehler verursachen. Hier ist eine Grammatik, die das tut:

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()
}

Und ein Probelauf:

$ 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! Eine Ausnahme.

Andere Tipps

Von dem Java CC FAQ

4.7 Ich habe Eine vorwärts Spezifikation und die Warnung ging weg; heißt das ich das Problem behoben?

Nein. JavaCC nicht Wahl Konflikt Warnungen melden, wenn Sie Eine vorwärts Spezifikation verwenden. Die Fehlen einer Warnung bedeutet nicht, dass Sie das Problem richtig gelöst haben, ist es nur bedeutet, dass Sie hinzugefügt Eine vorwärts Spezifikation .

ich anfangen würde, indem sie versuchen, loszuwerden, den Konflikt zu kommen, ohne zunächst einen Look-Ahead verwendet wird.

Das Problem ist, dass Sie nicht den Fehler, wenn der Parser verwenden, richtig? Nicht, dass der Parser-Generator wird behauptet, dass die Grammatik falsch ist (was die Diskussion in der anderen Antwort zu sein scheint).

Wenn das der Fall ist, dann vermute ich, dass Sie das Problem sind zu sehen, weil der Parser richtig paßt die Ausdruck Produktion, dann nachfolgende Eingabe ignoriert. Ich habe nicht JavaCC für längere Zeit nicht benutzt, aber iirc hat es nicht einen Fehler für nicht erreicht End-of-Stream werfen.

Die meisten Grammatiken haben eine explizite Top-Level-Produktion die gesamte Datei entsprechen, so etwas wie folgt aussehen (ich bin sicher, dass die Syntax falsch ist, wie gesagt, es war eine lange Zeit):

input : ( expression ) *

Oder gibt es wahrscheinlich ein EOF-Token, das Sie verwenden können, wenn Sie nur einen einzigen Ausdruck bearbeiten wollen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top