SlideShare a Scribd company logo
1 of 43
Download to read offline
Compiler Lecture Note, LL Parsing Page 1
컴파일러 입문
제 7 장
LL 구문 분석
Compiler Lecture Note, LL Parsing Page 2
I. 결정적 구문 분석
II. Recursive-descent 파서
III. Predictive 파서
VI. Predictive 파싱 테이블의 구성
V. Strong LL(k) 문법과 LL(k) 문법
목 차
Compiler Lecture Note, LL Parsing Page 3
I. 결정적 구문 분석
▶ Deterministic Top-Down Parsing
::= deterministic selection of production rules to be applied
in top-down syntax analysis.
▶ One pass nobackup
1. Input string is scanned once from left to right.
2. Parsing process is deterministic.
▶ Top-down parsing with nobackup
::= deterministic top-down parsing.
called LL parsing.
"Left to right scanning and Left parse"
Compiler Lecture Note, LL Parsing Page 4
▶ LL parsing
- backtracking이 없이 deterministic한 top-down parsing
⇒ 문법이 LL 조건 만족해야
- LL이란? Left-to-right scanning & Leftmost derivation
- 현재의 input symbol을 보고 적용될 생성규칙을 deterministic하게
선택
▶ How to decide which production is to be applied:
sentential form : 1 2 … i-1Xα
input string : 1 2 … i-1 i i+1 … n
 X  1 | 2 ... | k ∈ P일 때,
i를 보고 X-production 중에 unique하게 결정.
 the condition for no backtracking : FIRST와 FOLLOW가 필요.
(= LL condition)
FIRST
• 문법 G = (VN, VT, P, S)가 context-free 문법이고 A∈VN, a∈VT일 때, non-
terminal A에 대한 FIRST는 다음과 같이 정의
FIRST(A) = {a∈VT∪{} | A⇒a,  ∈V*}.
non-terminal A로부터 유도되어 첫번째로 나타날 수 있는 terminal의 집합
– 예 : 다음 생성 규칙에서 각 non-terminal에 대한 FIRST
A → aB | B
B → bC | C
C → c
Compiler Lecture Note, LL Parsing Page 5
X
FIRST(X)
 1. A ⇒ aB
A ⇒ B ⇒ bC
A ⇒ B ⇒ C ⇒ c
∴ FIRST(A) = {a, b, c}.
2. B ⇒ bC
B ⇒ C ⇒ c
∴ FIRST(B) = {b, c}.
3. C ⇒ c
∴ FIRST(C) = {c}.
• Non-terminal A가 을 유도할 수 있으면 A를 nullable하다고 부른다.
– A⇒ 이면 nullable하다.
• 두 개의 집합에 대한 연산자인 ring sum은 다음과 같이 정의 되면
기호  를 사용한다.
1. if   A then A  B = A
2. if   A then A  B = (A – {})∪B.
– Ring sum의 의미
• 첫 번째 피 연산자의 집합이 을 갖지 않으면 그 자신
• 을 포함하고 있으면 을 제외한 첫 번째 피 연산자와 두 번째 피 연산자를 합집합
한 것
– 예 : {a, b, c}  {c, d} = {a, b, c}.
{a, b, c, }  {c, d} = {a, b, c, d}.
{a, b, }  {c, d, } = {a, b, c, d, }.
Compiler Lecture Note, LL Parsing Page 6
• FIRST(A1A2 ···An) = FIRST(A1)  FIRST(A2)  ··· FIRST(An)
– 스트링의 FIRST : nullable이 아닌 심벌까지의 FIRST를 합집합 한 것
– 각 생성 규칙에 따라 FIRST(X)를 계산하는 방법
1. X가 terminal이면 X의 FIRST는 자기 자신
FIRST(X) = {X} if X∈VT.
2. X → a 의 생성 규칙이 존재하면 a가 FIRST(X)에 포함
FIRST(X) = FIRST(X) ∪ {a} if X → a∈P and a∈VT.
또한, X가  –생성 규칙을 가지면 X의 FIRST에  이 포함
FIRST(X) = FIRST(X) ∪ {} if X → ∈P.
3. X → Y1Y2 ···Yk인 생성 규칙이 있을 때,
FIRST(X) = FIRST(X) ∪ FIRST(Y1Y2 ···Yk).
Compiler Lecture Note, LL Parsing Page 7
Compiler Lecture Note, LL Parsing Page 8
ex1) E  TE E  +TE | 
T  FT T  FT | 
F  (E) | id
FIRST(E) = FIRST(T) = FIRST(F) = {(, id}
FIRST(E) = {+, }
FIRST(T) = {, }
ex2) PROGRAM  begin d semi X end
X  d semi X
X  s Y
Y  semi s Y | 
FIRST(PROGRAM) = {begin}
FIRST(X) = {d,s}
FIRST(Y) = {semi, }
FOLLOW
• FOLLOW
– Non-terminal A가 nullable하면 FIRST(A)에  이 속하게 되어
FIRST를 가지고는 생성 규칙을 결정적으로 선택할 수 없음
–  -생성 규칙을 갖는 문법에서는 non-terminal 다음에 오는 terminal 심벌이 의
미를 가짐
• 정의 : FOLLOW(A) = {a ∈ VT∪{$} | S ⇒ Aa, , ∈ V*}
– $ : 입력 스트링의 끝을 표기하는 마커 심벌(marker symbol)
– Non-terminal A의 FOLLOW란 시작 심벌로부터 유도될 수 있는 모든 문장 형
태에서 A 다음에 나오는 terminal 심벌의 집합
• FOLLOW를 계산하기 위해서는 모든 문장 형태를 고려해야 하나,
문장 형태는 생성 규칙의 rhs들로 이루어져 있으므로,
생성 규칙의 rhs를 이용하여 FOLLOW를 구할 수 있음.
Compiler Lecture Note, LL Parsing Page 9
• 각 생성 규칙의 형태에 따른 FOLLOW를 계산하는 방법
1. 시작 심벌은 $를 초기 값으로 갖는다.
FOLLOW(S) = {$}
2. 생성 규칙의 형태가 A→B ,    일 때, FIRST()에서  를 제외한 terminal
심벌을 B의 FOLLOW에 추가한다.
if A→B ,    then FOLLOW(B) = FOLLOW(B) ∪(FIRST() – {}).
3. A→B 이거나, A→B 에서 FIRST()가 이 속하는 경우(즉  ⇒  ), A의
FOLLOW 전체를 B의 FOLLOW에 추가한다.
if A→B ∈ P or (A→B and  ⇒  ) then
FOLLOW(B) = FOLLOW(B) ∪ FOLLOW(A).
– 계산 과정 3번의 의미
• 임의의 문장 형태에서 A 다음에 나올 수 있는 심벌은 모두 B 다음에 나올 수 있음
S ⇒ 1A2 ⇒ 1B2 ⇒ 1B2
• FOLLOW 속성으로 인하여 A→B, B→A 와 같은 형태의 생성 규칙을 갖고 있으
면 FOLLOW(A) = FOLLOW(B) 가 됨.
∵ 전자 형태의 생성 규칙으로부터 FOLLOW (A) ⊆ FOLLOW(B)
후자 형태의 생성 규칙으로부터 FOLLOW (A) ⊇ FOLLOW(B)
Compiler Lecture Note, LL Parsing Page 10
Compiler Lecture Note, LL Parsing Page 11
ex) E  TE‟ E'  +TE' | 
T  FT‟ T'  FT' | 
F  (E) | id
Nullable = { E, T }
FIRST(E) = FIRST(T) = FIRST(F) = {(, id}
FIRST(E) = {+, } FIRST(T) = {, }
FOLLOW(E) = {),$} FOLLOW(E') = {),$}
FOLLOW(T) = {+,),$} FOLLOW(T') = {+,),$}
FOLLOW(F) = {,+,),$}
Compiler Lecture Note, LL Parsing Page 12
▶ LL condition
::= no backup condition
::= the condition for deterministic parsing of top-down method.
input : 12 ... i-1i ...n
derived string : 12...i-1X
X  1 | 2 ... | m
 i를 보고 X-production들 중에서 X를 확장할 rule을
결정적으로 선택.
★ <LL condition> A   | ∈ P,
1. FIRST()  FIRST() = 
2. if  * , FOLLOW(A)  FIRST() = 
– 예 : 다음 문법을 가지고 스트링 i[e] ← e를 결정적으로 구문 분석할 수 있는지
알아보자
A → iB ← e
B → SB | 
S → [eC] | .i
C → eC | 
 (1) LL 조건 테스트 :
Compiler Lecture Note, LL Parsing Page 13
1. NULLABLE = {B, C}
2. FIRST(A) = {i}
FIRST(B) = {[, ., }
FIRST(S) = {[, .}
FIRST(C) = {e, }
3. FOLLOW(A) = {$}
FOLLOW(B) = {←}
FOLLOW(S) = {[, ., ←}
FOLLOW(C) = {]}
4. FIRST 와 FOLLOW를 이용하여 LL 조건을 테스트
1) B → SB |  에서,
FIRST(SB) ∩ FOLLOW(B) = {[, .} ∩ {←} = 
2) S → [eC] | .i 에서,
FIRST([eC]) ∩ FIRST(.i) = {[} ∩ {.}= 
3) C → eC |  에서,
FIRST(eC) ∩ FOLLOW(C) = {e} ∩ {]}= 
1. FIRST() ∩ FIRST() = 
2. if  ∈ FIRST() then FOLLOW(A) ∩ FIRST() = 
(2) 좌측 유도 과정 :
<문장 형태> <입력 스트링>
A ⇒ iB ← e
⇒ iSB ← e
⇒ i[eC]B ← e
⇒ i[e]B ← e
⇒ i[e] ← e
1. 입력 스트링 첫 심벌 i를 보고 시작 심벌 A를 첫 번째 생성 규칙으로 확장
2. 생성된 문장 형태 iB ← e 에서 첫 심벌 i와 입력 스트링 i가 같으므로 다음 심벌 비
교
3. 문장 형태의 다음 심벌은 non-terminal B이고, 현재의 입력 심벌은 [이므로 B-생성
규칙 중에서 [를 유도 할 수 있는 생성 규칙 B → SB를 적용하여 유도
• 이와 같은 과정을 계속 진행하면 시작 심벌로부터 주어진 스트링을 결정적으로
유도할 수 있다.
– FIRST와 FOLLOW는 이와 같이 문장 형태에서 각 non-terminal 이 생성할 수
있는 스트링이 무엇인지를 가리켜 주어서 현재의 입력 심벌을 보고 생성 규
칙을 결정적으로 선택할 수 있게 해준다.
Compiler Lecture Note, LL Parsing Page 14
i[e] ← e
↑
i[e] ← e
↑
i[e] ← e
↑
i[e] ← e
↑
i[e] ← e
↑
Compiler Lecture Note, LL Parsing Page 15
ex) A  aBc | Bc | dAa
B  bB | 
FIRST(A) = {a,b,c,d} FOLLOW(A) = {$,a}
FIRST(B) = {b, } FOLLOW(B) = {c}
1) A  aBc | Bc | dAa에서,
FIRST(aBc)  FIRST(Bc)  FIRST(dAa)
= {a}  {b,c}  {d} = 
2) B  bB |  에서,
FIRST(bB)  FOLLOW(B) = {b}  {c} = 
1), 2)에 의해 LL 조건을 만족한다.
II. Recursive-descent 파서
• LL 방법을 실제로 parsing algorithm으로 사용하는 syntax analyzer
– Recursive-descent parser
– Predictive parser
• Recursive-descent parser
– LL 방법의 일종
– 주어진 입력 스트링을 parsing하기 위하여 일련의 순환 프로시저(recursive
procedure)를 사용
– 각 순환 프로시저는 각 non-terminal 에 해당하는 것으로 non-terminal에 대한
유도를 프로시저 호출로 처리하는 방법
• Recursive-descent parser를 구현 하는 방법
– 각 non-terminal에 대한 프로시저를 작성-통합하여 전체적인 프로그램 구성
• 각 프로시저 내에서 입력 심벌에 따라 어떤 생성 규칙을 선택하느냐가 중요
• 한 생성 규칙을 적용했을 때 생성할 수 있는 terminal들을 알아야 함 :
“LOOKAHEAD”
• 현재의 입력 심벌이 한 생성 규칙의 LOOKAHEAD에 속하면 생성규칙으로 확장
할 수 있도록 프로시저 작성
Compiler Lecture Note, LL Parsing Page 16
• LOOKAHEAD 정의와 계산 방법
LOOKAHEAD(A → ) = FIRST( {| S ⇒ A ⇒  ⇒  ∈ VT
*}).
LOOKAHEAD(A → X1X2 ···Xn)
= FIRST(X1)  FIRST(X2)  ··· FIRST(Xn)  FOLLOW(A).
– rhs의 FIRST가 되든지, rhs가 를 유도할 수 있으면 lhs의 FOLLOW 도 속함
– 생성 규칙의 형태에서, rhs가 terminal로 시작하는 생성 규칙의 LOOKAHEAD
는 바로 그 terminal 심벌만이 된다.
ex) LOOKAHEAD(A → a) = {a}
– 예 : 다음의 문법에서 생성 규칙의 LOOKAHEAD를 구하자.
E → TE‟ E' → +TE' | 
T → FT‟ T' → *FT' | 
F → (E) | id
 LOOKAHEAD(E → TE') = FIRST(T)  FIRST(E')  FOLLOW(E)
