parsingcompiler-constructionll-grammarlr-grammarshift-reduce

Isn't an LR(0) parser using lookaheads as well?


An LL(1)-parser needs a lookahead-symbol for being able to decide which production to use. This is the reason why I always thought the term "lookahead" is used, when a parser looks at the next input token without "consuming" it (i.e. it can still be read from the input by the next action). LR(0) parsers, however, made me doubt that this is correct:

Every example of LR(0)-parsers that I've seen also uses the next input token for deciding whether to shift or to reduce. In case of reduction the input token is not consumed.

I used the freeware tool "ParsingEmu" for generating an LR-table and performing an LR evalutation below for the word "aab". As you can see the column head contain tokens. From the evaluation you can see that the parser is deciding which column to use by looking at the next input token. But when the parser reduces in steps 4 - 6 the input doesn't change (although the parser needs to know the next input token "$" when performing a transition to the next state).

Grammar:

S -> A
A -> aA
A -> b

Table: LR table

Evaluation: LR evaluation

Now I made following assumptions for the reason of my confusion:

  1. My assumption for the definition of "lookahead" (lookahead = input token not being consumed) is wrong. Lookahead just means two different things for either LL-parsers or LR-parsers. If so, how can "lookahead" be defined then?

  2. LR-parsers have (from the theoretical point of view when you would use push-down automaton) additional internal states where they consume the input token by putting it on the stack and therefore are able to make the shift- reduce- decision by just looking on the stack.

  3. The evaluation shown above is LR(1). If true, what would an LR(0) evaluation look like?

Now what is correct, 1, 2 or 3 or something completely different?


Solution

  • It's important to be precise:

    An LR(k) parser uses the curent parser state and k lookahead symbols to decide whether to reduce, and if so, by which production.

    It also uses a shift transition table to decide which parsing state it should move to after shifting the next input token. The shift transition table is keyed by the current state and the (single) token being shifted, regardless of the value of k.

    If in a given parser state, it would be possible to produce both a shift and a reduce action, then the parser has a shift/reduce conflict, and it is invalid. Consequently, the above two determinations could in theory be done nondeterministically.

    If in a given parser state, no reduce is possible and the next input symbol cannot be shifted (that is, there is no transition for that state with that input symbol), then the parse has failed and the algorithm terminates.

    If, on the other hand, the shift transition leads to the designated Accept state, then the parse succeeds and the algorithm terminates.

    What all that means is that the lookahead is used to predict which, if any, reduction should be applied. In an LR(0) parser, the decision to shift (more accurately, to attempt to shift) must be made before reading the next input token, but the computation of the state to transition to do is made after reading the token, at which point it will signal an error if no shift is possible.


    LL(k) parsers must predict which production replace a non-terminal with as soon as they see the non-terminal. The basic LL algorithm starts with a stack containing [S, $] (top to bottom) and does whichever of the following is applicable until done:


    In both cases, lookahead has the same meaning: it consists of looking at input tokens without moving the input cursor.

    If k is 0, then: