www.mikrocontroller.net

Forum: PC-Programmierung Probleme bei Java Syntaxchecker


Important announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: Kurt Tresen (kurtisblow)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Hallo,
ich habe die Aufgabe einen Syntaxchecker in Java zu programmieren,
der einen vorgegebenen J.Unit test erfolgreich absolviert.

Die Methode public static void parse(String kd) throws ParseException
ist vorgegeben, die restlichen Methoden habe ich bereits programmiert.
Ich versuche also rekursiv den Syntaxbaum zu überprüfen, jedoch erfüllt 
es mir keinen J-Unit Test:

 package u3a3;

public class KD {
  
  private static int offset = 0;
  /**
   * Parse a "Klammerdarstellung" (KD) of a tree.
   * 
   * <ul>
   * <li>An empty tree is encoded as '-'.</li>
   * <li>A node is encoded as an uppercase letter, i.e. everything accepted by {@link Character#isUpperCase(char)}.</li>
   * <li>Children are appended to the father as a ','-separated list of nodes enclosed in round brackets.</li>
   * </ul> 
   * 
   * @param kd Tree encoded in KD
   * @throws ParseException if the given String is not a valid KD of a tree.
   */
  
  public static void parse(String kd) throws ParseException
  {
    if (kd.length() > 1 && kd.charAt(0) != '-' && kd.charAt(1) != '-')
    {
    tree(kd,0);
    }
  }
  
  public static int tree(String str, int offset)
  {
    offset = follower(str, offset);
    while (str.length() > offset && str.charAt(offset) == '+'){
    offset = follower(str, offset + 1);
    }
    return offset;
  }
  
  public static int follower(String str, int offset)
  {
    offset = node(str, offset);
    while (str.length() > offset && str.charAt(offset) == '*'){
    offset = node(str, offset + 1);
    }
    return offset;
  }
  
  public static int node(String str, int offset)
  {
    while (str.length() > offset && str.charAt(offset) == '(' || str.charAt(offset) == ')'){
      offset = node(str, offset + 1);
      }
    return offset;
  }
}
 

Hier noch der JUnit test:
 package u3a3;

import org.junit.Test;

public class Tests {
  void testCase(String lkd) throws ParseException {
    KD.parse(lkd);
  }
  
  @Test public void empyTree() throws ParseException { testCase("-"); }
  @Test public void onlyRoot() throws ParseException { testCase("A"); }
  @Test public void balancedTree() throws ParseException { testCase("A(B,C)"); }
  @Test public void listLeft() throws ParseException { testCase("A(B(C,-),-)"); }
  @Test public void listLeftImplicit() throws ParseException { testCase("A(B(C))"); }
  @Test public void listRight() throws ParseException { testCase("A(-,B(-,C))"); }
  @Test public void missingSibling() throws ParseException { testCase("A(B,-,C)");}
  @Test public void noChildren() throws ParseException { testCase("A(-,-)");}
  @Test public void genericTree() throws ParseException { testCase("A(-,B(C),-,D(E(-,F(G,H)),I))"); }
  
  @Test(expected = ParseException.class)
  public void empyString() throws ParseException { testCase(""); }

  @Test(expected = ParseException.class)
  public void noChild()throws ParseException { testCase("A()"); }

  @Test(expected = ParseException.class)
  public void noSibling()throws ParseException { testCase("A(B,)"); }
  
  @Test(expected = ParseException.class)
  public void twoCommas()throws ParseException { testCase("A(B,,C)"); }

  @Test(expected = ParseException.class)
  public void missingOpenBrace()throws ParseException { testCase("AB)"); }

  @Test(expected = ParseException.class)
  public void missingCloseBrace()throws ParseException { testCase("A(B"); }

  @Test(expected = ParseException.class)
  public void missingComma()throws ParseException { testCase("A(BC)"); }
  
  @Test(expected = ParseException.class)
  public void garbage()throws ParseException { testCase("A(B)C"); }

  @Test(expected = ParseException.class)
  public void garbage2()throws ParseException { testCase("A(B)(C)"); }
  
  @Test(expected = ParseException.class)
  public void noRoot()throws ParseException { testCase("-(A)"); }

  @Test(expected = ParseException.class)
  public void invalidNode()throws ParseException { testCase("A(1)"); }

  
}
  


Vielleicht sieht jemand was ich falsch mache.

mfg Hans