= {(, id}  {+, }  {), $}
= {(, id}
LOOKAHEAD(E'→ +TE') = FIRST(+)  FIRST(T)  FIRST(E')  FOLLOW(E')
= {+}  {(, id}  {+, }  {), $}
= {+}
Compiler Lecture Note, LL Parsing Page 17
E → TE‟ E' → +TE' | 
T → FT‟ T' → *FT' | 
F → (E) | id
LOOKAHEAD(E' → ) = FIRST()  FOLLOW(E')
= {), $}
LOOKAHEAD(T → FT') = FIRST(F)  FIRST(T')  FOLLOW(T)
= {(, id}  {*, }  {), $}
= {(, id}
LOOKAHEAD(T → *FT') = FIRST(*)  FIRST(F)  FIRST(T')  FOLLOW(T')
= {*}  {(, id}  {*, }  {+, ), $}
= {*}
LOOKAHEAD(T' → ) = FIRST() FOLLOW(T')
= {+, ), $}
LOOKAHEAD(F → (E)) = FIRST(()  FIRST(E)  FIRST())  FOLLOW(F)
= {(}  {(, id}  {(}  {*, +, ), $}
= {(}
LOOKAHEAD(F → id) = FIRST(id)  FOLLOW(F)
= {id}  {*, +, ), $}
= {id}
Compiler Lecture Note, LL Parsing Page 18
Compiler Lecture Note, LL Parsing Page 19
▶ Strong LL condition
 Definition : A   |  ∈ P,
LOOKAHEAD(A  )  LOOKAHEAD(A  ) = .
 Meaning : for each distinct pair of productions with the same
left-hand side, it can select the unique alternate
that derives a string beginning with the input symbol.
 Definition : the grammar G is said to be strong LL(1)
if it satisfies the strong LL condition.
ex) G : S  aSA | 
A  c
 LOOKAHEAD(S  aSA) = {a}
 LOOKAHEAD(S  ) = FOLLOW(S) = {$, c}
LOOKAHEAD(S  aSA)  LOOKAHEAD(S  ) = 
 G는 strong LL(1)이다.
– 예 : 다음 문법이 strong LL(1) 문법인지를 살펴보자.
S → bRS | RcSa | 
R → acR | b
 먼저, 택일 생성 규칙에 대해 LOOKAHEAD를 구해야 한다.
1. LOOKAHEAD(S → bRS)
= FIRST(b)  FIRST(R)  FIRST(S)  FOLLOW(S)
= {b}  {a, b}  {a, b, }  {a, $}
= {b}
2. LOOKAHEAD(S → RcSa)
= FIRST(R)  FIRST(c)  FIRST(S)  FIRST(a)  FOLLOW(S)
= {a, b}  {c}  {a, b, }  {a} {a, $}
= {a, b}
LOOKAHEAD(S → bRS) ∩ LOOKAHEAD(S → RcSa) = {b}
∴ strong LL 문법이 아니다.
– 위 문법이 strong LL 문법이 아니므로 syntax analysis 시 적용할 생성 규칙을
결정적으로 선택할 수 없다.
• 현재의 입력 심벌이 b이고 확장해야 될 non-terminal이 S일 때, 생성 규칙 S → bRS
와 S → RcSa 가 모두 b를 생성 하므로 어느 생성 규칙을 적용할지 알 수 없다.
Compiler Lecture Note, LL Parsing Page 20
Compiler Lecture Note, LL Parsing Page 21
▶ Implementation of Recursive-descent parser
 If a grammar is strong LL(1), we can construct a parser for sentences of the
grammar using the following scheme.
 a ∈ VT,
procedure pa; (* get_nextsymbol=scanner *)
begin
if nextsymbol = ta then get_nextsymbol
else error
end;
 get_nextsymbol : 스캐너에 해당하는 루틴으로 입력 스트림으로부터
토큰 한 개를 읽어 전역변수 nextsymbol에 할당
- ta : terminal symbol a의 token number
Compiler Lecture Note, LL Parsing Page 22
 A ∈ VN,
procedure pA;
begin
case nextsymbol of
LOOKAHEAD(A  X1X2...Xm): for i := 1 to m do pXi;
LOOKAHEAD(A  Y1Y2...Yn): for i := 1 to n do pYi;
:
LOOKAHEAD(A  Z1Z2...Zr): for i := 1 to r do pZi;
LOOKAHEAD(A  ): ;
otherwise: error
end (* case *)
end;
 메인 프로그램 begin (* main *)
get_nextSymbol;
pS;
if nextSymbol = q$ then accept else error
end.
• 예 : 다음 문법을 위한 recursive-descent 프로시저를 구성하자
S → aAb
A → aS | b
Compiler Lecture Note, LL Parsing Page 23
(1) Terminal 심벌에 대한 프로시저
procedure pa;
begin
if nextSymbol = ta
then get_nextSymbol
else error
end; (* pa *)
procedure pb;
begin
if nextSymbol = tb
then get_nextSymbol
else error
end; (* pb *)
(2) Non-terminal 심벌에 대한 프로시저
procedure pS;
begin
if nextSymbol = ta
then begin pa; pA; pb end
else error
end; (* pS *)
procedure pA;
begin
case nextSymbol of
ta : begin pa; pS end;
tb : pb;
otherwise : error
end (* case *)
end; (* pA *)
Compiler Lecture Note, LL Parsing Page 24
▶ Improving the efficiency and structure of recursive-descent parser
1) Eliminating terminal procedures
::= In practice it is better not to write a procedure for each terminal.
Instead the action of advancing the input marker can always be initiated
by the nonterminal procedures. In this way many redundant tests can
be eliminated.
 (1) Non -terminal S에 대한 프로시저 :
procedure pS
begin
if nextSymbol = qa then
begin get_nextSymbol;
pA;
if nextSymbol = qb then get_nextSymbol
else error
end
else error
end; (* pS *)
(2) Non -terminal A에 대한 프로시저 :
procedure pA;
begin
case nextSymbol of
qa : begin get_nextSymbol; pS end;
qb : get_nextSymbol;
otherwise : error
end (* case *)
end; (* pA *)
Compiler Lecture Note, LL Parsing Page 25
▶ Improving the efficiency and structure of recursive-descent parser
2) BNF  EBNF : reduce the number of productions and nonterminals.
① repetitive part : { }
② optional part : [ ]
③ alternation : ( | )
ex) < IF_st > ::= ' if ' < cond > ' then ' < st > [ ' else ' < st > ]
procedure pIF;
begin if nextsymbol = tif then
begin get_nextsymbol; pCOND;
if nextsymbol = tthen then
begin get_nextsymbol; pST end
else error(10)
end
else error(20);
if nextsymbol = telse then
begin get_nextsymbol; pST end
end;
Compiler Lecture Note, LL Parsing Page 26
ex) <id_list> ::= ' id ' { ' , ' ' id ' }
procedure pID_LIST;
begin if nextsymbol = tid then
begin get_nextsymbol;
while (nextsymbol = tcomma) do
begin get_nextsymbol;
if nextsymbol = tid then get_nextsymbol
else error(100)
end
end
end;
• Recursive-descent 파서
– 생성 규칙에 대한 프로시저를 작성함으로써 syntax analyzer를
구현한 프로그램으로 생성규칙이 바뀔 때 마다 syntax analyzer
를 구현한 프로그램을 다시 고쳐야 하는 단점이 존재
Compiler Lecture Note, LL Parsing Page 27
[연습문제 7.8 (2)] 다음 grammar를 extended BNF로 바꾸고 그에 따른
recursive-descent parser를 위한 procedure를 작성하시오.
<D> ::= ' label ' <L> | ' integer ' <L>
<L> ::= <id> <R>
<R> ::= ' ; ' | ' , ' <L>
 <D> ::= ( ' label ' | ' integer ' ) <id> {' , ' <id>} ' ; „
procedure pD;
begin if nextsymbol in [tlabel,tinteger] then
begin get_nextsymbol;
if nextsymbol = qid then
begin get_nextsymbol;
while (nextsymbol = qcomma) do
begin get_nextsymbol;
if nextsymbol = qid then get_nextsymbol else error(3)
end
end
else error(2);
if nextsymbol = qsemi then get_nextsymbol else error(4)
end
else error(1)
end;
*
<L>  <id> (' , ' <id> )* ' ; '
Compiler Lecture Note, LL Parsing Page 28
III. Predictive Parsing
▶ Predictive parsing
::= a deterministic parsing method using a stack.
The stack contains a sequence of grammar symbols.
▶ Model of a predictive parser
Input
Output
Stack
a1 a2 ······ an$
X
$
···
Driver Routine
Predictive
Parsing Table
Compiler Lecture Note, LL Parsing Page 29
 Current input symbol과 stack top symbol 사이의 관계에 따라 parsing.
 The input buffer contains the string to be parsed, followed by $.
 Initial configuration : STACK INPUT
