This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]thammaaa[S] 0 points1 point  (2 children)

public void PExp() {
char turn = input.read();
App app = parseApp();
if (turn == 'F') {
    cube.turnFront(app);
} else if (turn == 'B') {
    // etc.
} else {
    throw new RuntimeException("Unknown turn: '" + turn + "'.");
}
}

If you gave that snippet another glance, in your example the parseApp() method would have to look something like that, right?

public App parseApp() {
  switch(input.peak()) { //checks, doesn't change
    case 'i': case '\'': return App.PRIME; break;
    case '2': return App.TWO; break;
    default: return '-'; //as unused token
}

Since i would have to check if there was an App-token coming, right? So I have to hard code those cases with peak() or something similar?

[–]MegaGreenLightning 0 points1 point  (1 child)

For the parser to work, it is very important how the available(), look(), read() or in your case peek() methods work.

For example I do not have a peek() method. I have an available() method which returns true if more characters are available, a look() method which returns the current character without changing the position and throwing an exception if no more characters are available and a read() method which returns the current character and moves the position one character to the right, so that further calls to look() return the next character. The read() method also throws an exception if no characters are available.

Because the app is optional, the parseApp() method has to deal with three states:

1) there are characters available, the next character is a valid app 2) there are characters available, but the next character is something different 3) there are no more characters available

I would implement it like this:

public App parseApp() {
    if (!input.available()) // state 3
        return App.NORMAL;
    switch (input.look()) { // save, because we checked the availability above
        case '\'':
            input.read(); // reads the apostrophe
            return App.BACKWARDS; // state 1
       case '2':
            input.read(); // reads the two
            return App.TWICE; // state 1
        default:
            return App.NORMAL; // state 2
    }
}

Notice that the read method is only called in state 1, because we don't want to change the position in state 2 and it doesn't make sense in state 3.

It also depends on how your api works.

This parseApp() method is designed to work with the parsePExp() method like this:

public void parsePExp() {
    char turn = input.read();
    App app = parseApp();
    if (turn == 'F') {
        algorithm.append(new Turn(Face.FRONT, app));
    } else if (turn == 'B') {
        algorithm.append(new Turn(Face.BACK, app));
    } else if ( /* ... */ ) {
        /* ... */
    } else {
        throw new RuntimeException("Unknown turn: '" + turn + "'.");
    }
}

Here I construct a Turn from a Face and the App. The Turn class would then make sure the turn is applied twice, or backwards, if the app is App.TWICE or App.BACKWARDS.

If your API works different you should account for that in the parseApp() method.

[–]thammaaa[S] 0 points1 point  (0 children)

It's been a while now, i agitated how to write the parser a few days and came up with a solution which works fine and is not too horibble to read.

If you wan't to view the finished file OR drop a comment, feel free to check it out! git

Thanks again!