Forum: PC-Programmierung Probleme bei Java Syntaxchecker


von Kurt T. (kurtisblow)


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:

1
 package u3a3;
2
3
public class KD {
4
  
5
  private static int offset = 0;
6
  /**
7
   * Parse a "Klammerdarstellung" (KD) of a tree.
8
   * 
9
   * <ul>
10
   * <li>An empty tree is encoded as '-'.</li>
11
   * <li>A node is encoded as an uppercase letter, i.e. everything accepted by {@link Character#isUpperCase(char)}.</li>
12
   * <li>Children are appended to the father as a ','-separated list of nodes enclosed in round brackets.</li>
13
   * </ul> 
14
   * 
15
   * @param kd Tree encoded in KD
16
   * @throws ParseException if the given String is not a valid KD of a tree.
17
   */
18
  
19
  public static void parse(String kd) throws ParseException
20
  {
21
    if (kd.length() > 1 && kd.charAt(0) != '-' && kd.charAt(1) != '-')
22
    {
23
    tree(kd,0);
24
    }
25
  }
26
  
27
  public static int tree(String str, int offset)
28
  {
29
    offset = follower(str, offset);
30
    while (str.length() > offset && str.charAt(offset) == '+'){
31
    offset = follower(str, offset + 1);
32
    }
33
    return offset;
34
  }
35
  
36
  public static int follower(String str, int offset)
37
  {
38
    offset = node(str, offset);
39
    while (str.length() > offset && str.charAt(offset) == '*'){
40
    offset = node(str, offset + 1);
41
    }
42
    return offset;
43
  }
44
  
45
  public static int node(String str, int offset)
46
  {
47
    while (str.length() > offset && str.charAt(offset) == '(' || str.charAt(offset) == ')'){
48
      offset = node(str, offset + 1);
49
      }
50
    return offset;
51
  }
52
}

Hier noch der JUnit test:
1
 package u3a3;
2
3
import org.junit.Test;
4
5
public class Tests {
6
  void testCase(String lkd) throws ParseException {
7
    KD.parse(lkd);
8
  }
9
  
10
  @Test public void empyTree() throws ParseException { testCase("-"); }
11
  @Test public void onlyRoot() throws ParseException { testCase("A"); }
12
  @Test public void balancedTree() throws ParseException { testCase("A(B,C)"); }
13
  @Test public void listLeft() throws ParseException { testCase("A(B(C,-),-)"); }
14
  @Test public void listLeftImplicit() throws ParseException { testCase("A(B(C))"); }
15
  @Test public void listRight() throws ParseException { testCase("A(-,B(-,C))"); }
16
  @Test public void missingSibling() throws ParseException { testCase("A(B,-,C)");}
17
  @Test public void noChildren() throws ParseException { testCase("A(-,-)");}
18
  @Test public void genericTree() throws ParseException { testCase("A(-,B(C),-,D(E(-,F(G,H)),I))"); }
19
  
20
  @Test(expected = ParseException.class)
21
  public void empyString() throws ParseException { testCase(""); }
22
23
  @Test(expected = ParseException.class)
24
  public void noChild()throws ParseException { testCase("A()"); }
25
26
  @Test(expected = ParseException.class)
27
  public void noSibling()throws ParseException { testCase("A(B,)"); }
28
  
29
  @Test(expected = ParseException.class)
30
  public void twoCommas()throws ParseException { testCase("A(B,,C)"); }
31
32
  @Test(expected = ParseException.class)
33
  public void missingOpenBrace()throws ParseException { testCase("AB)"); }
34
35
  @Test(expected = ParseException.class)
36
  public void missingCloseBrace()throws ParseException { testCase("A(B"); }
37
38
  @Test(expected = ParseException.class)
39
  public void missingComma()throws ParseException { testCase("A(BC)"); }
40
  
41
  @Test(expected = ParseException.class)
42
  public void garbage()throws ParseException { testCase("A(B)C"); }
43
44
  @Test(expected = ParseException.class)
45
  public void garbage2()throws ParseException { testCase("A(B)(C)"); }
46
  
47
  @Test(expected = ParseException.class)
48
  public void noRoot()throws ParseException { testCase("-(A)"); }
49
50
  @Test(expected = ParseException.class)
51
  public void invalidNode()throws ParseException { testCase("A(1)"); }
52
53
  
54
}


Vielleicht sieht jemand was ich falsch mache.

mfg Hans

von Udo S. (urschmitt)


Lesenswert?

Was sagt der Debugger?
Du kannst jeden Test Step für Step durchgehen und genau sehen was 
passiert.

von Kurt T. (kurtisblow)


Lesenswert?

Ok, danke, gleich mal probieren

von Läubi .. (laeubi) Benutzerseite


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?

von Robert L. (lrlr)


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" ??

von Kurt T. (kurtisblow)


Lesenswert?

Habe nun einmal die erste methode überarbeitet:
1
public static void parse(String kd) throws ParseException
2
  {
3
    
4
    boolean exception = false;
5
    for (int i = 0; i<kd.length(); i++)
6
    {
7
      if (kd.charAt(i) == '(' || kd.charAt(i) == ')' || kd.charAt(i) == ',' || kd.charAt(i) == '-' || kd.charAt(i) >= 'A' && kd.charAt(i) <= 'Z')
8
      {
9
        
10
      } else {
11
        exception = true;
12
        i = kd.length();
13
        
14
      }
15
    }
16
    
17
    if (exception == false)
18
    {
19
      tree (kd,0);
20
    }
21
  }

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

von Kurt T. (kurtisblow)


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?

von Narf (Gast)


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...

von Andreas B. (andreasb)


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

von Läubi .. (laeubi) Benutzerseite


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/1179405760728.html)