$S $
 Parsing table(LL) : parsing action을 결정지어 줌.
※ M[X,a] = r : stack top symbol이 X이고 current symbol이 a일 때,
r번 생성 규칙으로 expand.
r
terminals
nonterminals X
a
Compiler Lecture Note, LL Parsing Page 30
▶ Parsing Actions
X : stack top symbol, a : current input symbol
1. if X = a = $, then accept.
2. if X = a, then pop X and advance input.
3. if X ∈ VN, then if M[X,a] = r (X), then replace X by 
else error.
– 예 : 다음은 주어진 문법에 따른 predictive 파싱 테이블이다.
주어진 문법 : 파싱 테이블 :
1. S → aSb 2. S → bA
3. A → aA 4. A → b
• Empty entry 는 error
• 스택 top이 S이고 현재 입력 심벌이 a이면 1번 생성 규칙으로 확장하라는 의미
VN
VT a b $
S 1 2
A 3 4
– Predictive 파서의 driver routine
• 주어진 입력 스트링을 왼쪽에서 오른쪽으로 읽어가며 현재의 입력 심벌
과 스택의 top 심벌에 따라 구문 분석을 수행
• 파싱 테이블은 이와 같은 파싱 행동을 제어한다.
– 파싱 행동의 종류와 의미
1. Pop : 스택의 top과 현재의 입력 심벌이 같은 경우로 스택의 top 심벌은 스
택에서 제거하고 현재 입력 심벌은 입력 스트링에서 제거
2. Expand : 스택의 top이 non-terminal인 경우로 생성 규칙을 적용하여 확장
 M[A, a] = {A → XYZ}일 때, A를 스택에서 제거하고 rhs의 역순인 ZYX를
차례로 스택에 넣어 X가 스택 top이 되게 한다.
3. Accept : 스택이 top 심벌과 현재의 입력 심벌 모두가 $인 경우로 주어진
입 력 스트링이 올바른 스트링임을 알리고 파싱을 종료
4. Error : 스택의 top이 non-terminal 심벌인 경우로 그 심벌로부터 현재 보고
있는 입력 심벌을 결코 유도할 수 없음을 나타낸다.
Compiler Lecture Note, LL Parsing Page 31
Compiler Lecture Note, LL Parsing Page 32
• Predictive 파서의 구문 분석 방법
Algorithm Predictive_Parser_Action;
begin
repeat
if X ∈ VT∪{$} then
(* pop *)
if X = a then begin pop X; get_nextSymbol end else error fi
else (* X : non-terminal *)
(* expand *)
if M[X, a] = X → Y1Y2 ···Yk then 스택에서 X를 제거하고 rhs의
역순으로 YkYk-1 ···Y1 을 차례로 스택에 넣는다.
else error fi
fi
until X = a = $ (* accept : 스택에 $만 남을 때까지 반복 *)
end.
– X : 스택 top의 심벌
– a : 현재 입력 심벌
Compiler Lecture Note, LL Parsing Page 33
• 예 : 다음과 같이 문법과 그에 따른 predictive 파싱 테이블이 주어졌을 때, 스
트링 aabccd에 대한 구문 분석을 수행하고 그 결과로 좌 파스를 구해보자.
주어진 문법 : 1. S → aS 2. S → bA 파싱 테이블 :
3. A → d 4. A → ccA
파싱 테이블 을 이용한 predictive 구문 분석 :
VN
VT a b c d $
S 1 2
A 4 3
Step Stack Input Action parse
1 $S aabccd$ Expand 1 1
2 $Sa aabccd$ Pop & advance 1
3 $S abccd$ Expand 1 1 1
4 $Sa abccd$ Pop & advance 1 1
5 $S bccd$ Expand 2 1 1 2
6 $Ab bccd$ Pop & advance 1 1 2
7 $A ccd$ Expand 4 1 1 2 4
8 $Acc ccd$ Pop & advance & Pop & advance 1 1 2 4
9 $A d$ Expand 3 1 1 2 4 3
10 $d d$ Pop & advance 1 1 2 4 3
11 $ $ Accept 1 1 2 4 3
Compiler Lecture Note, LL Parsing Page 34
VI. Predictive 파싱 테이블의 구성
▶ main idea : If A   is a production with a in FIRST(), then
the parser will expand A by  when the current
input symbol is a. And if  * , then we should
again expand A by  when the current input symbol
is in FOLLOW(A).
▶ parsing table(LL):
M[X,a] = r : expand X with r-production
blank : error
VT a
X
VN
Compiler Lecture Note, LL Parsing Page 35
▶ Algorithm : for each production A,
1. a ∈ FIRST(), M[A,a] := <A>
2. if  * , then b ∈ FOLLOW(A), M[A,b] := <A>.
ex) G: 1. E  TE' 2. E'  +TE' 3. E'   4. T  FT'
5. T'  FT' 6. T'   7. F  (E) 8. F  id
FIRST(E)=FIRST(T)=FIRST(F)={ ( , id }
FIRST(E')={ + ,  } FIRST(T')={  ,  }
FOLLOW(E) = FOLLOW(E') = { ) , $ }
FOLLOW(T) = FOLLOW(T') = { + , ) , $ }
FOLLOW(F) = { + ,  , ) , $ }
78F
6656T'
44T
332E'
11E
$)(*+idVTVN
Compiler Lecture Note, LL Parsing Page 36
• 예 : id * id + id
주어진 문법 : 파싱 테이블 :
1. E  TE' 2. E'  +TE' 3. E'  
4. T  FT‟ 5. T'  FT' 6. T'  
7. F  (E) 8. F  id
파싱 테이블 을 이용한 predictive 구문 분석 :
Step Stack Input Action parse
1 $E id * id + id$ Expand 1 1
2 $E‟T id * id + id$ Expand 4 1 4
3 $E‟T‟F id * id + id$ Expand 8 1 4 8
4 $E‟T‟id id * id + id$ Pop id & advance 1 4 8
5 $E‟T‟ * id + id$ Expand 5 1 4 8 5
6 $E‟T‟F* * id + id$ Pop * & advance 1 4 8 5
7 $E‟T‟F id + id$ Expand 8 1 4 8 5 8
8 $E‟T‟id id + id$ Pop id & advance 1 4 8 5 8
9 $E‟T‟ + id$ Expand 6 1 4 8 5 8 6
10 $E‟ + id$ Expand 2 1 4 8 5 8 6 2
11 $E‟T+ + id $ Pop + & advance 1 4 8 5 8 6 2
12 $E‟T id$ Expand 4 1 4 8 5 8 6 2
13 $E‟T‟F id$ Expand 8 & pop id & advance 1 4 8 5 8 6 2 8
14 $E‟T‟ $ Expand 6 & expand 3 1 4 8 5 8 6 2 8 6 3
78F
6656T'
44T
332E'
11E
$)(*+idVTVN
Compiler Lecture Note, LL Parsing Page 37
▶ LL(1) Grammar
::= a grammar whose parsing table has no multiply-defined entries.
 multiply 정의되면 어느 rule로 expand해야 할 지 결정할 수 없기 때
문에 deterministic하게 parsing할 수 없다.
▶ LL(1) condition: A   | ,
1. FIRST( )  FIRST() = .
2. if   , then FOLLOW(A)  FIRST() =  .
ex) G : 1. S  iCtSS' 2. S  a 3. S'  eS 4. S'   5. C  b
FIRST(S) = {i,a} FOLLOW(S) = {$,e}
FIRST(S') = {e, } FOLLOW(S') = {$,e}
FIRST(C) = {b} FOLLOW(C) = {t}
• 위 문법은 LL(1) 문법이 아니다.
• 대부분의 경우 중복이 일어나지 않게 문법을 다시 쓰는 것이 보편적
*
3, 4
5C
4S'
12S
$tiebaVTVN
Compiler Lecture Note, LL Parsing Page 38
V. Strong LL(k) and LL(k) Grammars
▶ FIRSTk() = {|  * , || = k or    and || < k}
▶ G is said to be strong LL(k), for some fixed integer k > 0, if
whenever there are two leftmost derivations.
1. S * A   * x∈ VT
*, and
2. S * A   * y∈ VT
* such that
3. FIRSTk(x) = FIRSTk(y). It follows that
4.  = .
▶ Meaning: Suppose we consider any state of the parse in which A is
the nonterminal currently being parsed and FIRSTk(x) is
the k-lookahead at the current point. Then, if the
k-lookahead is same, the two productions A   and A  
are identical. Any other information provided by the
closed portion and the open portion of the current state
of the parse will be disregarded.
Compiler Lecture Note, LL Parsing Page 39
▶ S  A,  : closed portion,  : open portion
▶ Two states of the parse
FIRSTk(x) = FIRSTk(y) ===>  = .
*
S

A

 x
S

A

 y
• LOOKAHEAD 정의를 k개의 심벌로 확장
k- LOOKAHEAD(A→) = FIRSTk({|S⇒A⇒⇒∈VT
*}).
그러면 Strong LL(k)는 임의의 생성 규칙 A →  |  에 대하여
k- LOOKAHEAD(A→) ∩ k- LOOKAHEAD(A→ ) =  을 만족
– 어떤 고정된 k에 대해서 strong LL(k)의 조건을 만족하는 가를 검사하는 방법
• k의 값을 1부터 차례로 증가시켜 가면서 생성 규칙의 LOOKAHEAD를 구해서 위
조건을 적용
Compiler Lecture Note, LL Parsing Page 40
Compiler Lecture Note, LL Parsing Page 41
▶ Def) LL(k) grammar:
1. S  A    x ∈ VT
*, and
2. S  A    y ∈ VT
* such that
3. FIRSTk(x) = FIRSTk(y). It follows that
4.  = .
ex) S  aAaa | bAba
A  b | 
S S
a A a a b A b a
b 
 lookahead가 ba일 때 A  b, A   중 어느 rule을 택할 수
있는가? 이제 본 symbol이 a이면 A  b를 선택하고, b이면
A   를 선택한다. 따라서 SLL(2)는 아니며 LL(2)가 된다.
*
*
*
*
2-LOOKAHEAD(A→b) = {ba, bb}
2-LOOKAHEAD(A→) = {aa, ba}
∴ strong LL(2) 문법이 아니다.
Compiler Lecture Note, LL Parsing Page 42
▶ SLL(k) and LL(k)
▶ <theorem> strong LL(1)  LL(1)
Proof) () clear!
() Suppose that G is not strong LL(1).
Then, by definition, there are two distinct productions
A   and A   such that,
S  1A1  11  111  111
S  2A2  22  222  222
and FIRST(11) = FIRST(22).
SLL(k)
LL(k)
*
*
*
*
*
*
Compiler Lecture Note, LL Parsing Page 43
Now we must prove that G is not LL(1).
1) 1= 2= , G is not LL(1).
Indeed, it is ambiguous.
2) one (or both) of 1 and 2 is not . 1 .
FIRST1(1 1) = FIRST1(1) = FIRST1(2 2).
but then,
S  2A2  22  2 12  212
S  2A2  22  2 22  222
satisfy the property
FIRST1(1 2) = FIRST1(1) = FIRST1(2 2).
Thus, by definition, G is not LL(1).
*
*
*
*
*
*