Autor: Udo Schmitt (urschmitt)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Was sagt der Debugger?
Du kannst jeden Test Step für Step durchgehen und genau sehen was 
passiert.

Autor: Kurt Tresen (kurtisblow)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Ok, danke, gleich mal probieren

Autor: Läubi .. (laeubi) (Moderator) Benutzerseite
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Da du niergends eine Parseexception wirfst, der Test aber eine erwartet 
schlägt er fehl.
Was würdest du auch von einem Compiler halten welcher Kommentarlos jeden 
Unsinn aktzeptiert und keine Ausgaben macht egal ob richtig oder falsch?

Autor: Robert L. (lrlr)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
@Läubi

ich glaub nicht, dass das stimmt, was du schreibst
throws heitß ja nur dass man eine Parseexception werfen KÖNNTE
und nicht dass man das MUSS

(wird man vermutlich nur tun, wenn man das scheitern eines tests 
kommunizieren will


>von einem Compiler

ich glaub nicht, dass er ein Problem beim compilieren hat ...


@TO

class Tests {

fehlt da ein "extends" ??

Autor: Kurt Tresen (kurtisblow)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Habe nun einmal die erste methode überarbeitet:
public static void parse(String kd) throws ParseException
  {
    
    boolean exception = false;
    for (int i = 0; i<kd.length(); i++)
    {
      if (kd.charAt(i) == '(' || kd.charAt(i) == ')' || kd.charAt(i) == ',' || kd.charAt(i) == '-' || kd.charAt(i) >= 'A' && kd.charAt(i) <= 'Z')
      {
        
      } else {
        exception = true;
        i = kd.length();
        
      }
    }
    
    if (exception == false)
    {
      tree (kd,0);
    }
  }


Jetzt sollte sie zumindest eine Ausnahme erkennen, wie bringe ich das 
nun in diese Junit Test mit ein?

Autor: Kurt Tresen (kurtisblow)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Ich begreiffe einfach diesen JUnit Test nicht, ich weiss gar nicht was 
ich überhaupt erfüllen soll? Was muss ich machen, dass es mir die 
Exceptions richtig erfüllt?

Autor: Narf (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Hi,

wieso sollte eine Exception erkannt werden, wenn du exception = true; 
setzt?
Vll. solltest du erst mal nachschlagen, was Exceptions sind und wozu sie 
verwendet werden.

Anstelle von exception = true wirfst du einfach eine Exception wenn 
einer deiner Tests fehlgeschlagen ist:
throw new ParseException();

Natürlich sollte die ParseException Informationen über die Fehlerquelle, 
Position etc. enthalten...

Autor: Andreas B. (andreasb)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Robert L. schrieb:
> @Läubi
>
> ich glaub nicht, dass das stimmt, was du schreibst
> throws heitß ja nur dass man eine Parseexception werfen KÖNNTE
> und nicht dass man das MUSS

Aber
>  @Test(expected = ParseException.class)

>
> ich glaub nicht, dass er ein Problem beim compilieren hat ...
>
>
> @TO
>
> class Tests {
>
> fehlt da ein "extends" ??

extends TestCase wurde mit JUnit 4 abgeschafft.

Du bist wohl noch bei JUnit 3?;-) Ich auch...


mfg Andreas

Autor: Läubi .. (laeubi) (Moderator) Benutzerseite
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Robert L. schrieb:
> ich glaub nicht, dass das stimmt

Glauben heißt nicht wissen, der JUnittest erwartet das die Exception 
geworfen wird siehe weiter unten.

Hans Lüthi schrieb:
> Ich begreiffe einfach diesen JUnit Test nicht, ich weiss
> gar nicht was ich überhaupt erfüllen soll?
Dann sprich mit deinem Betreuer!

Hans Lüthi schrieb:
> @Test(expected = ParseException.class)

Das sagt aus, dass der Test erwartet, dass die Methode eine Exception 
vom Typ ParseException wirft. (siehe z.B. 
http://radio.javaranch.com/lasse/2007/05/17/117940...)

Autor: Kurt Tresen (kurtisblow)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Also, ich verstehe schon, dass die Ausnahmen als Exceptions geworfen 
werden sollen, mit "throw new ParseException();" klappt das aber nicht, 
zeigt mir Eclipse als Fehler an. Mit exceptions = true meine ich nur, 
dass es sich um eine Ausnahme handelt, somit versuche ich zu verhindern, 
dass es in den Syntaxchecker läuft. Wie aber werfe ich in Junit4 eine 
exception?
Gruss Hans

Autor: Peter II (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Hans Lüthi schrieb:
> "throw new ParseException();" klappt das aber nicht,
> zeigt mir Eclipse als Fehler an.

und welchen?

Autor: Kurt Tresen (kurtisblow)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
The constructor ParseException() is undefined,
naja, sollte ich wohl noch einen Konstruktor machen,
weiss aber nicht warum ich bei ParseException nen Konstruktor brauche?
$

Edit: sehe gerade, der Konsturktor is in einer anderen Klasse definiert.

Autor: Andreas B. (andreasb)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Also du scheinst wohl noch ganz am Anfang zu sein;-)

Bei Eclipse kannst du mit F2 die Dokumentation anzeigen lassen, und mit 
F3 in die Sourcen springen (sofern vorhanden).

ParseException ist nirgends importiert, daher wird es wohl eine Klasse 
in der gleichen Package sein.

Ich vermute mal diese Klasse hat einen Konstruktor der z.B. einen String 
als Parameter verlangt, warscheinlich einen Fehler.

(Alles geraten, wissen kannst das nur DU).

dann würde es heissen throw new ParserException("Mein Fehler");

Aja, ganz wichtig: Wenn du auf den Fehler klickst (also das rote Icon an 
der Linke Seite) sagt dir Eclipse oft einen Lösungsvorschlag.
Schau den dir mal an!

Meistens geht der in die richtige Richtung.


mfg Andreas

Autor: Kurt Tresen (kurtisblow)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Danke, alles richtig geraten.

Autor: Kurt Tresen (kurtisblow)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
So, habe das Programm mal so verändert:

package u3a3;

public class KD {
  
  private static int offset = 0;
  /**
   * Parse a "Klammerdarstellung" (KD) of a tree.
   * 
   * <ul>
   * <li>An empty tree is encoded as '-'.</li>
   * <li>A node is encoded as an uppercase letter, i.e. everything accepted by {@link Character#isUpperCase(char)}.</li>
   * <li>Children are appended to the father as a ','-separated list of nodes enclosed in round brackets.</li>
   * </ul> 
   * 
   * @param kd Tree encoded in KD
   * @throws ParseException if the given String is not a valid KD of a tree.
   */
  
  public static void parse(String kd) throws ParseException
  {
    
    boolean exception = false;
    for (int i = 0; i<kd.length(); i++) //This for-loop show, if in the tree string has illegal characters
    {
      if ((kd.charAt(i) == '(' || kd.charAt(i) == ')' || kd.charAt(i) == ',' || kd.charAt(i) == '-' || ((int) kd.charAt(i) >= 65) && ((int) kd.charAt(i) <= 90)))
      {
        
      } else {
        exception = true;
        i = kd.length();
        
      }
    }
    
    if (exception == false)
    {
      tree (kd,0);
    } else if (exception == true) // if the string has illegal characters
    {
      throw new ParseException("",0);
    }
  }
  
  public static int tree(String str, int offset)
  {
    offset = follower(str, offset);
    while (str.length() > offset && (((int) str.charAt(offset) >= 65) && ((int) str.charAt(offset) <= 90 ))){
    offset = follower(str, offset + 1);
    }
    return offset;
  }
  
  public static int follower(String str, int offset)
  {
    offset = node(str, offset);
    while (str.length() > offset && str.charAt(offset) == '('){
    offset = node(str, offset + 1);
    }
    return offset;
  }
  
  public static int node(String str, int offset)
  {
    while (str.length() > offset && (((int) str.charAt(offset) >= 65) && ((int) str.charAt(offset) <= 90 ))){
      offset = node(str, offset + 1);
      }
    return offset;
  }
}


10 Tests werden noch nicht erfüllt. Das offset soll zeigen, ob die 
Klammerdarstellung auch wirklich richtig ist.
Vielleicht sieht jemand noch einen Fehler.

Autor: Läubi .. (laeubi) (Moderator) Benutzerseite
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Was sollen die ganze integer da? Und die Exeption kann man sofort werfen 
wenn etwas schief lief, außerdem solltest du dich mal einigen wo du die 
Klammer setzen willst oder einfach mit STRG+F mal den Source formatieren 
lassen.

Außerdem wäre es ganz gut wenn du mal versuchst zu verstehen was da 
abläuft anstelle aus allen möglichen Quellen was zusammenzukopieren.

Autor: Kurt Tresen (kurtisblow)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Naja, das was da steht habe auch ich so gedacht und nicht einfach so 
zusammenkopiert. Ich konvertiere die Chars in einen Integer um damit zu 
sehen, ob es ein erlaubter Grossbuchstabe ist (Wert zwischen 64 und 91). 
Die Bäume die ich überprüfe sind aus Grossbuchstaben, Kommas, Klammern 
und "-" für keinen Baum.

Autor: Andreas B. (andreasb)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Läubi .. schrieb:
> Klammer setzen willst oder einfach mit STRG+F mal den Source formatieren
> lassen.

STRG+SHIF+F, er will nicht suchen;-)

Hans Lüthi schrieb:
> Naja, das was da steht habe auch ich so gedacht und nicht einfach so
> zusammenkopiert. Ich konvertiere die Chars in einen Integer um damit zu
> sehen, ob es ein erlaubter Grossbuchstabe ist (Wert zwischen 64 und 91).

Character.isLetter(ch)
Character.isUpperCase(ch)

Es gibt noch einige mehr, schaue die dir mal an.

Im übrigen ist es leserlicher (und ggf. sogar etwas schneller) wenn du 
statt
>      if ((kd.charAt(i) == '(' || kd.charAt(i) == ')' || kd.charAt(i) ==
> ',' || kd.charAt(i) == '-' || ((int) kd.charAt(i) >= 65) && ((int)
> kd.charAt(i) <= 90)))

etwas schreibst wie

> char c = kd.charAt(i);
>      if ((c == '(' || c == ')' || c == ',' || c == '-' || ((int) c >=
> 65) && ((int) c <= 90)))


mfg Andreas

Autor: Kurt Tresen (kurtisblow)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
So, habe alles probiert, das ist dabei rausgekommen, funktioniert leider 
nicht ganz, vielleicht sieht jemand noch einen Fehler:

package u3a3;

public class KD {

  private static int offset = 0;

  /**
   * Parse a "Klammerdarstellung" (KD) of a tree.
   * 
   * <ul>
   * <li>An empty tree is encoded as '-'.</li>
   * <li>A node is encoded as an uppercase letter, i.e. everything accepted by
   * {@link Character#isUpperCase(char)}.</li>
   * <li>Children are appended to the father as a ','-separated list of nodes
   * enclosed in round brackets.</li>
   * </ul>
   * 
   * @param kd
   *            Tree encoded in KD
   * @throws ParseException
   *             if the given String is not a valid KD of a tree.
   */

  public static void parse(String kd) throws ParseException {

    boolean exception = false;

    for (int i = 0; i < kd.length(); i++) // This for-loop show, if in the
                        // tree string has illegal
                        // characters
    {
      offset = i;
      if ((kd.charAt(i) == '(' || kd.charAt(i) == ')'
          || kd.charAt(i) == ',' || kd.charAt(i) == '-' || Character
            .isUpperCase(kd.charAt(i)))) {

      } else {
        exception = true;
        i = kd.length();

      }
    }

    if (exception == false && kd.length() > 0) {
      offset = 0;
      tree(kd, offset);
      if (offset != kd.length()) 
      {
        throw new ParseException(kd, offset);
      }
    } else if (exception == true || kd.length() == 0) {
      throw new ParseException(kd, offset);
    }
  }

  public static int tree(String str, int offset) {
    offset = node(str, offset);
    if (str.length() > offset && (str.charAt(offset) == '(' )) {
      offset = undertree(str, offset + 1);
    } else if (str.charAt(offset) == ')')
    {
      offset = offset + 1;
    }
    return offset;
  }

  public static int node(String str, int offset) {

    if (str.length() > offset && (Character.isUpperCase(str.charAt(offset)) || str.charAt(offset) == '-')) {
      return (offset + 1);
    } else {
      return 0;
    }
  }

  public static int undertree(String str, int offset) {
    offset = tree(str,offset + 1);
    while (str.length() > offset && str.charAt(offset) == ',') {
      offset = node(str, offset + 1);
    }
    return offset;
  }

}


Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel




Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder GIF-Format hochladen.
Siehe Bildformate
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken erkennst du die Nutzungsbedingungen an.

webmaster@mikrocontroller.netImpressumNutzungsbedingungenWerbung auf Mikrocontroller.net