Download presentation
Presentation is loading. Please wait.
Published byDomenic Gallagher Modified over 8 years ago
1
ISBN 0-321-19362-8 Chapter 4 Lexical and Syntax Analysis
2
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-2 Chapter 4 Topics Introduction Lexical Analysis The Parsing Problem Recursive-Descent Parsing Bottom-Up Parsing
3
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-3 Overview of parsing A parser constructs a parse tree for a given program The tree may be explicitly or implicitly constructed The parser has two goals: –Produce a parse tree –Check the syntax of the program, and do error detection and recovery
4
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-4 Classes of parsers Two broad classes of parsers: –Top-down — build parse tree from root to leaves –Bottom-up — build parse tree from leaves to root These parsing algorithms never look ahead more than one token into the input program. The recursive-descent parser is a type of top-down parser that is constructed from the EBNF grammar for a language.
5
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-5 Top down vs. bottom up parsing The parsing problem is to connect the root node S with the tree leaves, the input. Top-down parsers: Easy to implement by hand, but work with restricted grammars. examples: -Predictive parsers (e.g., LL(k)) Bottom-up parsers: Suitable for automatic parser generation, handle a larger class of grammars. examples: –shift-reduce parser (or LR(k) parsers) Both are general techniques that can be made to work for all languages (but not all grammars!).
6
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-6 Parsing an arbitrary Context Free Grammar is O(n 3 ), e.g., it can take time proportional the cube of the number of symbols in the input. This is bad! If we constrain the grammar somewhat, we can always parse in linear time. This is good! Linear-time parsing –LL parsers Recognize LL grammar Use a top-down strategy –LR parsers Recognize LR grammar Use a bottom-up strategy Parsing complexity LL(n) : Left to right, Leftmost derivation, look ahead at most n symbols. LR(n) : Left to right, Right derivation, look ahead at most n symbols.
7
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-7 Top-down Parsers –Given a sentential form, xA , the parser must choose the correct A-rule to get the next sentential form in the leftmost derivation, using only the first token produced by A Terminal symbols :a, b, c,… Nonterminal symbols :A, B, C,… Terminals or nonterminals :W, X, Y, Z,… Strings of terminals:w, x, y, z… Mixed strings:α, β,γ,δ…(Page 168) –The most common top-down parsing algorithms: Recursive descent - a coded implementation LL parsers - table driven implementation Top down vs. bottom up parsing
8
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-8 Bottom-up parsers –Given a right sentential form, , determine what substring of is the right-hand side of the rule in the grammar that must be reduced to produce the previous sentential form in the right derivation –The most common bottom-up parsing algorithms are in the LR family Top down vs. bottom up parsing
9
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-9 Top down vs. bottom up parsing Both are general techniques that can be made to work for all languages (but not all grammars!). Recall that a given language can be described by several grammars. Both of these grammars describe the same language E -> E + Num E -> Num E -> Num + E E -> Num The first one, with it’s left recursion, causes problems for top down parsers. For a given parsing technique, we may have to transform the grammar to work with it.
10
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-10 Recursive-Descent Parsing Recursive Descent Process –There is a subprogram for each nonterminal in the grammar, which can parse sentences that can be generated by that nonterminal –EBNF is ideally suited for being the basis for a recursive-descent parser, because EBNF minimizes the number of nonterminals
11
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-11 Recursive-Descent Parsing Assume we have a lexical analyzer named lex, which puts the next token code in nextToken The coding process when there is only one RHS: –For each terminal symbol in the RHS, compare it with the next input token; if they match, continue, else there is an error –For each nonterminal symbol in the RHS, call its associated parsing subprogram
12
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-12 Consider the following example grammar for simple assignment statements: → ident = → { (+|-) } → {(*|/) } → id | numliteral Each EBNF rule translates into a parsing procedure. Recursive Decent Parsing Example
13
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-13 The parsing procedure for the assignment rule → id = is quite simple: void assignstmt() { match(ID); match(ASSIGNOP); expr(); } Recursive Decent Parsing Example
14
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-14 /* Function expr Parses strings in the language generated by the rule: → {(+ | -) } */ void expr() { /* Parse the first term */ term(); /* As long as the next token is + or -, all lex to get the next token, and parse the next term */ while (nextToken == PLUS_CODE || nextToken == MINUS_CODE) { lex(); /* get next token */ term(); /* parse next term */ } } This particular routine does not detect errors Convention: Every parsing routine leaves the next token in nextToken Recursive Decent Parsing Example
15
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-15 Recursive Decent Parsing Example For the grammar: -> {(*|/) } We could use the following recursive descent parsing subprogram (this one is written in C) void term() { factor(); /* parse first factor*/ while (next_token == ast_code || next_token == slash_code) { lex(); /* get next token */ factor(); /* parse next factor */ }
16
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-16 factor() → id | numliteral void factor() { if (curtok == ID) match(ID); else if (curtok == NUMLITERAL) match(NUMLITERAL); else error("factor expected"); }
17
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-17 Auxiliary procedures string Token2String(Token t); Token match(Token expToken) { if (curtok == expToken) curtok = NextToken(); else { error(Token2String(expToken) + " expected"); }
18
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-18 The Parsing Problem –Parsers that work for any unambiguous grammar are complex and inefficient ( O(n 3 ), where n is the length of the input ) –Compilers use parsers that only work for a subset of all unambiguous grammars, but do it in linear time ( O(n), where n is the length of the input )
19
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-19 Top Down Parsing Methods Simplest method is a full-backup recursive descent parser. Write recursive recognizers (subroutines) for each grammar rule –If rules succeeds perform some action (i.e., build a tree node, emit code, etc.) –If rule fails, return failure. Caller may try another choice or fail –On failure it “backs up” Problems –When going forward, the parser consumes tokens from the input, so what happens if we have to back up? –Backup is, in general, inefficient –Grammar rules which are left-recursive lead to non-termination
20
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-20 Recursive-Descent Parsing A nonterminal that has more than one RHS requires an initial process to determine which RHS it is to parse –The correct RHS is chosen on the basis of the next token of input (the lookahead) –The next token is compared with the first token that can be generated by each RHS until a match is found –If no match is found, it is a syntax error
21
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-21 Recursive-Descent Parsing /* Function factor Parses strings in the language generated by the rule: -> id | ( ) */ void factor() { /* Determine which RHS */ if (nextToken) == ID_CODE) /* For the RHS id, just call lex */ lex();
22
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-22 Recursive-Descent Parsing /* If the RHS is ( ) – call lex to pass over the left parenthesis, call expr, and check for the right parenthesis */ else if (nextToken == LEFT_PAREN_CODE) { lex(); expr(); if (nextToken == RIGHT_PAREN_CODE) lex(); else error(); } /* End of else if (nextToken ==... */ /* It was neither an id nor a left parenthesis */ else error(); }
23
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-23 Problems Some grammars cause problems for top down parsers. Top down parsers do not work with left-recursive grammars. –E.g., one with a rule like: A -> A +B –We can transform a left-recursive grammar into one which is not. A top down grammar can limit backtracking if it only has one rule per non-terminal –The technique of factoring can be used to eliminate multiple rules for a non-terminal.
24
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-24 The LL Grammar Class The Left Recursion Problem (See page 173) If a grammar has left recursion, either direct or indirect, it cannot be the basis for a top-down parser –A grammar can be modified to remove left recursion(Aho et al., 1986), but will not cover it here.
25
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-25 The other characteristic of grammars that disallows top-down parsing is the lack of pairwise disjointness –The inability to determine the correct RHS on the basis of one token of lookahead –Def: FIRST( ) = {a | =>* a } (If =>* , is in FIRST( )) where =>* means 0 or more derivation steps The LL Grammar Class
26
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-26 Pairwise Disjointness Test: –For each nonterminal, A, in the grammar that has more than one RHS, for each pair of rules, A i and A j, it must be true that FIRST( i ) FIRST( j ) = ( The intersection of the two sets must be empty, it implies if a nonterminal A has more than one RHS, the first terminal symbol that can be generated in a derivation for each of them must be unique to that RHS) Examples: A a | bAb | c The FIRST sets for the RHSs of these rules are {a}, {b}, and {c}, which are clearly disjoint. Therefore, these rules pass the Pairwise Disjointness Test A aB | aAb The FIRST sets for the RHSs of these rules are {a} and {a}, which are clearly not disjoint. So, these rules fail the Pairwise Disjointness Test The LL Grammar Class
27
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-27 Recursive-Descent Parsing Left factoring can resolve the problem Replace identifier | identifier [ ] with identifier | [ ] or identifier [[ ]] (the outer brackets are metasymbols of EBNF)
28
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-28 Summary of Recursive Descent Simple and general parsing strategy –Left-recursion must be eliminated first but that can be done automatically Unpopular because of backtracking –Thought to be too inefficient In practice, backtracking is eliminated by restricting the grammar, allowing us to successfully predict which rule to use.
29
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-29 Predictive Parser A predictive parser uses information from the first terminal symbol of each expression to decide which production to use. A predictive parser is also known as an LL(k) parser because it does a Left-to-right parse, a Leftmost- derivation, and k-symbol lookahead. A grammar in which it is possible to decide which production to use examining only the first token (as in the previous example) are called LL(1) LL(1) grammars are widely used in practice. –The syntax of a PL can be adjusted to enable it to be described with an LL(1) grammar.
30
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-30 LL(k) and LR(k) parsers Two important classes of parsers are called LL(k) parsers and LR(k) parsers. The name LL(k) means: –L - Left-to-right scanning of the input –L - Constructing leftmost derivation –k – max number of input symbols needed to select a parser action The name LR(k) means: –L - Left-to-right scanning of the input –R - Constructing rightmost derivation in reverse –k – max number of input symbols needed to select a parser action So, a LL(1) parser never needs to “look ahead” more than one input token to know what parser production to apply.
31
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-31 Predictive Parsing and Left Factoring Consider the grammar E T + E | T T int | int * T | ( E ) Hard to predict because –For T, two productions start with int –For E, it is not clear how to predict which rule to use A grammar must be left-factored before use for predictive parsing Left-factoring involves rewriting the rules so that, if a non-terminal has more than one rule, each begins with a terminal.
32
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-32 Left-Factoring Example Consider the grammar E T + E | T T int | int * T | ( E ) Factor out common prefixes( 字首 ) of productions E T X X + E | T ( E ) | int Y Y * T |
33
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-33 Left Factoring Consider a rule of the form A -> a B1 | a B2 | a B3 | … a Bn A top down parser generated from this grammar is not efficient as it requires backtracking. To avoid this problem we left factor the grammar. –collect all productions with the same left hand side and begin with the same symbols on the right hand side –combine the common strings into a single production and then append a new non-terminal symbol to the end of this new production –create new productions using this new non-terminal for each of the suffixes( 字尾 ) to the common production. After left factoring the above grammar is transformed into: A –> a A1 A1 -> B1 | B2 | B3 … Bn
34
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-34 Bottom-up Parsing The parsing problem is finding the correct RHS in a right-sentential form to reduce to get the previous right-sentential form in the derivation E →E+T | T T →T*F | F F → i d| ( E ) E →E+T | T T →T*F | F F → i d| ( E ) E => E + T => E + T*F => E + T*id => E + F*id => E + id*id => T + id*id => F + id*id => id + id*id E => E + T => E + T*F => E + T*id => E + F*id => E + id*id => T + id*id => F + id*id => id + id*id E+ T*id may be from E+T, T, id for bottom-up parser if chosen E+T, the resulting sentential form would be E*id, it is not a legal right sentential form for the grammar
35
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-35 Bottom-up Parsing Intuition about handles: –Def: is the handle of the right sentential form = w if and only if S =>*rm Aw =>rm w =>rm specifies a rightmost derivation step –Def: is a phrase of the right sentential form if and only if S =>* = 1 A 2 =>+ 1 2 =>+ means one or more derivation steps –Def: is a simple phrase of the right sentential form if and only if S =>* = 1 A 2 => 1 2
36
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-36 Bottom-up Parsing Intuition about handles: –The handle of a right sentential form is its leftmost simple phrase –Given a parse tree, it is now easy to find the handle –Parsing can be thought of as handle pruning
37
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-37 Bottom-up Parsing Shift-Reduce Algorithms –Reduce is the action of replacing the handle on the top of the parse stack with its corresponding LHS –Shift is the action of moving the next token to the top of the parse stack
38
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-38 Shift-reduce parsers Shift-reduce parsers use a parse table and a stack to do syntax analysis The LR parsing algorithm is a shift-reduce parsing algorithm
39
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-39 Bottom-up Parsing Advantages of LR parsers: –They will work for nearly all grammars that describe programming languages. –They work on a larger class of grammars than other bottom-up algorithms, but are as efficient as any other bottom-up parser. –They can detect syntax errors as soon as it is possible. –The LR class of grammars is a superset of the class parsable by LL parsers.
40
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-40 The LR Parser Data Structures The LR parsing algorithm uses a stack and a parsing table. The LR stack contains –terminal symbols –nonterminal symbols –states (we ’ ll discuss these later) The LR parsing table consists of two tables: –the action table –the goto table
41
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-41 Structure of An LR Parser
42
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-42 The action table The action table has –a row for each state of the parser –a column for each terminal symbol of the grammar and $, the end of input symbol. –entries that are actions taken by the parser: shift s, where s is a state reduce by a grammar production A accept error
43
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-43 The goto table The goto table has –a row for each state of the parser –a column for each nonterminal symbol of the grammar. –entries that are states to which the parser makes a transition when a reduce operation occurs.
44
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-44 LR Parser Configuration A configuration of an LR parser is a pair –the first component is the stack contents –the second component is the unexpended input In more formal notation, a configuration looks like this (stack contents in red, unexpended input in blue): ( s 0 X 1 s 1 X 2 s 2... X m s m, a i a i+1... a n $ )
45
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-45 LR Parsing Algorithm At each step of the parse, the LR parser examines the current configuration ( s 0 X 1 s 1 X 2 s 2... X m s m, a i a i+1... a n $ ) to determine s m (the state on the top of the stack) and a i (the current input symbol) The parser then consults action[s m,a i ] to determine its next move. This move will cause the parser to enter a new configuration.
46
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-46 The shift operation If action [s m, a i ] = shift s, the parser executes a shift move, going from configuration ( s 0 X 1 s 1 X 2 s 2... X m s m, a i a i+1... a n $ ) to the new configuration ( s 0 X 1 s 1 X 2 s 2... X m s m a i s, a i+1... a n $ ) Here the parser has shifted both the current input symbol a i and the next state s onto the stack. a i+1 becomes the current input symbol.
47
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-47 The reduce operation If action [s m, a i ] = reduce A , then the parser executes a reduce move, going from the configuration ( s 0 X 1 s 1 X 2 s 2... X m s m, a i a i+1... a n $ ) to the new configuration ( s 0 X 1 s 1 X 2 s 2... X m-r s m-r A s, a i a i+1... a n $ ) where s = goto[s m-r, A] and r = | | The parser performs the following actions: –pops 2r symbols off the stack (r state symbols and r grammar symbols), exposing state s m-r. –pushes both A, the left side of the production, and s, the entry for goto[s m-r, A] onto the stack. The current input symbol is not changed.
48
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-48 LR Parser Output The output of an LR parser is generated after a reduce move by executing the semantic action associated with the reducing production. For the time being we shall assume the output consists of just printing the reducing production.
49
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-49 LR Parsing Algorithm push the start state s 0 onto the stack. while (true) begin s = state on top of the stack and a = input symbol pointed to by input pointer ip if action[s,a] = shift s' then begin push a then s' onto the stack advance ip to the next input symbol end else if action[s,a] = reduce A then begin pop 2*| | symbols off the stack, exposing state s' push A then goto[s',A] onto the stack output production A end else if action = accept then return else error() end
50
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-50 Parse Table For Expression Grammar Rules: 1. E E + T 2. E T 3. T T * F 4. T F 5. F ( E ) 6. F id Notation: R for reduce r4 means reduce using rule 4 S for shift s6 means shift the next symbol of input onto the stack and push state 6 onto the stack actiongoto State id+*()$ETF 0 s5s4123 1 s6acc 2 r2s7r2 3 r4 4 s5s4823 5 r6 6 s5s493 7 s5s410 8 s6s11 9 r1s7r1 10 r3 11 r5 Empty positions in the ACTION table indicate syntax errors
51
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-51 Parse of input id * id + id StackInputAction 1. 0 2. 0 id 5 3. 0 F 3 4. 0 T 2 5. 0 T 2 * 7 6. 0 T 2 * 7 id 5 7. 0 T 2 * 7 F 10 8. 0 T 2 9. 0 E 1 10. 0 E 1 + 6 11. 0 E 1 + 6 id 5 12. 0 E 1 + 6 F 3 13. 0 E 1 + 6 T 9 14. 0 E 1 id * id + id $ * id + id $ id + id $ + id $ id $ $ shift reduce by F id reduce by T F shift reduce by F id reduce by T T * F reduce by E T shift reduce by F id reduce by T F reduce by E E + T accept $ an end mark
52
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-52 Parse of input id * id + id actiongoto State id+*()$ETF 0s5s4123 1s6acc 2r2s7r2 3r4 4s5s4823 5r6 6s5s493 7s5s410 8s6s11 9r1s7r1 10r3 11r5 StackInputAction 1. 0 2. 0 id 5 3. 0 F 3 4. 0 T 2 5. 0 T 2 * 7 6. 0 T 2 * 7 id 5 7. 0 T 2 * 7 F 10 8. 0 T 2 9. 0 E 1 10. 0 E 1 + 6 11. 0 E 1 + 6 id 5 12. 0 E 1 + 6 F 3 13. 0 E 1 + 6 T 9 14. 0 E 1 id * id + id $ * id + id $ id + id $ + id $ id $ $ shift reduce by F id reduce by T F shift reduce by F id reduce by T T * F reduce by E T shift reduce by F id reduce by T F reduce by E E + T accept 1. E E + T 2. E T 3. T T * F 4. T F 5. F ( E ) 6. F id
53
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-53 Things to Note Reverse the production sequence: F id T F F id T T * F E T F id T F E E + T and do a rightmost derivation: E E + T E + F E + id T + id T * F + id T * id + id F * id + id id * id + id
54
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-54 More Things to Note Only terminal symbols (tokens) are shifted onto the parse stack. The only way nonterminal symbols get on the stack is through a reduce operation. A reduce operation is always coupled with a goto operation, in which a state is shifted onto the parse stack.
55
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-55 Bottom-up Parsing LR parsers must be constructed with a tool Knuth’s insight: A bottom-up parser could use the entire history of the parse, up to the current point, to make parsing decisions –There were only a finite and relatively small number of different parse situations that could have occurred, so the history could be stored in a parser state, on the parse stack
56
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-56 Bottom-up Parsing An LR configuration stores the state of an LR parser (S 0 X 1 S 1 X 2 S 2 …X m S m, a i a i +1…a n $)
57
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-57 Bottom-up Parsing LR parsers are table driven, where the table has two components, an ACTION table and a GOTO table –The ACTION table specifies the action of the parser, given the parser state and the next token Rows are state names; columns are terminals –The GOTO table specifies which state to put on top of the parse stack after a reduction action is done Rows are state names; columns are nonterminals
58
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-58 Bottom-up Parsing Initial configuration: (S 0, a 1 …a n $) Parser actions: –If ACTION[S m, a i ] = Shift S, the next configuration is: (S 0 X 1 S 1 X 2 S 2 …X m S m a i S, a i+1 …a n $) –If ACTION[S m, a i ] = Reduce A and S = GOTO[S m-r, A], where r = the length of , the next configuration is (S 0 X 1 S 1 X 2 S 2 …X m-r S m-r AS, a i a i+1 …a n $)
59
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-59 Bottom-up Parsing Parser actions (continued): –If ACTION[S m, a i ] = Accept, the parse is complete and no errors were found. –If ACTION[S m, a i ] = Error, the parser calls an error-handling routine.
60
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-60 LR Parsing Table
61
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-61 Bottom-up Parsing A parser table can be generated from a given grammar with a tool, e.g., yacc
62
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-62 Summary of Recursive Descent Simple and general parsing strategy –Left-recursion must be eliminated first –… but that can be done automatically Unpopular because of backtracking –Thought to be too inefficient In practice, backtracking is eliminated by restricting the grammar, allowing us to successfully predict which rule to use.
63
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-63 自底向上分析方法 移进 - 归约 自底向上分析方法,也称移进 - 归约分析 法。 实现思想: 将输入 符逐个移入一个后进先出栈中 一旦栈顶符号串形成某个句型的句柄时, 就用 左部代替 归约 – 对输入符号串自左向右进行扫描,并将输入 符逐个移入一个后进先出栈中,边移入边分 析,一旦栈顶符号串形成某个句型的句柄时, (该句型对应某产生式的右部),就用该产 生式的左部非终结符代替相应右部的文法符 号串,这称为归约。 – 重复这一过程直到归约到栈中只剩文法的开 始符号时则为分析成功 – 重复这一过程直到归约到栈中只剩文法的开 始符号时则为分析成功,也就确认输入串是 文法的句子。
64
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-64 文法 G[S] : (1) S → aAcBe (2) A → b (3) A → Ab (4) B → d abbcde 步骤符号栈输入符号串动作 1 ) # abbcde# 移进 2 ) #a bbcde# 移进 A 3 ) #ab bcde# 归约 (A → b) 4 ) #aA bcde# 移进 A 5 ) #aAb cde# 归约 (A → Ab) 6 ) #aA cde# 移进 7 ) #aAc de# 移进 B 8 ) # aAcd e# 归约 (B → d) 9 ) #aAcB e# 移进 11 ) #S # 接受 S 10 ) #aAcBe # 归约 (S → aAcBe) 分析符号串 abbcde 是否 G[S] 的句子 对输入串 abbcde# 的移进 - 规约分析过程 S aAcBe aAcde aAbcde abbcde
65
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-65 文法 G[S] : (1) S → bAb (2) A → (B|a (3) B → Aa) 步骤符号栈输入符号串动作 1 ) # b(aa)b# #<b, 移进 2 ) #b (aa)b# b<(, 移进 3 ) #b( aa)b# (<a, 移进 4 ) #b(a a)b# a>a, 归约 A → a 5 ) #b(A a)b# A=a, 移进 6 ) #b(Aa )b# a=), 移进 7 ) #b(Aa) b# )>b, 归约 B → Aa) 8 ) #b(B b# B>b, 归约 A → (B 9 ) #bA b# A=b, 移进 10 ) #bAb # b>#, 归约 S → bAb 11 ) #S # 接受 对输入串 b(aa)# 的简单优先分析过程 简单优先关系矩阵
66
Copyright © 2004 Pearson Addison-Wesley. All rights reserved.4-66
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.