next up previous
Next: Beyond LL(1) - use Up: How to implement a Previous: Constructing an LL(1) grammar

How to implement the parser

We can now implement a parser - one way would be to construct a deterministic PDA. However, using JAVA we can implement the parser using recursion - here the internal JAVA stack plays the role of the stack of the PDA.

First of all we have to separate the input into tokens which are the terminal symbols of our grammar. To keep things simple I assume that tokens are separated by blanks, i.e. one has to type

 ( a + a ) * a
for (a+a)*a. This has the advantage that we can use java.util.StringTokenizer. In a real implementation tokenizing is usually done by using finite automata.

I don't want to get lost in java details - in the main program I read a line and produce a tokenizer:

        String line=in.readLine();
        st = new StringTokenizer(line+" $");
The tokenizer st and the current token are static variables. I implement the convenience method next which assigns the next token to curr.
    static StringTokenizer st;
    static String curr;

    static void next() {
        try {
            curr=st.nextToken().intern();
        } catch( NoSuchElementException e) {
            curr=null;
        }
    }
We also implement a convenience method error(String) to report an error and terminate the program.

Now we can translate all productions into methods using the $ \textrm{Lookahead}$ sets to determine which alternative to choose. E.g. we translate

$\displaystyle E' \to \texttt{+} T E' \mid \epsilon$

into (using E1 for $ E'$ to follow JAVA rules):
    static void parseE1() {
        if (curr=="+") {
            next();
            parseT();
            parseE1();
        } else if(curr==")" || curr=="$" ) {
        } else {
            error("Unexpected :"+curr);
        }  
The basic idea is to

We initiate the parsing process by calling next() to read the first symbol and then call parseE(). If after processing parseE() we are at the end marker, then the parsing has been successful.

        next();
        parseE();
        if(curr=="$") {
            System.out.println("OK ");
        } else {
            error("End expected");
        }

The complete parser can be found at

http://www.cs.nott.ac.uk/~txa/g51mal/ParseE0.java.

Actually, we can be a bit more realistic and turn the parser into a simple evaluator by

Here is the complete program with evaluation

http://www.cs.nott.ac.uk/~txa/g51mal/ParseE.java.

We can try the program and observe that it handles precedence of operators and brackets properly:

[txa@jacob misc]$ java ParseE
3 + 4 * 5
OK 23
[txa@jacob misc]$ java ParseE
( 3 + 4 ) * 5
OK 35                                                                           


next up previous
Next: Beyond LL(1) - use Up: How to implement a Previous: Constructing an LL(1) grammar
Thorsten Altenkirch 2001-05-08