0

In this LR(0) automaton enter image description here

There are transitions for the non terminals as well, which I don't understand. If the input is aab. Then you are going to end up in the state which is just A->a·. If you were to visualise the state that were reached by inputting aab or any other input wouldn't there be transitions between states that don't have arcs between them?

I don't understand why this is different to a DFA or NFA, where you start at the starting state, and transition only along arcs in the Automata until you reach the accepting state.

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
Jonathan.
  • 53,997
  • 54
  • 186
  • 290
  • I think the drawing artists intentions on labeling the arcs was not to only show which input causes the transition, but also which of the matching rules (inside the boxes) matched and thus caused a transition. So, in the first box, rule ``A -> a .`` matches and thus he labels the arc to the right with ``A``. – BitTickler Aug 29 '15 at 19:48

3 Answers3

1

LR parsing uses a push-down stack of states, which at any point represents the set of as yet incompletely recognized productions in the parse. When a state with a complete production is reached (the dot is at the end, such in 'A -> a.'), this means that the stack has the symbols on the right hand side of this production at the top. You pop those off to go back to the state which started this particular sequence of transitions and now take the transition for the non-terminal on the left hand side of this production.

So if you reach 'A -> a.' you have to back up one transition (the path labeled 'a') and take the 'A' transition instead. If you reach 'S -> AB.' you have to back up two transitions and take the 'S' transition instead. And so on.

There is no such backtracking (or a corresponding need to maintain a stack) with a DFA or NFA.

arayq2
  • 2,502
  • 17
  • 21
  • So the reduction is not really included in just the diagram of the automaton? As in there is no arcs for it? – Jonathan. Aug 29 '15 at 21:29
  • To clarify a bit, when you follow an arrow transitioning to a state, you always push the new state on the stack, leaving the old state there underneath -- unlike with a FA where there's only 1 current state. States remain on the stack until they are popped by a reduce, and the first state on the bottom of the stack will never be popped. – Chris Dodd Aug 29 '15 at 21:30
  • @Jonathan, yes, that's right. Reductions amount to backtracking, while the arrows are shifts only. – arayq2 Aug 30 '15 at 02:31
0

The transitions labeled with nonterminals are only followed after performing a reduce step. When you do a reduce, you will remove some number of symbols from the parsing stack, then push a nonterminal onto the stack. At that point, you'll follow the transition labeled with that particular nonterminal.

The parsing automaton is different from a typical DFA or NFA in that it's designed to control a stack. The transitions all correspond to different actions on the parsing stack; each terminal corresponds to a shift, completed items correspond to reductions, and nonterminals tell you where to go after following the reduction. Theoretically speaking, an LR automaton is the control for a deterministic pushdown automaton, if that helps.

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
  • I am not sure if terminology is clean in this answer. LR(0) is in contrast to LL(0). While you can use shift reduce parsers for parsing LR(0), the basic semantics of the LR/LL terms is about where the recursions show in the productions: Example: ``LL: B -> B|a, LR: B -> a|B``. I am not sure if it is a perfect idea to relate LR with shift reduce in a synonymous way. LR/LL classify traits of the grammar and do not imply an algorithm. – BitTickler Aug 29 '15 at 20:12
  • @BitTickler: shift/reduce parsing IS LR parsing. LL parsing is recursive descent, not shift/reduce. – Chris Dodd Aug 29 '15 at 21:16
0

An LR automaton is a push-down automaton, which uses a stack of states, rather than a single current state as with a DFA. The actions (shift, reduce and goto) are governed by the state currently on the top of the stack, with shift and goto pushing a new state and reduce popping a fixed number of states based on the rule being reduced. In your example, if we number the states in columns (so 0 is the initial state in the upper left, 3 is the state in the middle column), we can show how it parses the input string 'ab':

Action              Stack
initial state       0
shift a             0 1
reduce A->a         0
goto A              0 3
shift b             0 3 4
reduce B->b         0 3
goto B              0 3 5
reduce S->AB        0
goto S              0 2
accept

Since this is an LR(0) parser, each state has either shift/goto actions or a single reduce action, and no lookahead is needed to know what to do next (though a shift, which consumes an input token, does depend on that token to determine which state to shift to).

For the input 'aab' the process is only a little bit longer:

Action              Stack
initial state       0
shift a             0 1
reduce A->a         0
goto A              0 3
shift a             0 3 1
reduce A->a         0 3
goto A              0 3 3
shift b             0 3 3 4
reduce B->b         0 3 3
goto B              0 3 3 5
reduce S->AB        0 3
goto S              0 3 6
reduce B->S         0 3
goto B              0 3 5
reduce S->AB        0
goto S              0 2
accept

The shows the effect of the right-recusive rule to match multiple a's in the input (B -> S -> AB), which results in all the a's being shifted (pushing states on the stack) until the end of the recusive sequence is reached, followed by a series of reduce/goto actions to pop them back off. Using a left-recursive rule is better and uses a fixed amount of stack space, alternating shifts and reduces.

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226