简体   繁体   中英

Definition of Shift/Reduce conflict in LR(1) parsing

Is it correct to state:

" A shift reduce conflict occurs in an LR(1) parser if and only if there exist items:

A -> alpha .

A -> alpha . beta

such that Follow(A) is not disjoint from First(beta).

where A is a non-terminal, alpha and beta are possibly empty sequences of grammar symbols."

(Intuitively this is because there is no way to determine, based on the top of the stack and the lookahead, whether it is appropriate to shift or reduce)

Note: If you guys think this depends on any specifics of the definition of first/follow comment and I will provide.

No, that statement is not correct.

Suppose in some grammar:

  • the productions include both:
    • A → α
    • A → α β
  • FOLLOW(A) ∩ FIRST(β) ≠ ∅

That is not quite sufficient for the grammar to have a shift-reduce conflict, because it requires that the non-terminal A be reachable in a context in which the lookahead includes FOLLOW(A) ∩ FIRST(β).

So only if we require the grammar to be reduced, or at least to not contain any unreachable or useless productions, is the above sufficient to generate a shift-reduce conflict.

However, the above conditions are not necessary because there is no requirement that the shift and the reduction apply to the same non-terminal, or even "related" non-terminals. Consider the following simple grammar:

prog → stmt
prog → prog stmt
stmt → expr
stmt → func
expr → ID
expr → '(' expr ')'
func → ID '(' ')' stmt

That grammar (which is not ambiguous, as it happens) has a shift-reduce conflict in the state containing ID . ( ID . ( because ID could be reduced to expr and then stmt , or ( could be shifted as part of func → ID '(' ')' stmt .


Although it's a side-point, it's worth noting the the FOLLOW set is only used in the construction of SLR(k) grammars. The canonical LR(k) construction -- and even the LALR(k) construction -- will successfully generating parsers for grammars in which the use of the FOLLOW set instead of a full lookahead computation will indicate a (non-existent) shift-reduce conflict. The classic example, taken from the Dragon book (example 4.39 in my copy), edited with slightly more meaningful non-terminal names:

stmt → lvalue '=' rvalue
stmt → rvalue
lvalue → '*' rvalue
lvalue → ID
rvalue → lvalue

Here, FOLLOW( rvalue ) is { = , $ }, and as a result in the state { stmt → lvalue · '=' rvalue , rvalue → lvalue · }, it appears that a reduction to rvalue is possible, leading to a false shift-reduce conflict.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM