The previous introduction of LL (1) and how to use LL (1) grammar. But ll (k) grammar requires predictions to be made when you see a K-letter, which is a lot less than the LR (k) grammar.
LR (K) grammar is defined as: left-to-right analysis, the right derivation, ahead of view K words. Let's take a look at an example to get a general idea of the LR grammar.
The above is an example of using the LR grammar to analyze the source code. Note that there are only three actions in the LR grammar: Move in, statute, and accept, and these three actions are obtained by looking up a table. At any time, if the only one of these three actions is identified, we can make the LR grammar work correctly. To better understand the LR (K) Grammar, we first introduce the following simplest LR (0) grammars.
Because the action is determined by the table, the construction of the table is still the focus of our construction, first to look at the final form of a table:
The first thing to note is that when we build this table, we use the state machine and the row label represents the state. The column label consists of two parts, Terminator, and non-terminator. s for the move in, R for the Statute, G for the jump, a for the acceptance, they followed the number, except R, is the status of the label, only r after the number refers to the time of the specification to the first generation. All empty places represent errors. Visible in non-terminator only jump.
To build this table, we first build the state machine. We start with a basic grammar, with the following syntax:
We add a point to the production to form this form, called the item. The position of this point tells us what is currently in the state. Each time the point moves, we jump to a state. The string in front of the point indicates the history we have read, and the string following the dot indicates what we want to get. This is the way of expression that can look to the future, but also the past. In the above starting item, we hope to get an S non-terminator next time, we can see that the 1 and 2 production is the equivalent form of s, if we get 1 and 2 of the right side of the production, we are equivalent to get the non-terminator s, so, our starting state is:
We call the first generation the core, the other as the normal. This state is called State 1, and all States are obtained by the movement of the points of each item in the state. For example, when State 1 eats a Terminator x, the point in the second item of State 1 is shifted one bit to the right. Get Status 2:
Of course, State 1 can also eat a terminator (, get State 3:
The first item in State 3 is a core item. That's what we're talking about. Move into operation.
If state 1 eats a non-terminator s, then we call the state to jump, start and move in a similar effect. Then get the following status:
Let's look at state 2, where the point is now at the end of the production, meaning that the formula is fully matched, then it can be set. The specific operation according to the subscript of R, select the production type, the stack of the right string of the production of all pop-up, will produce the left symbol of the stack, and then jump to the corresponding state. The statute is still not well understood, so let us give an example of the last four statutes of the top chart.
First of all, to illustrate, in the actual use process, the content in the stack does not contain any symbols, only the status number, the first picture is for the convenience of understanding, so the symbols are put into the stack. Then, in the Protocol pop-up stack, we pop up is also the status number.
Then, for the first of the last four statutes, the top of the stack symbol is +16 (8 S12, E21) 22 of the six symbols and six states, only the top four satisfies the statute, at this point, if expressed in Word, it can be represented as e-> (s,e). That means. Before we have got a complete production of the right part, can be on its statute. Need to put all the symbols involved in the right to pop up, but we actually pop up is the state, so, the original 16 8 12 18 21 22 Popup State, the resulting stack is 16, we pop the string specification becomes non-Terminator E, at this time, you can think of e as input in the input queue, get e??, The top of the stack is still 16. Then the e-stack, corresponding to the 16th status encountered E jump to 17 state, when the stack top is 16E17. Then proceed as it goes down.
The above, is the basic concept of moving into, the statute, jump (can be understood as moving into), the analysis of the acceptance, they are basic actions. According to the derivation process just now, we can build a state machine, according to the state machine we can build a table we need. Table if we get an analysis of each item in the table has only one action, then we say this is a non-semantic LR (0) grammar. However, the LR (0) Grammar may also appear two semantic, which we call the migration of the statute of conflict. First look at a table with conflicts:
Obviously, there is a conflict in the + number position. Let's analyze the causes of the conflict. If the input queue input is the + number, then the state 3 can be + into the stack, called the move, to the state 4, can also be the statute, the specification to the production of 2. So can the statute be? If the specification, (at this point + is still in the input queue), the protocol to the e will be placed into the input queue input, and then the e-Stack, the next + number will certainly be in the stack. Then in the top two bits of the stack there is a string such as e+, the surface + must be an E of the follow symbol set in a row. Through analysis, we know that the + cannot be a terminator in the follow collection of E. Therefore, there is no statute for this option.
So, when we build the table, we can follow test the Terminator, and only the symbols in this set will be able to perform the protocol. The pseudo-code and the final result are as follows:
Note that in the second for, the processing is. The item that has been to the end of the production type. Finally, the set R is a non-terminator that can be put into production type a->α, under these non-terminator, can be regulated to a->α.
The above workaround for LR (0) conflicts is called SLR (0). This is a relatively simple solution, but does not represent a perfect solution to all conflicts. Because it uses the follow collection is not a very precise set of conflicting pre-judgments. There is still a possibility of conflict.
So why is the follow set imprecise? We assume that an item contains such a string αf.β, and we know that the follow collection of F contains the first collection of string β. Therefore, the follow set we use in SLR (0) does not necessarily predict the resulting formula correctly. However, if you use the first collection, you can accurately predict the resulting formula. So, we redefined the item, which contains the generated, labeled State of the point, ahead of the view of the symbol collection, these three parts. Use the following algorithm to calculate the specific contents of each item in a state:
where closure (I), is based on the state set I in the core items to produce some other items, it can be seen that the first collection is used. Goto is the move-in operation. Visible if the item is in the. After there is a character, it directly starts to move in if the item is in. After there is no character, and the input port has a character in the Advanced View symbol collection of the item, the statute. The last set of R is a non-terminator set of protocols that can be a->α.
Using the above algorithm, we get the LR (1) grammar, obviously, its state machine and other LR (0) and the SLR (0) state machine contains the items are not the same. Here we give an example of the C language:
As can be seen in the state machine, there are a lot of states, they except the prediction symbol set is not the same, the others are the same. We can combine these states to simplify the size of the LR (1) Analysis table. We refer to the grammar described by the merged state machine as the LALR (1) (La:look Ahead) grammar. It requires less space to store the table, but its disadvantage is that there is a possibility of a statute-statute conflict, but in practice the impact of such a conflict is minimal.
Through this discussion, we went directly to a parser, the most important thing is the establishment of the analysis table.
For LL (K) grammars, their analysis table is an index of Terminator and non-terminator, and the table is filled with the resulting formula. For LR (K), they are state and Terminator, non-terminator indexed, and the table is filled with various actions.
From the analysis process, LL (k) grammar is a top-down analysis (from the second L decides to start down analysis when encountering non-Terminator), and the LR (k) grammar is from the bottom up analysis (R).
In fact, the reason that the ability to cause LR is higher than LL is that ll must determine the type of production used for each character you enter, and it is focused on the present. However, LR will continue until the information obtained is sufficient to determine a production type before it is determined, which is used in the item. Bring benefits (Review the past and look ahead).
The following is a comparison of the various grammatical abilities:
Modern compilation Principles-Chapter II (LR (1) of parsing)