More Related Content

What's hot

Functional programming
Functional programmingFunctional programming
Functional programmingssuserdcfefa
 
6장 표현식 및 문장
6장 표현식 및 문장6장 표현식 및 문장
6장 표현식 및 문장재정 이
 
[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기
[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기
[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기Chris Ohk
 
[C++ korea] effective modern c++ study item 2 understanding auto type deduc...
[C++ korea] effective modern c++ study   item 2 understanding auto type deduc...[C++ korea] effective modern c++ study   item 2 understanding auto type deduc...
[C++ korea] effective modern c++ study item 2 understanding auto type deduc...Seok-joon Yun
 
Design Pattern In Functional Language
Design Pattern In Functional LanguageDesign Pattern In Functional Language
Design Pattern In Functional LanguageSH Park
 
[C++ Korea] Effective Modern C++ Study, Item 1 - 3
[C++ Korea] Effective Modern C++ Study, Item 1 - 3[C++ Korea] Effective Modern C++ Study, Item 1 - 3
[C++ Korea] Effective Modern C++ Study, Item 1 - 3Chris Ohk
 
[C++ Korea] Effective Modern C++ MVA item 8 Prefer nullptr to 0 and null +윤석준
[C++ Korea] Effective Modern C++ MVA item 8 Prefer nullptr to 0 and null +윤석준[C++ Korea] Effective Modern C++ MVA item 8 Prefer nullptr to 0 and null +윤석준
[C++ Korea] Effective Modern C++ MVA item 8 Prefer nullptr to 0 and null +윤석준Seok-joon Yun
 
[C++ Korea] Effective Modern C++ mva item 7 distinguish between and {} when c...
[C++ Korea] Effective Modern C++ mva item 7 distinguish between and {} when c...[C++ Korea] Effective Modern C++ mva item 7 distinguish between and {} when c...
[C++ Korea] Effective Modern C++ mva item 7 distinguish between and {} when c...Seok-joon Yun
 
C++ 타입 추론
C++ 타입 추론C++ 타입 추론
C++ 타입 추론Huey Park
 
[C++ Korea] Effective Modern C++ MVA item 9 Prefer alias declarations to type...
[C++ Korea] Effective Modern C++ MVA item 9 Prefer alias declarations to type...[C++ Korea] Effective Modern C++ MVA item 9 Prefer alias declarations to type...
[C++ Korea] Effective Modern C++ MVA item 9 Prefer alias declarations to type...Seok-joon Yun
 
[C++ korea] effective modern c++ study item 7 distinguish between () and {} w...
[C++ korea] effective modern c++ study item 7 distinguish between () and {} w...[C++ korea] effective modern c++ study item 7 distinguish between () and {} w...
[C++ korea] effective modern c++ study item 7 distinguish between () and {} w...Seok-joon Yun
 
Effective Modern C++ MVA item 18 Use std::unique_ptr for exclusive-ownership ...
Effective Modern C++ MVA item 18 Use std::unique_ptr for exclusive-ownership ...Effective Modern C++ MVA item 18 Use std::unique_ptr for exclusive-ownership ...
Effective Modern C++ MVA item 18 Use std::unique_ptr for exclusive-ownership ...Seok-joon Yun
 
[C++ korea] effective modern c++ study item8~10 정은식
[C++ korea] effective modern c++ study item8~10 정은식[C++ korea] effective modern c++ study item8~10 정은식
[C++ korea] effective modern c++ study item8~10 정은식은식 정
 
2.Startup JavaScript - 연산자
2.Startup JavaScript - 연산자2.Startup JavaScript - 연산자
2.Startup JavaScript - 연산자Circulus
 
[C++ korea] effective modern c++ study item 1정은식
[C++ korea] effective modern c++ study item 1정은식[C++ korea] effective modern c++ study item 1정은식
[C++ korea] effective modern c++ study item 1정은식은식 정
 

What's hot (20)

Functional programming
Functional programmingFunctional programming
Functional programming
 
6장 표현식 및 문장
6장 표현식 및 문장6장 표현식 및 문장
6장 표현식 및 문장
 
[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기
[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기
[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기
 
[C++ korea] effective modern c++ study item 2 understanding auto type deduc...
[C++ korea] effective modern c++ study   item 2 understanding auto type deduc...[C++ korea] effective modern c++ study   item 2 understanding auto type deduc...
[C++ korea] effective modern c++ study item 2 understanding auto type deduc...
 
Design Pattern In Functional Language
Design Pattern In Functional LanguageDesign Pattern In Functional Language
Design Pattern In Functional Language
 
3. linked list
3. linked list3. linked list
3. linked list
 
[C++ Korea] Effective Modern C++ Study, Item 1 - 3
[C++ Korea] Effective Modern C++ Study, Item 1 - 3[C++ Korea] Effective Modern C++ Study, Item 1 - 3
[C++ Korea] Effective Modern C++ Study, Item 1 - 3
 
4. stack
4. stack4. stack
4. stack
 
2012 Ds 03
2012 Ds 032012 Ds 03
2012 Ds 03
 
[C++ Korea] Effective Modern C++ MVA item 8 Prefer nullptr to 0 and null +윤석준
[C++ Korea] Effective Modern C++ MVA item 8 Prefer nullptr to 0 and null +윤석준[C++ Korea] Effective Modern C++ MVA item 8 Prefer nullptr to 0 and null +윤석준
[C++ Korea] Effective Modern C++ MVA item 8 Prefer nullptr to 0 and null +윤석준
 
[C++ Korea] Effective Modern C++ mva item 7 distinguish between and {} when c...
[C++ Korea] Effective Modern C++ mva item 7 distinguish between and {} when c...[C++ Korea] Effective Modern C++ mva item 7 distinguish between and {} when c...
[C++ Korea] Effective Modern C++ mva item 7 distinguish between and {} when c...
 
C++ 타입 추론
C++ 타입 추론C++ 타입 추론
C++ 타입 추론
 
[C++ Korea] Effective Modern C++ MVA item 9 Prefer alias declarations to type...
[C++ Korea] Effective Modern C++ MVA item 9 Prefer alias declarations to type...[C++ Korea] Effective Modern C++ MVA item 9 Prefer alias declarations to type...
[C++ Korea] Effective Modern C++ MVA item 9 Prefer alias declarations to type...
 
[C++ korea] effective modern c++ study item 7 distinguish between () and {} w...
[C++ korea] effective modern c++ study item 7 distinguish between () and {} w...[C++ korea] effective modern c++ study item 7 distinguish between () and {} w...
[C++ korea] effective modern c++ study item 7 distinguish between () and {} w...
 
Effective Modern C++ MVA item 18 Use std::unique_ptr for exclusive-ownership ...
Effective Modern C++ MVA item 18 Use std::unique_ptr for exclusive-ownership ...Effective Modern C++ MVA item 18 Use std::unique_ptr for exclusive-ownership ...
Effective Modern C++ MVA item 18 Use std::unique_ptr for exclusive-ownership ...
 
[C++ korea] effective modern c++ study item8~10 정은식
[C++ korea] effective modern c++ study item8~10 정은식[C++ korea] effective modern c++ study item8~10 정은식
[C++ korea] effective modern c++ study item8~10 정은식
 
5. queue
5. queue5. queue
5. queue
 
2.Startup JavaScript - 연산자
2.Startup JavaScript - 연산자2.Startup JavaScript - 연산자
2.Startup JavaScript - 연산자
 
[C++ korea] effective modern c++ study item 1정은식
[C++ korea] effective modern c++ study item 1정은식[C++ korea] effective modern c++ study item 1정은식
[C++ korea] effective modern c++ study item 1정은식
 
6 swift 고급함수
6 swift 고급함수6 swift 고급함수
6 swift 고급함수
 

Similar to Ch07

사칙연산 프로그램
사칙연산 프로그램사칙연산 프로그램
사칙연산 프로그램중선 곽
 
하스켈 프로그래밍 입문 2
하스켈 프로그래밍 입문 2하스켈 프로그래밍 입문 2
하스켈 프로그래밍 입문 2Kwang Yul Seo
 
2012 Dm A0 02 Pdf
2012 Dm A0 02 Pdf2012 Dm A0 02 Pdf
2012 Dm A0 02 Pdfjinwookhong
 
2012 Dm A0 02 Pdf
2012 Dm A0 02 Pdf2012 Dm A0 02 Pdf
2012 Dm A0 02 Pdfkd19h
 
알고리즘과 자료구조
알고리즘과 자료구조알고리즘과 자료구조
알고리즘과 자료구조영기 김
 
[C++ Korea] Effective Modern C++ Study item14 16 +신촌
[C++ Korea] Effective Modern C++ Study item14 16 +신촌[C++ Korea] Effective Modern C++ Study item14 16 +신촌
[C++ Korea] Effective Modern C++ Study item14 16 +신촌Seok-joon Yun
 
2.1 부동소수점 비법들
2.1 부동소수점 비법들2.1 부동소수점 비법들
2.1 부동소수점 비법들준섭 김
 
나에 첫번째 자바8 람다식 지앤선
나에 첫번째 자바8 람다식   지앤선나에 첫번째 자바8 람다식   지앤선
나에 첫번째 자바8 람다식 지앤선daewon jeong
 
불어오는 변화의 바람, From c++98 to c++11, 14
불어오는 변화의 바람, From c++98 to c++11, 14 불어오는 변화의 바람, From c++98 to c++11, 14
불어오는 변화의 바람, From c++98 to c++11, 14 명신 김
 
Project#2말의여행 Hwp
Project#2말의여행 HwpProject#2말의여행 Hwp
Project#2말의여행 HwpKimjeongmoo
 
12장 함수 조합 다시 보기4
12장 함수 조합 다시 보기412장 함수 조합 다시 보기4
12장 함수 조합 다시 보기4cosmosyc
 
[구로IT학원추천/구로디지털단지IT학원/국비지원IT학원/재직자/구직자환급교육]#9.SQL초보에서 Schema Objects까지
[구로IT학원추천/구로디지털단지IT학원/국비지원IT학원/재직자/구직자환급교육]#9.SQL초보에서 Schema Objects까지[구로IT학원추천/구로디지털단지IT학원/국비지원IT학원/재직자/구직자환급교육]#9.SQL초보에서 Schema Objects까지
[구로IT학원추천/구로디지털단지IT학원/국비지원IT학원/재직자/구직자환급교육]#9.SQL초보에서 Schema Objects까지탑크리에듀(구로디지털단지역3번출구 2분거리)
 
2012 Ds B2 05
2012 Ds B2 052012 Ds B2 05
2012 Ds B2 05chl132435
 
이산수학 C1 프로젝트 3
이산수학 C1 프로젝트 3이산수학 C1 프로젝트 3
이산수학 C1 프로젝트 3pkok15
 
Spherical Harmonics.pdf
Spherical Harmonics.pdfSpherical Harmonics.pdf
Spherical Harmonics.pdfBongseok Cho
 
Java jungsuk3 ch14_lambda_stream
Java jungsuk3 ch14_lambda_streamJava jungsuk3 ch14_lambda_stream
Java jungsuk3 ch14_lambda_stream성 남궁
 

Similar to Ch07 (20)

사칙연산 프로그램
사칙연산 프로그램사칙연산 프로그램
사칙연산 프로그램
 
하스켈 프로그래밍 입문 2
하스켈 프로그래밍 입문 2하스켈 프로그래밍 입문 2
하스켈 프로그래밍 입문 2
 
2012 Dm A0 02 Pdf
2012 Dm A0 02 Pdf2012 Dm A0 02 Pdf
2012 Dm A0 02 Pdf
 
이산치2번
이산치2번이산치2번
이산치2번
 
2012 Dm A0 02 Pdf
2012 Dm A0 02 Pdf2012 Dm A0 02 Pdf
2012 Dm A0 02 Pdf
 
알고리즘과 자료구조
알고리즘과 자료구조알고리즘과 자료구조
알고리즘과 자료구조
 
[C++ Korea] Effective Modern C++ Study item14 16 +신촌
[C++ Korea] Effective Modern C++ Study item14 16 +신촌[C++ Korea] Effective Modern C++ Study item14 16 +신촌
[C++ Korea] Effective Modern C++ Study item14 16 +신촌
 
2.1 부동소수점 비법들
2.1 부동소수점 비법들2.1 부동소수점 비법들
2.1 부동소수점 비법들
 
나에 첫번째 자바8 람다식 지앤선
나에 첫번째 자바8 람다식   지앤선나에 첫번째 자바8 람다식   지앤선
나에 첫번째 자바8 람다식 지앤선
 
06장 함수
06장 함수06장 함수
06장 함수
 
자구5번
자구5번자구5번
자구5번
 
불어오는 변화의 바람, From c++98 to c++11, 14
불어오는 변화의 바람, From c++98 to c++11, 14 불어오는 변화의 바람, From c++98 to c++11, 14
불어오는 변화의 바람, From c++98 to c++11, 14
 
이산수학03
이산수학03이산수학03
이산수학03
 
Project#2말의여행 Hwp
Project#2말의여행 HwpProject#2말의여행 Hwp
Project#2말의여행 Hwp
 
12장 함수 조합 다시 보기4
12장 함수 조합 다시 보기412장 함수 조합 다시 보기4
12장 함수 조합 다시 보기4
 
[구로IT학원추천/구로디지털단지IT학원/국비지원IT학원/재직자/구직자환급교육]#9.SQL초보에서 Schema Objects까지
[구로IT학원추천/구로디지털단지IT학원/국비지원IT학원/재직자/구직자환급교육]#9.SQL초보에서 Schema Objects까지[구로IT학원추천/구로디지털단지IT학원/국비지원IT학원/재직자/구직자환급교육]#9.SQL초보에서 Schema Objects까지
[구로IT학원추천/구로디지털단지IT학원/국비지원IT학원/재직자/구직자환급교육]#9.SQL초보에서 Schema Objects까지
 
2012 Ds B2 05
2012 Ds B2 052012 Ds B2 05
2012 Ds B2 05
 
이산수학 C1 프로젝트 3
이산수학 C1 프로젝트 3이산수학 C1 프로젝트 3
이산수학 C1 프로젝트 3
 
Spherical Harmonics.pdf
Spherical Harmonics.pdfSpherical Harmonics.pdf
Spherical Harmonics.pdf
 
Java jungsuk3 ch14_lambda_stream
Java jungsuk3 ch14_lambda_streamJava jungsuk3 ch14_lambda_stream
Java jungsuk3 ch14_lambda_stream
 

More from Hankyo

01.표준프레임워크개요
01.표준프레임워크개요01.표준프레임워크개요
01.표준프레임워크개요Hankyo
 
01.실행환경 실습교재(공통기반)
01.실행환경 실습교재(공통기반)01.실행환경 실습교재(공통기반)
01.실행환경 실습교재(공통기반)Hankyo
 
01.모바일 프레임워크 이론
01.모바일 프레임워크 이론01.모바일 프레임워크 이론
01.모바일 프레임워크 이론Hankyo
 
01.공통컴포넌트 교육교재
01.공통컴포넌트 교육교재01.공통컴포넌트 교육교재
01.공통컴포넌트 교육교재Hankyo
 
01.개발환경 교육교재
01.개발환경 교육교재01.개발환경 교육교재
01.개발환경 교육교재Hankyo
 
07.실행환경 교육교재(표준프레임워크 세부 적용기준)
07.실행환경 교육교재(표준프레임워크 세부 적용기준)07.실행환경 교육교재(표준프레임워크 세부 적용기준)
07.실행환경 교육교재(표준프레임워크 세부 적용기준)Hankyo
 
06.실행환경 실습교재(easy company,해답)
06.실행환경 실습교재(easy company,해답)06.실행환경 실습교재(easy company,해답)
06.실행환경 실습교재(easy company,해답)Hankyo
 
06.실행환경 실습교재(easy company,문제)
06.실행환경 실습교재(easy company,문제)06.실행환경 실습교재(easy company,문제)
06.실행환경 실습교재(easy company,문제)Hankyo
 
05.실행환경 교육교재(업무처리,연계통합)
05.실행환경 교육교재(업무처리,연계통합)05.실행환경 교육교재(업무처리,연계통합)
05.실행환경 교육교재(업무처리,연계통합)Hankyo
 
04.실행환경 실습교재(화면처리)
04.실행환경 실습교재(화면처리)04.실행환경 실습교재(화면처리)
04.실행환경 실습교재(화면처리)Hankyo
 
04.실행환경 교육교재(화면처리)
04.실행환경 교육교재(화면처리)04.실행환경 교육교재(화면처리)
04.실행환경 교육교재(화면처리)Hankyo
 
04.모바일 device api_실습교재
04.모바일 device api_실습교재04.모바일 device api_실습교재
04.모바일 device api_실습교재Hankyo
 
04.[참고]개발환경 실습교재
04.[참고]개발환경 실습교재04.[참고]개발환경 실습교재
04.[참고]개발환경 실습교재Hankyo
 
03.실행환경 실습교재(배치처리)
03.실행환경 실습교재(배치처리)03.실행환경 실습교재(배치처리)
03.실행환경 실습교재(배치처리)Hankyo
 
03.실행환경 교육교재(배치처리)
03.실행환경 교육교재(배치처리)03.실행환경 교육교재(배치처리)
03.실행환경 교육교재(배치처리)Hankyo
 
03.모바일 실습교재(모바일 공통컴포넌트 실습)
03.모바일 실습교재(모바일 공통컴포넌트 실습)03.모바일 실습교재(모바일 공통컴포넌트 실습)
03.모바일 실습교재(모바일 공통컴포넌트 실습)Hankyo
 
03.[참고]표준프레임워크기반 개발방법
03.[참고]표준프레임워크기반 개발방법03.[참고]표준프레임워크기반 개발방법
03.[참고]표준프레임워크기반 개발방법Hankyo
 
03.[참고]개발환경 교육교재
03.[참고]개발환경 교육교재03.[참고]개발환경 교육교재
03.[참고]개발환경 교육교재Hankyo
 
02.실행환경 실습교재(데이터처리)
02.실행환경 실습교재(데이터처리)02.실행환경 실습교재(데이터처리)
02.실행환경 실습교재(데이터처리)Hankyo
 
02.실행환경 교육교재(데이터처리)
02.실행환경 교육교재(데이터처리)02.실행환경 교육교재(데이터처리)
02.실행환경 교육교재(데이터처리)Hankyo
 

More from Hankyo (20)

01.표준프레임워크개요
01.표준프레임워크개요01.표준프레임워크개요
01.표준프레임워크개요
 
01.실행환경 실습교재(공통기반)
01.실행환경 실습교재(공통기반)01.실행환경 실습교재(공통기반)
01.실행환경 실습교재(공통기반)
 
01.모바일 프레임워크 이론
01.모바일 프레임워크 이론01.모바일 프레임워크 이론
01.모바일 프레임워크 이론
 
01.공통컴포넌트 교육교재
01.공통컴포넌트 교육교재01.공통컴포넌트 교육교재
01.공통컴포넌트 교육교재
 
01.개발환경 교육교재
01.개발환경 교육교재01.개발환경 교육교재
01.개발환경 교육교재
 
07.실행환경 교육교재(표준프레임워크 세부 적용기준)
07.실행환경 교육교재(표준프레임워크 세부 적용기준)07.실행환경 교육교재(표준프레임워크 세부 적용기준)
07.실행환경 교육교재(표준프레임워크 세부 적용기준)
 
06.실행환경 실습교재(easy company,해답)
06.실행환경 실습교재(easy company,해답)06.실행환경 실습교재(easy company,해답)
06.실행환경 실습교재(easy company,해답)
 
06.실행환경 실습교재(easy company,문제)
06.실행환경 실습교재(easy company,문제)06.실행환경 실습교재(easy company,문제)
06.실행환경 실습교재(easy company,문제)
 
05.실행환경 교육교재(업무처리,연계통합)
05.실행환경 교육교재(업무처리,연계통합)05.실행환경 교육교재(업무처리,연계통합)
05.실행환경 교육교재(업무처리,연계통합)
 
04.실행환경 실습교재(화면처리)
04.실행환경 실습교재(화면처리)04.실행환경 실습교재(화면처리)
04.실행환경 실습교재(화면처리)
 
04.실행환경 교육교재(화면처리)
04.실행환경 교육교재(화면처리)04.실행환경 교육교재(화면처리)
04.실행환경 교육교재(화면처리)
 
04.모바일 device api_실습교재
04.모바일 device api_실습교재04.모바일 device api_실습교재
04.모바일 device api_실습교재
 
04.[참고]개발환경 실습교재
04.[참고]개발환경 실습교재04.[참고]개발환경 실습교재
04.[참고]개발환경 실습교재
 
03.실행환경 실습교재(배치처리)
03.실행환경 실습교재(배치처리)03.실행환경 실습교재(배치처리)
03.실행환경 실습교재(배치처리)
 
03.실행환경 교육교재(배치처리)
03.실행환경 교육교재(배치처리)03.실행환경 교육교재(배치처리)
03.실행환경 교육교재(배치처리)
 
03.모바일 실습교재(모바일 공통컴포넌트 실습)
03.모바일 실습교재(모바일 공통컴포넌트 실습)03.모바일 실습교재(모바일 공통컴포넌트 실습)
03.모바일 실습교재(모바일 공통컴포넌트 실습)
 
03.[참고]표준프레임워크기반 개발방법
03.[참고]표준프레임워크기반 개발방법03.[참고]표준프레임워크기반 개발방법
03.[참고]표준프레임워크기반 개발방법
 
03.[참고]개발환경 교육교재
03.[참고]개발환경 교육교재03.[참고]개발환경 교육교재
03.[참고]개발환경 교육교재
 
02.실행환경 실습교재(데이터처리)
02.실행환경 실습교재(데이터처리)02.실행환경 실습교재(데이터처리)
02.실행환경 실습교재(데이터처리)
 
02.실행환경 교육교재(데이터처리)
02.실행환경 교육교재(데이터처리)02.실행환경 교육교재(데이터처리)
02.실행환경 교육교재(데이터처리)
 

Ch07

  • 1. Compiler Lecture Note, LL Parsing Page 1 컴파일러 입문 제 7 장 LL 구문 분석
  • 2. Compiler Lecture Note, LL Parsing Page 2 I. 결정적 구문 분석 II. Recursive-descent 파서 III. Predictive 파서 VI. Predictive 파싱 테이블의 구성 V. Strong LL(k) 문법과 LL(k) 문법 목 차
  • 3. Compiler Lecture Note, LL Parsing Page 3 I. 결정적 구문 분석 ▶ Deterministic Top-Down Parsing ::= deterministic selection of production rules to be applied in top-down syntax analysis. ▶ One pass nobackup 1. Input string is scanned once from left to right. 2. Parsing process is deterministic. ▶ Top-down parsing with nobackup ::= deterministic top-down parsing. called LL parsing. "Left to right scanning and Left parse"
  • 4. Compiler Lecture Note, LL Parsing Page 4 ▶ LL parsing - backtracking이 없이 deterministic한 top-down parsing ⇒ 문법이 LL 조건 만족해야 - LL이란? Left-to-right scanning & Leftmost derivation - 현재의 input symbol을 보고 적용될 생성규칙을 deterministic하게 선택 ▶ How to decide which production is to be applied: sentential form : 1 2 … i-1Xα input string : 1 2 … i-1 i i+1 … n  X  1 | 2 ... | k ∈ P일 때, i를 보고 X-production 중에 unique하게 결정.  the condition for no backtracking : FIRST와 FOLLOW가 필요. (= LL condition)
  • 5. FIRST • 문법 G = (VN, VT, P, S)가 context-free 문법이고 A∈VN, a∈VT일 때, non- terminal A에 대한 FIRST는 다음과 같이 정의 FIRST(A) = {a∈VT∪{} | A⇒a,  ∈V*}. non-terminal A로부터 유도되어 첫번째로 나타날 수 있는 terminal의 집합 – 예 : 다음 생성 규칙에서 각 non-terminal에 대한 FIRST A → aB | B B → bC | C C → c Compiler Lecture Note, LL Parsing Page 5 X FIRST(X)  1. A ⇒ aB A ⇒ B ⇒ bC A ⇒ B ⇒ C ⇒ c ∴ FIRST(A) = {a, b, c}. 2. B ⇒ bC B ⇒ C ⇒ c ∴ FIRST(B) = {b, c}. 3. C ⇒ c ∴ FIRST(C) = {c}.
  • 6. • Non-terminal A가 을 유도할 수 있으면 A를 nullable하다고 부른다. – A⇒ 이면 nullable하다. • 두 개의 집합에 대한 연산자인 ring sum은 다음과 같이 정의 되면 기호  를 사용한다. 1. if   A then A  B = A 2. if   A then A  B = (A – {})∪B. – Ring sum의 의미 • 첫 번째 피 연산자의 집합이 을 갖지 않으면 그 자신 • 을 포함하고 있으면 을 제외한 첫 번째 피 연산자와 두 번째 피 연산자를 합집합 한 것 – 예 : {a, b, c}  {c, d} = {a, b, c}. {a, b, c, }  {c, d} = {a, b, c, d}. {a, b, }  {c, d, } = {a, b, c, d, }. Compiler Lecture Note, LL Parsing Page 6
  • 7. • FIRST(A1A2 ···An) = FIRST(A1)  FIRST(A2)  ··· FIRST(An) – 스트링의 FIRST : nullable이 아닌 심벌까지의 FIRST를 합집합 한 것 – 각 생성 규칙에 따라 FIRST(X)를 계산하는 방법 1. X가 terminal이면 X의 FIRST는 자기 자신 FIRST(X) = {X} if X∈VT. 2. X → a 의 생성 규칙이 존재하면 a가 FIRST(X)에 포함 FIRST(X) = FIRST(X) ∪ {a} if X → a∈P and a∈VT. 또한, X가  –생성 규칙을 가지면 X의 FIRST에  이 포함 FIRST(X) = FIRST(X) ∪ {} if X → ∈P. 3. X → Y1Y2 ···Yk인 생성 규칙이 있을 때, FIRST(X) = FIRST(X) ∪ FIRST(Y1Y2 ···Yk). Compiler Lecture Note, LL Parsing Page 7
  • 8. Compiler Lecture Note, LL Parsing Page 8 ex1) E  TE E  +TE |  T  FT T  FT |  F  (E) | id FIRST(E) = FIRST(T) = FIRST(F) = {(, id} FIRST(E) = {+, } FIRST(T) = {, } ex2) PROGRAM  begin d semi X end X  d semi X X  s Y Y  semi s Y |  FIRST(PROGRAM) = {begin} FIRST(X) = {d,s} FIRST(Y) = {semi, }
  • 9. FOLLOW • FOLLOW – Non-terminal A가 nullable하면 FIRST(A)에  이 속하게 되어 FIRST를 가지고는 생성 규칙을 결정적으로 선택할 수 없음 –  -생성 규칙을 갖는 문법에서는 non-terminal 다음에 오는 terminal 심벌이 의 미를 가짐 • 정의 : FOLLOW(A) = {a ∈ VT∪{$} | S ⇒ Aa, , ∈ V*} – $ : 입력 스트링의 끝을 표기하는 마커 심벌(marker symbol) – Non-terminal A의 FOLLOW란 시작 심벌로부터 유도될 수 있는 모든 문장 형 태에서 A 다음에 나오는 terminal 심벌의 집합 • FOLLOW를 계산하기 위해서는 모든 문장 형태를 고려해야 하나, 문장 형태는 생성 규칙의 rhs들로 이루어져 있으므로, 생성 규칙의 rhs를 이용하여 FOLLOW를 구할 수 있음. Compiler Lecture Note, LL Parsing Page 9
  • 10. • 각 생성 규칙의 형태에 따른 FOLLOW를 계산하는 방법 1. 시작 심벌은 $를 초기 값으로 갖는다. FOLLOW(S) = {$} 2. 생성 규칙의 형태가 A→B ,    일 때, FIRST()에서  를 제외한 terminal 심벌을 B의 FOLLOW에 추가한다. if A→B ,    then FOLLOW(B) = FOLLOW(B) ∪(FIRST() – {}). 3. A→B 이거나, A→B 에서 FIRST()가 이 속하는 경우(즉  ⇒  ), A의 FOLLOW 전체를 B의 FOLLOW에 추가한다. if A→B ∈ P or (A→B and  ⇒  ) then FOLLOW(B) = FOLLOW(B) ∪ FOLLOW(A). – 계산 과정 3번의 의미 • 임의의 문장 형태에서 A 다음에 나올 수 있는 심벌은 모두 B 다음에 나올 수 있음 S ⇒ 1A2 ⇒ 1B2 ⇒ 1B2 • FOLLOW 속성으로 인하여 A→B, B→A 와 같은 형태의 생성 규칙을 갖고 있으 면 FOLLOW(A) = FOLLOW(B) 가 됨. ∵ 전자 형태의 생성 규칙으로부터 FOLLOW (A) ⊆ FOLLOW(B) 후자 형태의 생성 규칙으로부터 FOLLOW (A) ⊇ FOLLOW(B) Compiler Lecture Note, LL Parsing Page 10
  • 11. Compiler Lecture Note, LL Parsing Page 11 ex) E  TE‟ E'  +TE' |  T  FT‟ T'  FT' |  F  (E) | id Nullable = { E, T } FIRST(E) = FIRST(T) = FIRST(F) = {(, id} FIRST(E) = {+, } FIRST(T) = {, } FOLLOW(E) = {),$} FOLLOW(E') = {),$} FOLLOW(T) = {+,),$} FOLLOW(T') = {+,),$} FOLLOW(F) = {,+,),$}
  • 12. Compiler Lecture Note, LL Parsing Page 12 ▶ LL condition ::= no backup condition ::= the condition for deterministic parsing of top-down method. input : 12 ... i-1i ...n derived string : 12...i-1X X  1 | 2 ... | m  i를 보고 X-production들 중에서 X를 확장할 rule을 결정적으로 선택. ★ <LL condition> A   | ∈ P, 1. FIRST()  FIRST() =  2. if  * , FOLLOW(A)  FIRST() = 
  • 13. – 예 : 다음 문법을 가지고 스트링 i[e] ← e를 결정적으로 구문 분석할 수 있는지 알아보자 A → iB ← e B → SB |  S → [eC] | .i C → eC |   (1) LL 조건 테스트 : Compiler Lecture Note, LL Parsing Page 13 1. NULLABLE = {B, C} 2. FIRST(A) = {i} FIRST(B) = {[, ., } FIRST(S) = {[, .} FIRST(C) = {e, } 3. FOLLOW(A) = {$} FOLLOW(B) = {←} FOLLOW(S) = {[, ., ←} FOLLOW(C) = {]} 4. FIRST 와 FOLLOW를 이용하여 LL 조건을 테스트 1) B → SB |  에서, FIRST(SB) ∩ FOLLOW(B) = {[, .} ∩ {←} =  2) S → [eC] | .i 에서, FIRST([eC]) ∩ FIRST(.i) = {[} ∩ {.}=  3) C → eC |  에서, FIRST(eC) ∩ FOLLOW(C) = {e} ∩ {]}=  1. FIRST() ∩ FIRST() =  2. if  ∈ FIRST() then FOLLOW(A) ∩ FIRST() = 
  • 14. (2) 좌측 유도 과정 : <문장 형태> <입력 스트링> A ⇒ iB ← e ⇒ iSB ← e ⇒ i[eC]B ← e ⇒ i[e]B ← e ⇒ i[e] ← e 1. 입력 스트링 첫 심벌 i를 보고 시작 심벌 A를 첫 번째 생성 규칙으로 확장 2. 생성된 문장 형태 iB ← e 에서 첫 심벌 i와 입력 스트링 i가 같으므로 다음 심벌 비 교 3. 문장 형태의 다음 심벌은 non-terminal B이고, 현재의 입력 심벌은 [이므로 B-생성 규칙 중에서 [를 유도 할 수 있는 생성 규칙 B → SB를 적용하여 유도 • 이와 같은 과정을 계속 진행하면 시작 심벌로부터 주어진 스트링을 결정적으로 유도할 수 있다. – FIRST와 FOLLOW는 이와 같이 문장 형태에서 각 non-terminal 이 생성할 수 있는 스트링이 무엇인지를 가리켜 주어서 현재의 입력 심벌을 보고 생성 규 칙을 결정적으로 선택할 수 있게 해준다. Compiler Lecture Note, LL Parsing Page 14 i[e] ← e ↑ i[e] ← e ↑ i[e] ← e ↑ i[e] ← e ↑ i[e] ← e ↑
  • 15. Compiler Lecture Note, LL Parsing Page 15 ex) A  aBc | Bc | dAa B  bB |  FIRST(A) = {a,b,c,d} FOLLOW(A) = {$,a} FIRST(B) = {b, } FOLLOW(B) = {c} 1) A  aBc | Bc | dAa에서, FIRST(aBc)  FIRST(Bc)  FIRST(dAa) = {a}  {b,c}  {d} =  2) B  bB |  에서, FIRST(bB)  FOLLOW(B) = {b}  {c} =  1), 2)에 의해 LL 조건을 만족한다.
  • 16. II. Recursive-descent 파서 • LL 방법을 실제로 parsing algorithm으로 사용하는 syntax analyzer – Recursive-descent parser – Predictive parser • Recursive-descent parser – LL 방법의 일종 – 주어진 입력 스트링을 parsing하기 위하여 일련의 순환 프로시저(recursive procedure)를 사용 – 각 순환 프로시저는 각 non-terminal 에 해당하는 것으로 non-terminal에 대한 유도를 프로시저 호출로 처리하는 방법 • Recursive-descent parser를 구현 하는 방법 – 각 non-terminal에 대한 프로시저를 작성-통합하여 전체적인 프로그램 구성 • 각 프로시저 내에서 입력 심벌에 따라 어떤 생성 규칙을 선택하느냐가 중요 • 한 생성 규칙을 적용했을 때 생성할 수 있는 terminal들을 알아야 함 : “LOOKAHEAD” • 현재의 입력 심벌이 한 생성 규칙의 LOOKAHEAD에 속하면 생성규칙으로 확장 할 수 있도록 프로시저 작성 Compiler Lecture Note, LL Parsing Page 16
  • 17. • LOOKAHEAD 정의와 계산 방법 LOOKAHEAD(A → ) = FIRST( {| S ⇒ A ⇒  ⇒  ∈ VT *}). LOOKAHEAD(A → X1X2 ···Xn) = FIRST(X1)  FIRST(X2)  ··· FIRST(Xn)  FOLLOW(A). – rhs의 FIRST가 되든지, rhs가 를 유도할 수 있으면 lhs의 FOLLOW 도 속함 – 생성 규칙의 형태에서, rhs가 terminal로 시작하는 생성 규칙의 LOOKAHEAD 는 바로 그 terminal 심벌만이 된다. ex) LOOKAHEAD(A → a) = {a} – 예 : 다음의 문법에서 생성 규칙의 LOOKAHEAD를 구하자. E → TE‟ E' → +TE' |  T → FT‟ T' → *FT' |  F → (E) | id  LOOKAHEAD(E → TE') = FIRST(T)  FIRST(E')  FOLLOW(E) = {(, id}  {+, }  {), $} = {(, id} LOOKAHEAD(E'→ +TE') = FIRST(+)  FIRST(T)  FIRST(E')  FOLLOW(E') = {+}  {(, id}  {+, }  {), $} = {+} Compiler Lecture Note, LL Parsing Page 17
  • 18. E → TE‟ E' → +TE' |  T → FT‟ T' → *FT' |  F → (E) | id LOOKAHEAD(E' → ) = FIRST()  FOLLOW(E') = {), $} LOOKAHEAD(T → FT') = FIRST(F)  FIRST(T')  FOLLOW(T) = {(, id}  {*, }  {), $} = {(, id} LOOKAHEAD(T → *FT') = FIRST(*)  FIRST(F)  FIRST(T')  FOLLOW(T') = {*}  {(, id}  {*, }  {+, ), $} = {*} LOOKAHEAD(T' → ) = FIRST() FOLLOW(T') = {+, ), $} LOOKAHEAD(F → (E)) = FIRST(()  FIRST(E)  FIRST())  FOLLOW(F) = {(}  {(, id}  {(}  {*, +, ), $} = {(} LOOKAHEAD(F → id) = FIRST(id)  FOLLOW(F) = {id}  {*, +, ), $} = {id} Compiler Lecture Note, LL Parsing Page 18
  • 19. Compiler Lecture Note, LL Parsing Page 19 ▶ Strong LL condition  Definition : A   |  ∈ P, LOOKAHEAD(A  )  LOOKAHEAD(A  ) = .  Meaning : for each distinct pair of productions with the same left-hand side, it can select the unique alternate that derives a string beginning with the input symbol.  Definition : the grammar G is said to be strong LL(1) if it satisfies the strong LL condition. ex) G : S  aSA |  A  c  LOOKAHEAD(S  aSA) = {a}  LOOKAHEAD(S  ) = FOLLOW(S) = {$, c} LOOKAHEAD(S  aSA)  LOOKAHEAD(S  ) =   G는 strong LL(1)이다.
  • 20. – 예 : 다음 문법이 strong LL(1) 문법인지를 살펴보자. S → bRS | RcSa |  R → acR | b  먼저, 택일 생성 규칙에 대해 LOOKAHEAD를 구해야 한다. 1. LOOKAHEAD(S → bRS) = FIRST(b)  FIRST(R)  FIRST(S)  FOLLOW(S) = {b}  {a, b}  {a, b, }  {a, $} = {b} 2. LOOKAHEAD(S → RcSa) = FIRST(R)  FIRST(c)  FIRST(S)  FIRST(a)  FOLLOW(S) = {a, b}  {c}  {a, b, }  {a} {a, $} = {a, b} LOOKAHEAD(S → bRS) ∩ LOOKAHEAD(S → RcSa) = {b} ∴ strong LL 문법이 아니다. – 위 문법이 strong LL 문법이 아니므로 syntax analysis 시 적용할 생성 규칙을 결정적으로 선택할 수 없다. • 현재의 입력 심벌이 b이고 확장해야 될 non-terminal이 S일 때, 생성 규칙 S → bRS 와 S → RcSa 가 모두 b를 생성 하므로 어느 생성 규칙을 적용할지 알 수 없다. Compiler Lecture Note, LL Parsing Page 20
  • 21. Compiler Lecture Note, LL Parsing Page 21 ▶ Implementation of Recursive-descent parser  If a grammar is strong LL(1), we can construct a parser for sentences of the grammar using the following scheme.  a ∈ VT, procedure pa; (* get_nextsymbol=scanner *) begin if nextsymbol = ta then get_nextsymbol else error end;  get_nextsymbol : 스캐너에 해당하는 루틴으로 입력 스트림으로부터 토큰 한 개를 읽어 전역변수 nextsymbol에 할당 - ta : terminal symbol a의 token number
  • 22. Compiler Lecture Note, LL Parsing Page 22  A ∈ VN, procedure pA; begin case nextsymbol of LOOKAHEAD(A  X1X2...Xm): for i := 1 to m do pXi; LOOKAHEAD(A  Y1Y2...Yn): for i := 1 to n do pYi; : LOOKAHEAD(A  Z1Z2...Zr): for i := 1 to r do pZi; LOOKAHEAD(A  ): ; otherwise: error end (* case *) end;  메인 프로그램 begin (* main *) get_nextSymbol; pS; if nextSymbol = q$ then accept else error end.
  • 23. • 예 : 다음 문법을 위한 recursive-descent 프로시저를 구성하자 S → aAb A → aS | b Compiler Lecture Note, LL Parsing Page 23 (1) Terminal 심벌에 대한 프로시저 procedure pa; begin if nextSymbol = ta then get_nextSymbol else error end; (* pa *) procedure pb; begin if nextSymbol = tb then get_nextSymbol else error end; (* pb *) (2) Non-terminal 심벌에 대한 프로시저 procedure pS; begin if nextSymbol = ta then begin pa; pA; pb end else error end; (* pS *) procedure pA; begin case nextSymbol of ta : begin pa; pS end; tb : pb; otherwise : error end (* case *) end; (* pA *)
  • 24. Compiler Lecture Note, LL Parsing Page 24 ▶ Improving the efficiency and structure of recursive-descent parser 1) Eliminating terminal procedures ::= In practice it is better not to write a procedure for each terminal. Instead the action of advancing the input marker can always be initiated by the nonterminal procedures. In this way many redundant tests can be eliminated.  (1) Non -terminal S에 대한 프로시저 : procedure pS begin if nextSymbol = qa then begin get_nextSymbol; pA; if nextSymbol = qb then get_nextSymbol else error end else error end; (* pS *) (2) Non -terminal A에 대한 프로시저 : procedure pA; begin case nextSymbol of qa : begin get_nextSymbol; pS end; qb : get_nextSymbol; otherwise : error end (* case *) end; (* pA *)
  • 25. Compiler Lecture Note, LL Parsing Page 25 ▶ Improving the efficiency and structure of recursive-descent parser 2) BNF  EBNF : reduce the number of productions and nonterminals. ① repetitive part : { } ② optional part : [ ] ③ alternation : ( | ) ex) < IF_st > ::= ' if ' < cond > ' then ' < st > [ ' else ' < st > ] procedure pIF; begin if nextsymbol = tif then begin get_nextsymbol; pCOND; if nextsymbol = tthen then begin get_nextsymbol; pST end else error(10) end else error(20); if nextsymbol = telse then begin get_nextsymbol; pST end end;
  • 26. Compiler Lecture Note, LL Parsing Page 26 ex) <id_list> ::= ' id ' { ' , ' ' id ' } procedure pID_LIST; begin if nextsymbol = tid then begin get_nextsymbol; while (nextsymbol = tcomma) do begin get_nextsymbol; if nextsymbol = tid then get_nextsymbol else error(100) end end end; • Recursive-descent 파서 – 생성 규칙에 대한 프로시저를 작성함으로써 syntax analyzer를 구현한 프로그램으로 생성규칙이 바뀔 때 마다 syntax analyzer 를 구현한 프로그램을 다시 고쳐야 하는 단점이 존재
  • 27. Compiler Lecture Note, LL Parsing Page 27 [연습문제 7.8 (2)] 다음 grammar를 extended BNF로 바꾸고 그에 따른 recursive-descent parser를 위한 procedure를 작성하시오. <D> ::= ' label ' <L> | ' integer ' <L> <L> ::= <id> <R> <R> ::= ' ; ' | ' , ' <L>  <D> ::= ( ' label ' | ' integer ' ) <id> {' , ' <id>} ' ; „ procedure pD; begin if nextsymbol in [tlabel,tinteger] then begin get_nextsymbol; if nextsymbol = qid then begin get_nextsymbol; while (nextsymbol = qcomma) do begin get_nextsymbol; if nextsymbol = qid then get_nextsymbol else error(3) end end else error(2); if nextsymbol = qsemi then get_nextsymbol else error(4) end else error(1) end; * <L>  <id> (' , ' <id> )* ' ; '
  • 28. Compiler Lecture Note, LL Parsing Page 28 III. Predictive Parsing ▶ Predictive parsing ::= a deterministic parsing method using a stack. The stack contains a sequence of grammar symbols. ▶ Model of a predictive parser Input Output Stack a1 a2 ······ an$ X $ ··· Driver Routine Predictive Parsing Table
  • 29. Compiler Lecture Note, LL Parsing Page 29  Current input symbol과 stack top symbol 사이의 관계에 따라 parsing.  The input buffer contains the string to be parsed, followed by $.  Initial configuration : STACK INPUT $S $  Parsing table(LL) : parsing action을 결정지어 줌. ※ M[X,a] = r : stack top symbol이 X이고 current symbol이 a일 때, r번 생성 규칙으로 expand. r terminals nonterminals X a
  • 30. Compiler Lecture Note, LL Parsing Page 30 ▶ Parsing Actions X : stack top symbol, a : current input symbol 1. if X = a = $, then accept. 2. if X = a, then pop X and advance input. 3. if X ∈ VN, then if M[X,a] = r (X), then replace X by  else error. – 예 : 다음은 주어진 문법에 따른 predictive 파싱 테이블이다. 주어진 문법 : 파싱 테이블 : 1. S → aSb 2. S → bA 3. A → aA 4. A → b • Empty entry 는 error • 스택 top이 S이고 현재 입력 심벌이 a이면 1번 생성 규칙으로 확장하라는 의미 VN VT a b $ S 1 2 A 3 4
  • 31. – Predictive 파서의 driver routine • 주어진 입력 스트링을 왼쪽에서 오른쪽으로 읽어가며 현재의 입력 심벌 과 스택의 top 심벌에 따라 구문 분석을 수행 • 파싱 테이블은 이와 같은 파싱 행동을 제어한다. – 파싱 행동의 종류와 의미 1. Pop : 스택의 top과 현재의 입력 심벌이 같은 경우로 스택의 top 심벌은 스 택에서 제거하고 현재 입력 심벌은 입력 스트링에서 제거 2. Expand : 스택의 top이 non-terminal인 경우로 생성 규칙을 적용하여 확장  M[A, a] = {A → XYZ}일 때, A를 스택에서 제거하고 rhs의 역순인 ZYX를 차례로 스택에 넣어 X가 스택 top이 되게 한다. 3. Accept : 스택이 top 심벌과 현재의 입력 심벌 모두가 $인 경우로 주어진 입 력 스트링이 올바른 스트링임을 알리고 파싱을 종료 4. Error : 스택의 top이 non-terminal 심벌인 경우로 그 심벌로부터 현재 보고 있는 입력 심벌을 결코 유도할 수 없음을 나타낸다. Compiler Lecture Note, LL Parsing Page 31
  • 32. Compiler Lecture Note, LL Parsing Page 32 • Predictive 파서의 구문 분석 방법 Algorithm Predictive_Parser_Action; begin repeat if X ∈ VT∪{$} then (* pop *) if X = a then begin pop X; get_nextSymbol end else error fi else (* X : non-terminal *) (* expand *) if M[X, a] = X → Y1Y2 ···Yk then 스택에서 X를 제거하고 rhs의 역순으로 YkYk-1 ···Y1 을 차례로 스택에 넣는다. else error fi fi until X = a = $ (* accept : 스택에 $만 남을 때까지 반복 *) end. – X : 스택 top의 심벌 – a : 현재 입력 심벌
  • 33. Compiler Lecture Note, LL Parsing Page 33 • 예 : 다음과 같이 문법과 그에 따른 predictive 파싱 테이블이 주어졌을 때, 스 트링 aabccd에 대한 구문 분석을 수행하고 그 결과로 좌 파스를 구해보자. 주어진 문법 : 1. S → aS 2. S → bA 파싱 테이블 : 3. A → d 4. A → ccA 파싱 테이블 을 이용한 predictive 구문 분석 : VN VT a b c d $ S 1 2 A 4 3 Step Stack Input Action parse 1 $S aabccd$ Expand 1 1 2 $Sa aabccd$ Pop & advance 1 3 $S abccd$ Expand 1 1 1 4 $Sa abccd$ Pop & advance 1 1 5 $S bccd$ Expand 2 1 1 2 6 $Ab bccd$ Pop & advance 1 1 2 7 $A ccd$ Expand 4 1 1 2 4 8 $Acc ccd$ Pop & advance & Pop & advance 1 1 2 4 9 $A d$ Expand 3 1 1 2 4 3 10 $d d$ Pop & advance 1 1 2 4 3 11 $ $ Accept 1 1 2 4 3
  • 34. Compiler Lecture Note, LL Parsing Page 34 VI. Predictive 파싱 테이블의 구성 ▶ main idea : If A   is a production with a in FIRST(), then the parser will expand A by  when the current input symbol is a. And if  * , then we should again expand A by  when the current input symbol is in FOLLOW(A). ▶ parsing table(LL): M[X,a] = r : expand X with r-production blank : error VT a X VN
  • 35. Compiler Lecture Note, LL Parsing Page 35 ▶ Algorithm : for each production A, 1. a ∈ FIRST(), M[A,a] := <A> 2. if  * , then b ∈ FOLLOW(A), M[A,b] := <A>. ex) G: 1. E  TE' 2. E'  +TE' 3. E'   4. T  FT' 5. T'  FT' 6. T'   7. F  (E) 8. F  id FIRST(E)=FIRST(T)=FIRST(F)={ ( , id } FIRST(E')={ + ,  } FIRST(T')={  ,  } FOLLOW(E) = FOLLOW(E') = { ) , $ } FOLLOW(T) = FOLLOW(T') = { + , ) , $ } FOLLOW(F) = { + ,  , ) , $ } 78F 6656T' 44T 332E' 11E $)(*+idVTVN
  • 36. Compiler Lecture Note, LL Parsing Page 36 • 예 : id * id + id 주어진 문법 : 파싱 테이블 : 1. E  TE' 2. E'  +TE' 3. E'   4. T  FT‟ 5. T'  FT' 6. T'   7. F  (E) 8. F  id 파싱 테이블 을 이용한 predictive 구문 분석 : Step Stack Input Action parse 1 $E id * id + id$ Expand 1 1 2 $E‟T id * id + id$ Expand 4 1 4 3 $E‟T‟F id * id + id$ Expand 8 1 4 8 4 $E‟T‟id id * id + id$ Pop id & advance 1 4 8 5 $E‟T‟ * id + id$ Expand 5 1 4 8 5 6 $E‟T‟F* * id + id$ Pop * & advance 1 4 8 5 7 $E‟T‟F id + id$ Expand 8 1 4 8 5 8 8 $E‟T‟id id + id$ Pop id & advance 1 4 8 5 8 9 $E‟T‟ + id$ Expand 6 1 4 8 5 8 6 10 $E‟ + id$ Expand 2 1 4 8 5 8 6 2 11 $E‟T+ + id $ Pop + & advance 1 4 8 5 8 6 2 12 $E‟T id$ Expand 4 1 4 8 5 8 6 2 13 $E‟T‟F id$ Expand 8 & pop id & advance 1 4 8 5 8 6 2 8 14 $E‟T‟ $ Expand 6 & expand 3 1 4 8 5 8 6 2 8 6 3 78F 6656T' 44T 332E' 11E $)(*+idVTVN
  • 37. Compiler Lecture Note, LL Parsing Page 37 ▶ LL(1) Grammar ::= a grammar whose parsing table has no multiply-defined entries.  multiply 정의되면 어느 rule로 expand해야 할 지 결정할 수 없기 때 문에 deterministic하게 parsing할 수 없다. ▶ LL(1) condition: A   | , 1. FIRST( )  FIRST() = . 2. if   , then FOLLOW(A)  FIRST() =  . ex) G : 1. S  iCtSS' 2. S  a 3. S'  eS 4. S'   5. C  b FIRST(S) = {i,a} FOLLOW(S) = {$,e} FIRST(S') = {e, } FOLLOW(S') = {$,e} FIRST(C) = {b} FOLLOW(C) = {t} • 위 문법은 LL(1) 문법이 아니다. • 대부분의 경우 중복이 일어나지 않게 문법을 다시 쓰는 것이 보편적 * 3, 4 5C 4S' 12S $tiebaVTVN
  • 38. Compiler Lecture Note, LL Parsing Page 38 V. Strong LL(k) and LL(k) Grammars ▶ FIRSTk() = {|  * , || = k or    and || < k} ▶ G is said to be strong LL(k), for some fixed integer k > 0, if whenever there are two leftmost derivations. 1. S * A   * x∈ VT *, and 2. S * A   * y∈ VT * such that 3. FIRSTk(x) = FIRSTk(y). It follows that 4.  = . ▶ Meaning: Suppose we consider any state of the parse in which A is the nonterminal currently being parsed and FIRSTk(x) is the k-lookahead at the current point. Then, if the k-lookahead is same, the two productions A   and A   are identical. Any other information provided by the closed portion and the open portion of the current state of the parse will be disregarded.
  • 39. Compiler Lecture Note, LL Parsing Page 39 ▶ S  A,  : closed portion,  : open portion ▶ Two states of the parse FIRSTk(x) = FIRSTk(y) ===>  = . * S  A   x S  A   y
  • 40. • LOOKAHEAD 정의를 k개의 심벌로 확장 k- LOOKAHEAD(A→) = FIRSTk({|S⇒A⇒⇒∈VT *}). 그러면 Strong LL(k)는 임의의 생성 규칙 A →  |  에 대하여 k- LOOKAHEAD(A→) ∩ k- LOOKAHEAD(A→ ) =  을 만족 – 어떤 고정된 k에 대해서 strong LL(k)의 조건을 만족하는 가를 검사하는 방법 • k의 값을 1부터 차례로 증가시켜 가면서 생성 규칙의 LOOKAHEAD를 구해서 위 조건을 적용 Compiler Lecture Note, LL Parsing Page 40
  • 41. Compiler Lecture Note, LL Parsing Page 41 ▶ Def) LL(k) grammar: 1. S  A    x ∈ VT *, and 2. S  A    y ∈ VT * such that 3. FIRSTk(x) = FIRSTk(y). It follows that 4.  = . ex) S  aAaa | bAba A  b |  S S a A a a b A b a b   lookahead가 ba일 때 A  b, A   중 어느 rule을 택할 수 있는가? 이제 본 symbol이 a이면 A  b를 선택하고, b이면 A   를 선택한다. 따라서 SLL(2)는 아니며 LL(2)가 된다. * * * * 2-LOOKAHEAD(A→b) = {ba, bb} 2-LOOKAHEAD(A→) = {aa, ba} ∴ strong LL(2) 문법이 아니다.
  • 42. Compiler Lecture Note, LL Parsing Page 42 ▶ SLL(k) and LL(k) ▶ <theorem> strong LL(1)  LL(1) Proof) () clear! () Suppose that G is not strong LL(1). Then, by definition, there are two distinct productions A   and A   such that, S  1A1  11  111  111 S  2A2  22  222  222 and FIRST(11) = FIRST(22). SLL(k) LL(k) * * * * * *
  • 43. Compiler Lecture Note, LL Parsing Page 43 Now we must prove that G is not LL(1). 1) 1= 2= , G is not LL(1). Indeed, it is ambiguous. 2) one (or both) of 1 and 2 is not . 1 . FIRST1(1 1) = FIRST1(1) = FIRST1(2 2). but then, S  2A2  22  2 12  212 S  2A2  22  2 22  222 satisfy the property FIRST1(1 2) = FIRST1(1) = FIRST1(2 2). Thus, by definition, G is not LL(1). * * * * * *