von Kurt T. (kurtisblow)


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

von Peter II (Gast)


Lesenswert?

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

und welchen?

von Kurt T. (kurtisblow)


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.

von Andreas B. (andreasb)


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

von Kurt T. (kurtisblow)


Lesenswert?

Danke, alles richtig geraten.

von Kurt T. (kurtisblow)


Lesenswert?

So, habe das Programm mal so verändert:
1
package u3a3;
2
3
public class KD {
4
  
5
  private static int offset = 0;
6
  /**
7
   * Parse a "Klammerdarstellung" (KD) of a tree.
8
   * 
9
   * <ul>
10
   * <li>An empty tree is encoded as '-'.</li>
11
   * <li>A node is encoded as an uppercase letter, i.e. everything accepted by {@link Character#isUpperCase(char)}.</li>
12
   * <li>Children are appended to the father as a ','-separated list of nodes enclosed in round brackets.</li>
13
   * </ul> 
14
   * 
15
   * @param kd Tree encoded in KD
16
   * @throws ParseException if the given String is not a valid KD of a tree.
17
   */
18
  
19
  public static void parse(String kd) throws ParseException
20
  {
21
    
22
    boolean exception = false;
23
    for (int i = 0; i<kd.length(); i++) //This for-loop show, if in the tree string has illegal characters
24
    {
25
      if ((kd.charAt(i) == '(' || kd.charAt(i) == ')' || kd.charAt(i) == ',' || kd.charAt(i) == '-' || ((int) kd.charAt(i) >= 65) && ((int) kd.charAt(i) <= 90)))
26
      {
27
        
28
      } else {
29
        exception = true;
30
        i = kd.length();
31
        
32
      }
33
    }
34
    
35
    if (exception == false)
36
    {
37
      tree (kd,0);
38
    } else if (exception == true) // if the string has illegal characters
39
    {
40
      throw new ParseException("",0);
41
    }
42
  }
43
  
44
  public static int tree(String str, int offset)
45
  {
46
    offset = follower(str, offset);
47
    while (str.length() > offset && (((int) str.charAt(offset) >= 65) && ((int) str.charAt(offset) <= 90 ))){
48
    offset = follower(str, offset + 1);
49
    }
50
    return offset;
51
  }
52
  
53
  public static int follower(String str, int offset)
54
  {
55
    offset = node(str, offset);
56
    while (str.length() > offset && str.charAt(offset) == '('){
57
    offset = node(str, offset + 1);
58
    }
59
    return offset;
60
  }
61
  
62
  public static int node(String str, int offset)
63
  {
64
    while (str.length() > offset && (((int) str.charAt(offset) >= 65) && ((int) str.charAt(offset) <= 90 ))){
65
      offset = node(str, offset + 1);
66
      }
67
    return offset;
68
  }
69
}

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

von Läubi .. (laeubi) Benutzerseite


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.

von Kurt T. (kurtisblow)


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.

von Andreas B. (andreasb)


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

von Kurt T. (kurtisblow)


Lesenswert?

So, habe alles probiert, das ist dabei rausgekommen, funktioniert leider 
nicht ganz, vielleicht sieht jemand noch einen Fehler:
1
package u3a3;
2
3
public class KD {
4
5
  private static int offset = 0;
6
7
  /**
8
   * Parse a "Klammerdarstellung" (KD) of a tree.
9
   * 
10
   * <ul>
11
   * <li>An empty tree is encoded as '-'.</li>
12
   * <li>A node is encoded as an uppercase letter, i.e. everything accepted by
13
   * {@link Character#isUpperCase(char)}.</li>
14
   * <li>Children are appended to the father as a ','-separated list of nodes
15
   * enclosed in round brackets.</li>
16
   * </ul>
17
   * 
18
   * @param kd
19
   *            Tree encoded in KD
20
   * @throws ParseException
21
   *             if the given String is not a valid KD of a tree.
22
   */
23
24
  public static void parse(String kd) throws ParseException {
25
26
    boolean exception = false;
27
28
    for (int i = 0; i < kd.length(); i++) // This for-loop show, if in the
29
                        // tree string has illegal
30
                        // characters
31
    {
32
      offset = i;
33
      if ((kd.charAt(i) == '(' || kd.charAt(i) == ')'
34
          || kd.charAt(i) == ',' || kd.charAt(i) == '-' || Character
35
            .isUpperCase(kd.charAt(i)))) {
36
37
      } else {
38
        exception = true;
39
        i = kd.length();
40
41
      }
42
    }
43
44
    if (exception == false && kd.length() > 0) {
45
      offset = 0;
46
      tree(kd, offset);
47
      if (offset != kd.length()) 
48
      {
49
        throw new ParseException(kd, offset);
50
      }
51
    } else if (exception == true || kd.length() == 0) {
52
      throw new ParseException(kd, offset);
53
    }
54
  }
55
56
  public static int tree(String str, int offset) {
57
    offset = node(str, offset);
58
    if (str.length() > offset && (str.charAt(offset) == '(' )) {
59
      offset = undertree(str, offset + 1);
60
    } else if (str.charAt(offset) == ')')
61
    {
62
      offset = offset + 1;
63
    }
64
    return offset;
65
  }
66
67
  public static int node(String str, int offset) {
68
69
    if (str.length() > offset && (Character.isUpperCase(str.charAt(offset)) || str.charAt(offset) == '-')) {
70
      return (offset + 1);
71
    } else {
72
      return 0;
73
    }
74
  }
75
76
  public static int undertree(String str, int offset) {
77
    offset = tree(str,offset + 1);
78
    while (str.length() > offset && str.charAt(offset) == ',') {
79
      offset = node(str, offset + 1);
80
    }
81
    return offset;
82
  }
83
84
}

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.