Page 1
299
11. CFG의 Ambiguity(모호성)
11.1 Parse tree 302
11.2 Parse Tree와 CFG의 Ambiguity(모호성) 305
11.3 CFG의 Ambiguity를 제거하는 기법 307
괄호로 묶는 법, Rule 적용 순서를 고정하는 법동일한 내용을 생성하는 rule을 제거하는 법Precedence (우선운위)와 associativity (결합순위)를 정하는 법
되새김(rumination) 317
연습문제 318
Page 3
301
11. CFG의 Ambiguity(모호성)
우리가 쓰는 자연어에서 문장의 의미(semantics) 또는 구조(structure)가 여러 개로 해석되면 모호하다(ambiguous)고
한다. 의미가 모호한 것을 semantic ambiguity(어의적 모호성) 또는 lexical ambiguity(어휘적 모호성)이라 하고, 문법적
구조가 다양한 것을 syntactic ambiguity(문맥적 모호성)라 한다. 예를 들면, “밤”을 먹는 밤과 어두운 밤으로 해석할 수
있고 “시원하다.”를 바람이 불어 시원하다는 뜻과 문제가 해결되어 시원하다는 뜻으로 해석할 수 있다. 따라서 이 두
표현은 lexical ambiguity를 갖고 있다. “나는 새를 좋아한다.”에서 “나는” 을 명사 절 (noun phrase)로 해석할 수도 있고,
새를 수식하는 형용 구로 해석할 수도 있으므로 이 문장은 syntactic ambiguity를 갖고 있다. 이 장에서는 프로그래밍
언어에서 중요한 문제로 다루는 CFG의 syntactic ambiguity에 대하여 공부한다.
Page 4
302
11.1 Parse Tree
Ambiguity
형식언어에서 string (즉, 문장)의 구조는 string을 생성할 때 적용되는
rule과 그 순서에 따라 결정된다. 따라서 어떤 string x를 여러 절차로
생성할 수 있다면, 이는 x의 구조를 여러 가지로 해석할 수 있음을
뜻한다.
CFG가 string을 어떻게 derive 하는지를 보여줄 때 흔히 쓰는 방법이
parse tree다. 아래 그림 (b)는 그림 (a)의 CFG G가 string pqr을
생성하는 과정을 보여주는 parse tree다.
SS S
SSA
A Ap
q r
(b)(a)
G: S SSSSSA
A pqr
Page 5
303
Parse tree는 아래 그림과 같이 적용하는 rule의 좌측에 있는
nonterminal 기호를 tree의 node에 두고 rule의 우측에 있는 symbol들을
좌측으로부터 차례로 자식 node에 두어 만든다. Parse tree의 각 leaf
node에는 terminal symbol이 있어야 하며, 이들을 좌측에서 우측으로
가며 모아 만든 string을 parse tree의 생성물(yield)라 한다. CFG가
생성하는 모든 string은 이들을 생성하는 parse tree로 표현할 수 있음을
알 수 있다.
AmbiguityParse Tree
SS S
SSA
A Ap
q r
(b)(a)
G: S SSSSSA
A pqr
Page 6
304
parse tree
Compiler는 한 명령을 주면, 이를 생성하는 parse tree를 만든 후 이
tree를 따라 leaf node로부터 root로 가며 object code를 생성한다. 아래의
CFG에 의하여 생성된 string pqr이 Boolean expression이라 하자.
Compiler는 leaf node에 있는 두 변수 q, r의 값을 memory로부터 읽어온
다음, tree의 오른쪽 가지에 있는 AND operation qr을 계산하는 object
code(기계어 명령)를 먼저 만들고, 계산 결과를 좌측 leaf node p의
값과 OR 연산을 하는 object code를 생성한다. 결과적으로 이 parse
tree의 구조는 pqr을 p( qr )와 같이 AND operation을 먼저 한 다음,
OR를 한다는 operation의 우선순위를 정해준다.
Ambiguity
S
S S
SSA
A Ap
q r
(b)(a)
G: S SSSSSA
A pqr
Page 7
305
아래 그림은 예의 CFG G가 string pqr을 두 절차로 생성할 수
있음을 보여준다. 그림 (b)의 parse tree는 rule S SS을 먼저 적용하여
만든 것이고, 그림 (c)는 S SS을 먼저 적용한 것이다. 그림 (b), (c)의
제목은 같은 표현 pqr에 대하여 operator를 적용하는 순서, 즉
우선순위(precedence)가 다름을 보여준다.
(b) p(qr)
S
S S
SSA
A A
p
q r
S
S S
SS A
A A
p q
r
(c) (pq)r
G: S SSSSSA
A pqr
(a)
11.2 Parse Tree 와 Ambiguity
Ambiguity
Page 8
306
앞의 예에서 본 바와 같이 ambiguity는 programming 언어 model인
CFG에서 매우 중요하게 다루는 요소이다. Ambiguous CFG를 다음과
같이 정의한다.
임의의 CFG가 ambiguous 한지를 밝히거나, 임의의 ambiguous한
CFG를 unambiguous한 CFG로 전환하는 일반화된 algorithm은 없다.
그러나 앞의 예와 같이 특정한 CFG가 ambiguous 한지를 밝히거나,
이를 unambiguous한 CFG로 전환하는 것은 가능하다. 이을 위한
몇 가지 기법을 예를 들어 소개하기로 한다.
AmbiguityParse Tree와 Ambiguity
정의 (CFG의 Ambiguity): CFG G의 언어에 두 개의 서로 다른 parse
tree에 의하여 생성될 수 있는 string이 있으면, grammar G는
ambiguous하다고 한다.
Page 9
307
11.3 CFG의 모호성 제거하기
(1) 괄호로 묶는 방법.
예: 아래의 CFG G1은, 앞서 본 바와 같이, string pqr을 생성하는 두
parse tree가 있으므로 ambiguous 한 CFG이다. 이 grammar의 모호성은
rule S SS과 S SS 중 어느 것을 먼저 적용해도 같은 string을
생성할 수 있기 때문이다.
Ambiguity
(b) p(qr)
S
S S
SSA
A A
p
q r
S
S S
SS A
A A
p q
r
(c) (pq)r
G: S SSSSSA
A pqr
(a)
Page 10
308
CFG의 모호성 제거하기
S
S S
SS A
A A
p q
r
(b) ((p q ) r)
( )
( )
(a) (p (q r))
S
S S
SA
A A
p
q r
( )
( )S
Ambiguous G1: S SSSSSA A pqr
Unambiguous G2: S (SS)(SS)S A A pqr
이와 같은 모호성을 제거하는 간단한 방법은 아래의 CFG G2와 같이
문제가 되는 rule의 우측을 괄호로 묶어 두 parse tree가 생성하는
string이 서로 다르게 만드는 것이다.
Ambiguity
Page 11
309
CFG의 모호성 제거하기
괄호를 이용하는 방법은 간단하여 적용하기 쉽지만, 괄호를 위한 두
terminal symbol을 추가해야 하므로, 주어진 문법이 발생하는 언어가
바뀌게 되어, 바람직한 방법이 아니다. 그러나 이 방법은 프로그래밍
언어 Pascal의 begin-end, C 또는 C++의 block 표시 {. . .}와 같이 흔히 쓰는
간단한 방법이다.
Ambiguity
Family Gift
Amanpreet heard a rumor that his father, grandfather and great-grandfather had all walked on water on their
21st birthdays. So, on his 21st birthday, Amanpreet and his good friend Brian headed out to the lake. "If they did
it, I can too!" he insisted. When Amanpreet and Brian arrived at the lake, they rented a boat and began paddling.
When the got to the middle of the lake, Amanpreet stepped off of the side of the boat . . . and nearly drowned.
Furious and somewhat shamed, he and Brian headed for home.
When Amanpreet arrived back at the family farm, he asked his grandmother for an explanation. "Grandma, why
can I not walk on water like my father, and his father, and his father before him?“ The feeble old grandmother
took Amanpreet by the hands, looked into his eyes, and explained, "That's because your father, grandfather, and
great-grandfather were born in January . . . you were born in July, dear.“
- Raman -
쉬어 가기
Page 12
310
S
bS
bS
c
S
bS
bS
c
G3 : S bSSbc
CFG의 모호성 제거하기
예: (a) 아래의 CFG G3의 언어는 {bicbj | i, j 0} 이다. 아래의 두 parse
tree는 같은 string bcb를 생성한다. Rule S bS를 먼저 적용하여
좌측에 있는 b를 생성한 다음, 우측의 b를 생성하거나, 이와 역순으로
생성할 수 있다. 따라서 G3 는 ambiguous 하다.
Ambiguity
(2) Rule을 적용하는 순서를 제한하는 방법
Page 13
311
Ambiguous G3 : S bSSbc
Unambiguous G4 : S bSA AAbc
CFG의 모호성 제거하기
G3를 수정하여 아래의 G4와 같이 좌측의 b를 먼저 생성한 다음,
우측의 b를 생성하도록 rule을 수정하여 모호성을 제거한다. 그림
(b)는 bcb를 생성하는 유일한 parse tree다.
S
bS
bS
c
S
bS
bS
c
(a)
Sb
S
b
A
A
c
(b)
Ambiguity
Page 14
312
CFG의 모호성 제거하기
예: (b) 앞서 예로 들었던 ambiguous CFG G1은 아래의 G5와 같이
string에 나타나는 operator의 순으로 좌측에서 우측으로 차례로
생성하도록 rule을 바꾸어 모호성을 제거할 수 있다.
S
SA
SA
SA
p
q
S
A
p
q
(b) p qq p
G1: S SSSSSA
A pqr
Ambiguous:
G5 : S ASASSA
A pqr
Unambiguous:
(a)
Ambiguity
Page 15
313
(3) 동일한 string을 발생할 수 있는 rule들을 제거하는 방법.
Ambiguous G8 : S BD B bBc D dDe
Unambiguous G9 : S BD B bBcbc
D dDede
아래의 CFG G8의 모호성은 두 -production rule 때문이다. 따라서 -
production rule을 줄이는 방법을 적용하여 G9와 같이 모호성을
제거한다.
Ambiguous G6 : S BD B abb D abd
Unambiguous G7 : S BD B abb D d
CFG의 모호성 제거하기
다음 CFG G6는 B ab와 D ab 중 하나만 두어 unambiguous한
CFG G7을 만든다.
Ambiguity
Page 16
314
(4) Precedence (우선순위) 와 associativity (결합순위) 를 정하기
Programming language는 서로 다른 operator들 사이에 precedence
(우선순위)를 두고 , 같은 precedence를 가진 operator들 사이에
associativity(결합순위)를 두어 계산 순서가 모호하지 않도록 할 수 있다.
예를 들면, 아래 그림 (a)의 산술 문에 있는 operator들은 그림 (b)와 같은
순서로 이행한다. 곱셈과 나눗셈의 precedence가 덧셈과 뺄셈보다 높고,
assignment operator(=)가 가장 낮으며, 같은 precedence를 가진 곱셈과
나눗셈, 그리고 뺄셈과 덧셈의 associativity는 좌측에서 우측으로 (즉, left
associativity) 지정되어 있기 때문이다.
이러한 precedence와 associativity는 언어의 문법에 따라 결정된다.
문법이 어떻게 precedence와 associativity를 정하는지 알아보기로 하자.
a = b + c * d – e / f
(a)
Ambiguity
(b)
a = ((b + (c * d)) – (e / f))
(5) (3) (1) (4) (2)
CFG의 모호성 제거하기
Page 17
315
Precedence 와 associativity 를 정하기
G10 : S DSD D CDC
C CA A pqr
(a)
C~
A
D
C D
A
A
S
SD
DS
C
C
A C
p q r
p(b)
아래 CFG G10는 앞서 예로 든 ambiguous CFG G1을 수정하여
precedence와 associativity를 정한 것이다. G10은 항상 을 먼저 생성한
다음, 과 순으로 발생하도록 rule이 구성되어 있다. 그림 (b)의 parse
tree를 보면, operator의 precedence가 낮을수록 높은 level (즉,
root에 가까이)에서 생성되어야 한다는 것을 알 수 있다.
Ambiguity
Page 18
316
Precedence 와 associativity 를 정하기
G10 : S DSD D CDC
C CA A pqr
(a)
C~
A
D
C D
A
A
S
SD
DS
C
C
A C
p q r
p(b)
G10의 rule을 보면, 같은 operator, 예를 들어, 는 좌로부터 우측으로
가며 생성되므로 우측에 있는 가 좌측에 있는 것보다 parse tree
상에서 하위에 있게 된다. 따라서 associativity는 계산이 우측에서
좌측으로 진행히도록 지정되었다. 만일 rule S DS를 S SD로
바꾸면 associativity는 반대로 된다.
Ambiguity
Page 19
317
앞서 보았던 예들과 같이 CFG가 비교적 단순하면, 모호한지를 알 수 있다. 그러나 아래와 같은 사실이
말해주는 것과 같이 CFG의 모호성에 관한 문제는 대부분 매우 어렵거나 해결 불가능한 문제이다.
• 임의의 CFG G가 주어졌을 때, G가 모호한지를 판단할 수 있는 algorithm은 존재하지 않는다. 다시 말하면, 이
문제는 해결 불가능한(unsolvable) 문제이다.
• CFL L에 대하여 L을 발생하는 모든 CFG가 ambiguous 할 때, L을 선천적으로(inherently) 모호한 context-free
언어라 한다. 다음의 언어가 한 예이다.
L = {anbncmdm n, m 1} {anbmcmdn n, m 1}.
• 임의의 모호한 (그러나 선천적으로 모호하지 않은) CFG G가 주어졌을 때, G를 모호하지 않은 CFG로 전환하는
algorithm은 있을 수 없다.
Rumination: ambiguity
Ambiguity
Page 20
318
연습문제
11.2 (a) 다음 CFG가 ambiguous하다는 것을 보이라.
G: S S + S | S * S | T T a | b
(b) 기호 +를 덧셈 operator, *를 곱셈 operator 라 하면, 위의 grammar는 두 변수 a, b 를 가진 산술 연산식을 발생한다.
위의 grammar를 다음 조건을 만족하는 unambiguous한 CFG G’로 전환하라.
(i) L(G) = L(G‟)
(ii) Operator *가 operator +보다 precedence가 높다.
(iii) 두 operator 모두 left-to-right associativity 를 갖는다.
Grammar G’와 함께 위의 두 조건을 만족함을 보이는 parse tree 예도 제시하라.
11.1 다음 각 CFG가 ambiguous 하다는 것을 밝히고 같은 언어를 발생하는 unambiguous 한 CFG를 만들어 보이라.
(a) S Sa | A | a A a | bA
(b) S AB | A a | B b |
Ambiguity
Page 21
319
11.3 아래의 syntax flow graph은 Pascal programming 언어의 <IF-statement>를 간추린 것이다. 관례에 따라 원 또는 타원
안에 있는 string은 모두 terminal string이며, 꺾임 괄호 안의 것은 nonterminal 기호에 해당한다.
(a) 주어진 syntax flow graph을 CFG G로 전환하고 grammar G가 ambiguous 하다는 것을 보이라.
(b) 위의 grammar G를 unambiguous한 CFG로 전환하고, 그 과정을 설명하라.
<IF-statement>
IF ( <bool> ) then else<statement> <statement>
c
d
<bool>
<IF-statement>
a + b
<statement>a - b
다음 문제는 programming 언어에서 ambiguous한 실예를 들 때 mathematical expression과 함께 자주 등장하는 것이다.
문제의 질문 (a)는 grammar가 ambiguous 함을 증명하는 것으로 어렵지 않게 답할 수 있으나, 질문 (b)는
간단히 답할 수 있는 문제가 아니다. 면밀한 분석을 요구하는 흥미로운 문제이다.
Page 22
320
12. Chomsky Hierarchy II:
정규포함 관계
12.1 언어 class들 사이의 포함관계 32512.2 Regular 언어에 대한 pumping lemma 329
Lemma 증명12.3 Pumping lemma 응용 339
응용 예되새김(rumination) 344
12.4 CFL에 대한 pumping lemma 34712.5 CFL에 대한 pumping lemma 응용 350되새김(rumination) 35412.6 Ogden’s lemma 355
Lemma 응용12.7 CFL에 대한 pumping lemma 증명 358연습문제 363
Page 24
322
Chomsky Hierarchy
Recursively
Enumerable
Sets (type 0)
Turing Machines
(TM)
Post System,
Markov Algorithms,
-recursive Functions
Regular
Expression
Context-sensitive
Languages(type 1)
Context-free
Languages(type 2)
Regular
Languages(type3)
Linear-boundedAutomata
(LBA)
PushdownAutomata
(PDA)
Finite StateAutomata
(FA)
.
.
.
.
.
Languages (grammars) Machines 기타 Models
Review형식언어 및 오토마타 체계 II
Page 25
323
12. Chomsky Hierarchy II: 정규포함 관계
우리는 7장에서 여러 형식언어와 automata 사이의 계층적 체계인 소위 Chomsky hierarchy를 소개하고 최하위에
있는 regular language 계층의 횡적 관계, 즉 특성화 (characterization) 관계를 증명하였다. 이 장에서는 다시 Chomsky
hierarchy로 돌아가, 하위 두 계층 사이의 수직 관계를 증명하기로 한다. 아래 두 그림은 Chomsky hierarchy의 수직
관계, 즉 언어 집단 (language class)들 사이의 정규 포함 ( , 즉 proper containment) 관계와 automata 기능 사이의 정규
포함 관계를 나타낸다. 하위 class에 있는 언어는 상위 class 언어의 일종이며, 상위 class 언어 중에는 하위 class에
속하지 않은 언어가 있다는 뜻이다. Automata 측면에서, 상위 class에 속한 automata는 하위 class에 속한 automata가
인식하는 언어를 인식할 수 있지만, 그 역은 참이 아니라는 뜻이다.
형식언어 및 오토마타 체계 II
(a) Language class의 포함관계
TMLBA
PDAFA
(b) Automata 기능의 포함관계
Type-0L Type-1L Type-2L
Type-3L
Page 26
324
형식언어 및 오토마타 체계 II정규포함관계
Chomsky hierarchy의 상위 계층에 갈수록 계층의 특성화 관계와 계층들 사이의 정규포함관계를 증명하려면,
더 깊은 논리적인 사고가 필요하며, 이를 위하여 1장에서 배운 증명법이 많은 도움을 줄 것이다. Chomsky hierarchy의
증명을 이해하고 나면, computer science를 공부하는 과정에 등장하는 논리적인 문제를 극복할 수 있는 지식을 갖추게
될 것이다.
May You Have
May you have enough happiness to make you sweet,
enough trials to make you strong,
enough sorrow to keep you human,
enough hope to make you happy and
Enough money to buy gift!
- Anonymous -
쉬어 가기
Page 27
325
형식언어 및 오토마타 체계 II
Language class들 사이의 정규포함관계(, proper containment)를
증명하기에 앞서, 다음 Theorem이 말하는 포함관계 (, containment)를
증명하기로 한다.
Theorem. Type i (i = 0, 1, 2, 3) language class를 Type-iL이라 하자. 모든
i < 3에 대하여 다음과 같은 포함관계가 성립한다.
Type-iL Type-(i+1)L
증명. Grammar G = (VT, VN, P, S)의 rule을 라 하자. 정의에 의하여
type 3 (regular) grammar rule의 형식은 type 2 grammar (CFG) rule의 조건
|| = 1에 추가 조건 = xB 또는 = x (단, x (VT)*, B VN)을 둔 것이다.
따라서 type 3 grammar는 type 2 grammar의 일종이다. 그러므로 type 3
언어는 모두 type 2 언어에 속한다. 즉,
Type-2L Type-3L
12. 1 언어 class 사이의 포함관계
Page 28
326
형식언어 및 오토마타 체계 II포함관계
증명(계속). 정의에 의하여 type 1 grammar (CSG) rule은 type 0 grammar
rule 형식에 rule의 좌측이 우측보다 길 수 없다는 제한조건을 갖고
있다. 따라서 type 1 grammar는 모두 type 0 grammar이다. 따라서
Type-0L Type-1L.
CSG rule은 type 0 grammar rule에 조건 || ||를, CFG rule은 type 0
grammar rule에 조건 || = 1을 추가한 것이다. 따라서Type-1L과 Type 2L
사이의 포함관계를 앞서 적용한 것과 같은 단순한 논리를 이용하여
증명할 수 없다. 문제는 -production rule이다. CSG는 start 기호에
한하여 S 을 허용하고 A 와 같은 임의의 nonterminal 기호는 을
생성할 수 없다. 이는 rule의 좌측이 우측보다 길 수 없다는 CSG
조건에 맞지 않기 때문이다. 반면 CFG는 위와 같은 -production rule을
모두 허용한다. CFG의 rule 중에 -production rule이 아닌 rule은 모두
CSG의 rule 조건을 만족하므로 문제가 될 수 없다.
Page 29
327
우리가 10.1절에서 배운 CFG의 -production의 수를 최소로 줄일 수
있다는 다음의 Theorem을 기억한다면, CFG의 -production rule 문제는
쉽게 해결할 수 있다.
위의 조건을 만족하는 CFG G'는 모두 CSG이다. 이 Theorem은 모든
CFL은 일종의 CSG로 생성할 수 있다는 뜻이다. 따라서
Type-1L Type-2L.
Theorem. 임의의 CFG G가 주어졌다 하자. 다음 조건을 만족하는 CFG
G´을 만들 수 있다.
• L(G) = L(G´)
• L(G)면, G´에는 - production rule이 없다.
• L(G) 면, S 는 G´이 가지고 있는 유일한 -production rule이다.
형식언어 및 오토마타 체계 II포함관계
Page 30
328
형식언어 및 오토마타 체계 II포함관계
이를 위하여 각 i (= 0, 1, 2, 3)에 대하여, 상위 class Type-iL에 속하면서
하위 class Type-(i+1)L에 속하지 않는 언어 하나를 제시할 수 있으면
충분하다. 이 장에서는 우리가 아는 CFL {aibi | i 0 }가 regular language가
아니며, CSL {aibici | i 0 }는 CFL가 아님을 보여 Type-1L Type-2L Type-
3L임을 증명한다. 나머지 상위 두 class 사의의 정규포함관계 Type-0L
Type-1L은 더 깊은 논증을 다루는 15장으로 미루기로 한다.
앞서 밝힌 결과들을 종합하면 language class들 사이에 다음과 같은
포함 관계를 얻는다.
Type-0L Type-1L Type-2L Type-3L
이제 우리의 목표는 이 포함관계를 다음과 같은 정규포함관계 (proper
containment)로 발전시키는 것이다.
Type-0L Type-1L Type-2L Type-3L
Page 31
329
12.2 Pumping Lemma
우리는 앞 절에서 Chomsky hierarchy의 하위 계층은 상위 계층에
포함되어 있음을 증명하였다. 이 포함관계가 정규포함 관계임(proper
containment)을 증명하려면, 상위계층에 있지만 하위계층에 없는 언어
하나를 보여줌으로 충분하다. 먼저 CFL와 regular language 사이의 관계,
즉 모든 regular language는 CFL이지만 , CFL 중에는 regular
language가 아닌 언어가 있음을 증명한다.
증명을 위하여 먼저 regular language들이 공유하고 있는 한 특성을
찾아내고, 이 특성이 없는 CFL를 보여주기로 한다. 이러한 특성은
어디서 찾을 수 있을까? 크기가 유한한 언어는 모두 regular이다. (이
절의 되새김 참조.) 따라서 regular 언어에 있으면서 CFL에 없는 특성은
크기가 무한한 언어 중에서 찾아야 한다. 다음 Lemma가 그러한 특성을
제시한다.
형식언어 및 오토마타 체계 II
Page 32
330
Pumping Lemma
Pumping Lemma: L을 크기가 무한한 임의의 regular language라 할 때,
다음 조건을 만족하는 상수 n이 있다.
형식언어 및 오토마타 체계 II
Language L의 alphabet을 라 하자. L에 있는 길이가 n보다 크거나
같은 모든 string z에 대하여 아래의 조건을 만족하는 string u, v, w가
있다.
• z = uvw, |uv| n, |v| 1
• 모든 i 0에 대하여 uviw L
Page 33
331
Pumping Lemma
증명: M을 언어 L을 인식하는 DFA의 state transition graph이라 하자.
Graph M 상에서 edge의 방향을 따라 두 state를 연결하는 길을 state
transition path라 하고, 이 path의 각 edge 상에 있는 기호를
차례로 모아 만든 string을 그 state transition path의 path label이라 하자.
아래의 state transition graph 상에서 state 1 2 4 3 2 4를
차례로 잇는 edge로 구성된 transition path의 path label은 aabba 이다.
물론 이 DFA에 aabba를 input로 주면 path 1 2 4 3 2 4를
따라 transition이 발생한다.
형식언어 및 오토마타 체계 II
a
b
b
a
a
b
start 1
2
3
4
Page 34
332
L을 크기가 무한한 임의의 regular 언어라 하고, 이를 인식하는
DFA의 state transition graph를 M, state 수를 n이라 하자. 언어 L 내에
있는 길이가 n보다 크거나 같은 임의의 string z (즉, |z| n)를 input로
주었을 때 M 상에서 transition이 어떻게 진행하는지 알아보자. State의
수 n이 유한하고 언어 L이 무한하므로, L에는 길이가 n보다 길거나
같은 string z가 있다 ( 즉, |z| n ).
String z의 길이가 m ( n)이라 하고, z = a1a2 …am라 하자. 이해를 돕기
위하여 예로 들었던 다음의 DFA를 이용하기로 한다.
Pumping Lemma: 증명형식언어 및 오토마타 체계 II
a
b
b
a
a
b
start 1
2
3
4
Page 35
333
Pumping Lemma: 증명
String z의 길이 |z| = m ≥ n이므로, 아래 그림 (b)와 같이 z를 label로
갖는 transition path에는 cycle이 반드시 존재한다. 즉, path 상에 두 번
방문한 state (그림의 q)가 있다. 이 사실은 Pigeonhole Principle을
이용하거나, proof-by-induction 방법으로 쉽게 증명할 수 있다. (1장의
pigeonhole principle 응용 예, 또는 연습문제 1.8 참조. )
형식언어 및 오토마타 체계 II
a
b
b
a
a
b
start 1
2
3
4
(a) Label aabba를 갖는 path (b) Label a1a2 …am를 갖는 path
qstart a1
M
a2
ai
...
ai+1aj
aj+1..
. am
|z| = m n
Page 36
334
Pumping Lemma: 증명
String z가 DFA M이 인식하는 언어 L에 포함되어 있으므로 input z에
의한 transition은 그림과 같이 accepting state (예의 4)에서 끝나야 한다.
형식언어 및 오토마타 체계 II
a
b
b
a
a
b
start 1
2
3
4
(a) Label aabba을 갖는 path
qstart
a1
M
a2
ai
...
ai+1aj
aj+
1
..
. am
(b) Label a1a2 …am을 갖는 path
|z| = m n
Page 37
335
Pumping Lemma: 증명
아래 그림처럼 z를 label로 갖는 transition path에서 cycle 이전 부분의
path label을 u, cycle 부분의 path label을 v, cycle 이후부터 accepting state
까지의 path label을 w라 하자. State q가 start state이면 u = , transition
path의 최종 state이면 w = 이다. Cycle 부분 v는 최소한 하나의
symbol이 있어야 하므로 |v| 1이다.
형식언어 및 오토마타 체계 II
a
b
b
a
a
b
start 1
2
3
4
|z| = m n |v| 1
z = a1a2 …ai ai+1 . . . . aj aj+1 . . . .am
u v w
qstart
a1
M
a2
ai
...
ai+1aj
aj+
1
..
. am
uv
w
u = a, v = abb, w = a
Page 38
336
Pumping Lemma: 증명
Node의 수가 n인 방향성 graph에서 길이가 n인 path는 반드시
cycle을 거치므로 |uv| n인 조건이 성립한다.
형식언어 및 오토마타 체계 II
a
b
b
a
a
b
start 1
2
3
4
u = a, v = abb, w = az = a1a2 …ai ai+1 . . . . aj aj+1 . . . .am
u v w
qstart
a1
M
a2
ai
...
ai+1aj
aj+
1
..
. am
uv
w
|v| 1|z| = m n |uv| n
Page 39
337
Pumping Lemma: 증명
M은, string uvw를 accept하므로, string uw = uv0w를 (cycle을
거치지 않고) accept 하며, uvvw = uv2w를 (cycle을 두 번 돌아) accept
한다. 같은 논리로, 모든 i ( 0)에 대하여, M은 string uviw를 (cycle을
i 번 돌아) accept 한다. 따라서 모든 i 0에 대하여 uviw L이다.
형식언어 및 오토마타 체계 II
z = a1a2 …ai ai+1 . . . . aj aj+1 . . . .am
u v w
qstart
a1
M
a2
ai
...
ai+1aj
aj+
1
..
. am
uv
w
For all i 0, uviw L
|v| 1|z| = m n |uv| n
u = a, v = abb, w = a
For all i 0, a(abb)ia L
a
b
b
a
a
b
start 1
2
3
4
Page 40
338
Pumping Lemma: 증명
따라서 다음의 pumping lemma가 성립한다.
형식언어 및 오토마타 체계 II
Language L에 있는 길이가 n보다 크거나 같은 모든 string z에 대하여
아래의 조건을 만족하는 string u, v, w가 있다.
• z = uvw, |uv| n, |v| 1
• 모든 i 0 에 대하여 uviw L
P u m p i n g L e m m a : L 을 크 기 가 무 한 한 임 의 의 r e g u l a r
language라 할 때, 다음 조건을 만족하는 상수 n이 있다.
Pressure
Pressure is part of life: adapt to it and use it! I don‟t do without pressure.
A physical therapist said, “Get in tune with your body.”
But if I listened to my body, I‟d stay in bed all morning.”
- Stan Pottinger -
쉬어 가기
Page 41
339
이제 pumping lemma를 이용하여 regular language가 아닌 CFL가
있음을 증명하자. 응용에 앞서, 편이 상 lemma에 있는 논리적인
요소가 분명히 드러나도록 다음과 같이 lemma를 정리하여 다시 쓴다.
12.3 Pumping Lemma 응용
(1) 크기가 무한한 모든 regular 언어 L에 대하여, // regular language L,
(2) 다음 조건을 만족하는 상수 n이 있다. // a constant n such that
(3) | z | n인 모든 string z L에 대하여, // string z L, | z | n
(4) 다음 네 조건을 만족하는
string u, v 및 w가 있다. // strings u, v, w such that
(i) z = uvw,
(ii) |uv| n,
(iii) |v| 1,
(iv) 모든 정수 i 0에 대하여,
uviw L. // i 0, uviw L.
형식언어 및 오토마타 체계 II
Page 42
340
Pumping Lemma: 응용형식언어 및 오토마타 체계 II
응용에 앞서 1장에서 증명법을 배울 때 existential quantification
(, 내재적 계량)과 universal quantification(, 보편적 계량)을 처리하는
방법을 복습하자. 응용은 특정한 CFL에 대하여 pumping lemma가 옳지
않음을 증명하는 것이다.
따라서 lemma의 existential quantification을 가진 변수들 (n, strings u, v,
w)은 모든 값을 다 고려해야 한다. 반면, universal quantification을 가진
변수들 (regular language L, 길이가 n인 string z L , 정수 i 0)은
증명에 편리한 하나의 값을 선택하면 충분하다.
증명은 pumping lemma를 주장하는 사람과 선택한 CFL가 pumping
lemma를 만족하지 않는다고 주장하는 우리와의 논리적인 게임으로
다음과 같이 전개할 수 있다.
Page 43
341
이제 우리가 잘 아는 CFL L = {aibi | i 1 }이 pumping lemma를 만족하지
않기 때문에 regular 언어가 아님을 증명한다. L이 regular language라
가정하자. (이 말투는 1장에서 배운 proof-by-contradiction을 쓸 것임을
암시한다 . ) Lemma의 논리적 줄거리를 따라가며 L이 lemma를
만족하지 않으므로 가정이 틀린다는 주장을 펼친다.
Pumping Lemma: 응용
(1) 크기가 무한한 모든 regular
languages L 에 대하여,
(2) 다음 조건 (3), (4) 를
만족하는 상수 n이 있다.
(3) . . . . .
(4) . . . .
L은 크기가 무한한 r eg u la r
언어이다. 따라서 lemma의 조건
(3)과 (4)를 만족하는 상수 n이
있다 . 이 상수가 어떤 값이든
그것을 n이라 하자. (즉, n의 모든
경우의 값을 동시에 고려한다.)
Pumping Lemma 의 주장 우리의 주장
형식언어 및 오토마타 체계 II
Page 44
342
Pumping Lemma: 응용
(3) | z | n인 모든
string z L에 대하여,
(4) 다음 조건을 만족하는
string u, v 및 w가 있다.
(i) z = uvw,
(ii) |uv| n,
(iii) |v| 1,
(iv) 모든 정수 i 0에 대하여,
uviw L.
L에 있는 string z = anbn를
선택한다. String z가 조건 (4)의
(i) – (iii)을 만족하는 모든 u, v,
w가 조건(iv)를 만족하는지 알아
보자.
조건 (i)에 따라, z = anbn =
uvw라 두면, 조건 (ii)과 (iii)에
의하여 v는 그림과 같이 z의
전 반 부 , 즉 a 만 있 는 곳 의
string이다.aa . . . . . . . .a bb . . . . . . . . .b
n n
u v w
|uv| n
Pumping Lemma 의 주장 우리의 주장
형식언어 및 오토마타 체계 II
Page 45
343
Pumping Lemma: 응용
(3) | z | n인 모든
string z L에 대하여,
(4) 다음 조건을 만족하는
string u, v 및 w가 있다.
(i) z = uvw,
(ii) |uv| n,
(iii) |v| 1,
(iv) 모든 정수 i 0에 대하여,
uviw L.
마지막으로 z가 lemma의 조건
(iv)를 만족하는지 따져보자. String
v는 a만으로 구성되어 있으므로,
uv2w에는 a의 수가 b의 수보다
많다. 즉, i = 2일 때, uv2w L.
언어 L은 p u m p i n g l e m m a 를
만족하지 못하므로 regular 언어가
아니다.
aa . . . . . . . .a bb . . . . . . . . .b
n n
u v w
|uv| n
Pumping Lemma 의 주장 우리의 주장
형식언어 및 오토마타 체계 II
Page 46
344
Rumination: Pumping Lemma 응용
(1) 우리는 언어 L = {aibi | i 1 }이 CFL임을 잘 알고 있다. 이 언어가 regular 언어가 아님을 증명하였으므로 우리가
이미 12.1 절에서 증명한 CFL class와 regular 언어 class 사이의 포함관계 Type-2L Type-3L는 실제로 정규포함관계
Type-2L Type-3L임을 증명한 것이다.
(2) 위의 증명은 L에 대하여 lemma가 참이 아님을 보이는 것이다. 이때 existential quantification (, 즉 있다, 또는
존재한다)과 universal quantification (, 즉 모든)을 어떻게 처리하고 있는지 검토해 보자.
Lemma에는 두 곳 (2), (4)에 “. . . 가 있다.”라는 형식으로 existential quantification을 쓰고 있으며, (1), (3), (iv)에
“모든. . .에 대하여”라는 형식으로universal quantification을 쓰고 있다. Lemma가 참이 아님을 보이려면, existential
quantification 부분은 주어진 모든 경우를 고려해야 하며, universal quantification 부분은 한 가지 예를 고려하는 것으로
충분하다.
따라서 (2) 번에 있는 “… 상수 n이 있다.”라는 부분에 대하여 증명은 n을 변수로 이용하여 모든 상수를 동시에
고려하고 있다. Lemma의 (4)번에 있는 “ … u, v 및 w 가 있다.”라는 부분 역시 조건 (i) – (iii)을 만족하는 모든 u,
v, w를 고려하여 논리를 전개하고 있다.
한편, (1) 번의 “모든 regular languages…” 부분에 대하여, 증명은 주어진 언어 L = {aibi | i 1}을 택하고, (3) 번의
“모든 string z …” 부분에 대한 증명은 특정한 string z = anbn를, (iv) 번의 “모든 정수 i 0 …”에 대한 증명은
i = 2를 택하였다. (물론 z = anbn 와 i = 2 대신 다른 값을 택할 수 있다.)
형식언어 및 오토마타 체계 II
Page 47
345
Rumination: Pumping Lemma 응용
(3) 다음은 학생들이 제출한 답에서 흔히 볼 수 있는 pumping lemma를 잘못 적용한 예를 보여준다.
문제: L = {abcaiabc | i 0 }이 regular language인지를 밝히라.
답: L은 regular language가 아니다. L이 regular라고 가정하자. L은 pumping lemma를 만족해야 한다. 정수 n을 lemma의
상수라 하고, z = abcanabc라 두자. |z| n이므로 string z는 lemma의 조건 (2)를 만족한다. 이제 z = uvw라 두고, u = a, v
= b, w = canabc일 때 lemma를 만족하는지 따져 보자. String uv2w = abbcanabc은 L에 없는 것이다. L은 pumping
lemma를 만족하지 못하므로 regular language 가 아니다!!
L은 아래의 FA가 인식하는 regular language다. 이 증명에 무엇이 잘못되었는가? 증명의 결정적인 오류는 lemma의
조건 (4)의 existential quantification을 쓴 u, v, w에 대하여 특정한 경우, 즉 u = a, v = b, w = canabc인 경우만 예로 들어,
조건 (ii)를 만족하는 다른 경우를 고려하지 않은 데 있다. 다시 말하면, „pump‟ 할 수 있는 위치 v는 길이가 n인 string의
prefix 어디에도 있을 수 있음을 간과했기 때문이다. 만일 v가 string w의 substring an 내에 있다면, 모든 정수 i 0에
대하여, uviw L이므로 lemma를 만족하기 때문에 증명은 실패한다.
형식언어 및 오토마타 체계 II
a b c a cb
a
(4) 다음 조건을 만족하는 string u, v 및 w가 있다.
(i) z = uvw,
(ii) |uv| n,
(iii) |v| 1,
(iv) 모든 정수 i 0 에 대하여,
uviw L.
Page 48
346
(5) Pumping lemma는 크기가 무한한 모든 regular 언어가 갖는 특성이다. ( „For all i ≥ 0, uviw L‟ 부분을 기억하자.)
크기가 유한한 언어는 모두 regular이며, 이를 인식하는 FA의 state transition graph에는 cycle이 존재할 수 없다. 크기가
유한한 언어 L = {w1, w2, . . ., wk }가 있다 하자. L을 인식하는 FA는 아래 그림이 예시하는 것과 같이 각 string wi마다
w i를 path label로 갖는 accepting transition path를 만들어 주면 된다.언어 L이 유한하므로 이 FA의 state
수도 유한하다.
되새김: Pumping Lemma 응용 형식언어 및 오토마타 체계 II
.
.
.
w1
w2
wk
(4) 언어 L이 regular임을 증명하려고 pumping lemma를 이용하려는 학생을 가끔 본다. 이러한 시도는 언어 L을 인식
하는 FA, L을 생성하는 regular grammar, 또는 L을 표현하는 regular expression을 제시하는 것보다 어려울 뿐
아니라, 근본적으로 다음과 같은 논리적 허점을 갖고 있어 옳은 답을 얻을 수 없다.
Pumping lemma는 크기가 무한한 regular 언어가 갖는 공통적인 특성이지만, regular 언어가 아닌 언어에 이러한
특성을 없다는 증명을 한 바 없다. 실제로 pumping lemma를 만족하는 regular 언어가 아닌 언어가 있다. 부록 E 가
그러한 언어를 보여준다. 따라서 한 언어가 pumping lemma를 만족한다고 하여 regular 언어라고 주장할 수 없다.
Page 49
347
12.4 CFL에 대한 Pumping Lemma
CFL에 대한 pumping lemma (uvwxy Theorem). 크기가 무한한 모든
CFL에 대하여 다음 조건을 만족하는 상수 p가 있다.
L에 있는 길이가 p 보다 크거나 같은 모든 string z에 대하여 다음
조건을 만족하는 strings u, v, w, x, y가 있다.
• z = uvwxy, |vwx| p, |vx| 1
• 모든 정수 i 0에 대하여 uviwxiy L
형식언어 및 오토마타 체계 II
CSL class와 CFL class 사이의 정규포함관계, 즉 Type-1L Type-2L의
증명은 12.3절에서 증명한 CFL class와 regular 언어 class 사이의 관계,
즉 Type-2L Type-3L의 증명과 비슷하다. 먼저 크기가 무한한
CFL들이 갖는 아래와 같은 특성을 제시하고, 2.3 절에서 CSL의 한
예로 들었던 언어 { aibici | i ≥ 1}가 이 특성을 만족하지 않음을
증명한다. 증명에 앞서 이 lemma가 regular의 것과 다른 점을 알아보자.
Page 50
348
CFL에 대한 Pumping Lemma
• z = uvw, |uv| n, |v| 1
• 모든 i 0 에 대하여 uviw L
• z = uvwxy, |vwx| p, |vx| 1
• 모든 i 0 에 대하여 uviwxiy L
CFL 용 lemma Regular 언어 용 lemma
u v w
|uv| n
u v w x y
vwx| p
z
형식언어 및 오토마타 체계 II
CFL에 대한 pumping lemma는 regular 언어에 대한 lemma와 매우
유사하다. 아래 그림은 이 두 lemma를 비교한 것이다. Regular 언어에
대한 pumping lemma는 string z 가 u, v, w 세 부분으로 나뉘고 (즉 z = uvw)
pump 할 위치가 하나 (즉, v) 이다. CFL에 대한 lemma에서는 string z가 u,
v, w, x, y 다섯 부분으로 나뉘고 (z = uvwxy), pump 할 위치
(화살표)가 v와 x 두 곳이다 .
Page 51
349
Lemma를 응용할 때, regular 언어용 lemma는 조건 |uv| n에 의하여
pump할 부분 v의 위치를 길이 n인 z의 prefix 부분으로 제한하여
이용하기 편하다. 반면 CFL의 경우, 조건 |vwx| p에 의하여 pump할
부분 v와 x는 넓이가 P인 창(window) 내에 존재하지만, 이 창은 string
z의 어느 곳에나 있을 수 있다. 따라서 이 lemma를 응용하려면
논리적으로 고려해야 할 경우가 많다. 이 lamma를 증명하기에 앞서
응용 예를 보기로 하자.
CFL에 대한 Pumping Lemma
• z = uvw, |uv| n, |v| 1
• 모든 i 0 에 대하여 uviw L
• z = uvwxy, |vwx| p, |vx| 1
• 모든 i 0 에 대하여 uviwxiy L
CFL 용 lemma Regular 언어 용 lemma
u v w
|uv| n
u v w x y
vwx| p
z
형식언어 및 오토마타 체계 II
Page 52
350
(1) 크기가 무한한 모든 CFL L에 대하여
(2) 다음 조건을 만족하는 상수 p가 있다.
(3) |z| p인 조건을 만족하는 모든 string z L에 대하여
(4) 다음 조건을 만족하는 strings u, v, w, x, y가 있다.
(i) z = uvwxy,
(ii) |vwx| p,
(iii) |vx| 1,
(iv) 모든 i 0에 대하여, uviwxiy L.
12.5 CFL에 대한 Pumping Lemma: 응용
Regular language의 경우와 같이 lemma의 논리적인 요소를 드러내기
위하여 lemma를 다음과 같이 다시 쓴다.
형식언어 및 오토마타 체계 II
Page 53
351
이제, 우리가 2.3절에서 배운 CSL L = {aibici | i 1 }가 CFL에 대한
pumping lemma를 만족하지 않는다는 것을 증명한다. 증명 방법은
언어 {aibi | i 1}이 regular 언어가 아님을 증명할 때와 비슷하다.
우선 L이 CFL라 가정하자. L이 가정대로 CFL인지를 lemma의
논리적 줄거리를 따라가며 따져 보기로 하자. (우리의 주장에 있는
번호는 lemma의 것과 같다.
(1) 크기가 무한한 모든 CFL
L에 대하여,
(2) 다음 조건 (3), (4)를
만족하는 상수 p가 있다.
(3) . . . . .
(4) . . . .
Pumping Lemma 의 주장
L은 크기가 무한한 CFL 이므로,
lemma의 조건 (3)과 (4)를 만족하는
상수 p가 존재한다. 이 상수가 어떤
값이든 그것을 p라 하자. (즉, p의
모든 경우의 값을 동시에 고려한다.)
우리의 주장
CFL에 대한 Pumping Lemma: 응용 형식언어 및 오토마타 체계 II
Page 54
352
CFL Pumping Lemma: 응용
(3) | z | p인 모든
string z L에 대하여,
(4) 다음 조건을 만족하는
string u, v, w, x, y가 있다.
(i) z = uvwxy,
(ii) |vwx| p,
(iii) |vx| 1,
(iv) 모든 정수 i 0에 대하여,
uviwxiy L.
L에 있는 string z = apbpcp를
선택하고, 조건 (4)의 (i) – (iii)을
만족하는 모든 u, v, w, x, y에
대 하 여 ( i v ) 가 만 족 하 는 지
따져보기로 한다.
(i) z = apbpbp = uvwxy라 두고,
v와 x에 있을 수 있는 기호들을
알아보기로 한다.
Pumping Lemma 의 주장 우리의 주장
aa . . . . . . . . .abb . . . . . . . . .bcc. . . . . . . . . cu vwx
pp p
y
형식언어 및 오토마타 체계 II
Page 55
353
CFL Pumping Lemma: 응용
(i) z = uvwxy,
(ii) |vwx| p,
(iii) |vx| 1,
(iv) 모든 정수 i 0에
대하여, uviwxiy L.
aa . . . . . . . . .abb . . . . . . . . .bcc. . . . . . . . . cu vwx
pp p
y
|vwx| p
위의 그림을 보면, 조건 |vwx| p에 의하여, v와 x는 함께 한 종류 또는
많아야 두 종류(a와 b, 또는 b와 c)의 symbol을 포함 할 수 있다. (String
v의 첫 문자와 x의 마지막 문자 사이의 거리가 p를 넘지 못한다는
조건에 유의하자.) 그리고 조건 |vx| 1에 의하여 v와 x는 함께 최소한
하나의 symbol을 포함하고 있다.
따라서 string uv2wx2y에는 같은 수의 a, b, c가 있을 수 없다 (즉,
uv2wx2y L). 이는 i = 2일 경우 조건 (iv)를 만족하지 못한다는 뜻이다.
L은 CFL의 pumping lemma를 만족하지 않으므로 CFL일 수 없다.
형식언어 및 오토마타 체계 II
Page 56
354
Rumination: CFL에 대한 Pumping Lemma 응용
형식언어 및 오토마타 체계 II
(1) CFL에 대한 pumping lemma를 응용할 때, regular language에 대한 pumping lemma와 다른 점에 유의할 필요가 있다.
Regular language의 pumping lemma는 pump 할 곳 (즉, z = uvw 내의 v)을 선택한 string z의 길이 n인 prefix 내로 한정한다.
반면, CFL의 pumping lemma는, pump 할 곳 (z = uvwxy 내의 v와 x)은, string u와 y의 길이에 제한이 없으므로, 조건 |vwx|
p에 의하여 넓이가 최대 p인 창(window)이 있을 수 있는 위치이면 어디든지 가능하다. String vwx 는 z의 prefix가 될 수도
있고 suffix가 될 수도 있다. 따라서 CFL에 대한 pumping lemma를 이용하여 어떤 language L이 CFL가 아님을 증명하는
과정에서 조건 (iv)를 만족할 수 없음을 보이기 위하여 vwx가 있을 수 있는 z 상의 모든 위치를 고려해야 한다.
(2) 앞서 배운 CFL에 대한 pumping lemma는 응용 예로 든 언어에 대하여 비교적 쉽게 적용할 수 있었다. 그러나 이
lemma의 약점은 CFL가 아님에도 lemma를 만족하는 언어가 많다는 것이다. 예를 들어 CFL가 아닌 아래 언어 L을 예로
들어 보자. L에 있는 string은 같은 binary string이 string ai로 분리되어 있거나, 순수 binary string이다. 이 언어에 속한
길이가 p보다 같거나 큰 어떤 string을 택하든지 모두 이 lemma를 만족한다.
L = {xaix | i > 0, x {0,1}+} {x | x {0,1}+}
예를 들어 string z = 1p0
paaa1
p0
p= uvwxy를 pump 하여 L에 속하지 않은 string을 만들 수 있는지 검토하여 보자. 만일
v = a, w = a, x = a라 두면, 모든 i 0에 대하여 uviwxiy L이다. 기호 a가 하나 있을 때, 즉 z = 1p0
pa1
p0
p일 때도 v = a, w =
x = 라 두면, 역시 모든 i 0 에 대하여 uviwxiy L임을 알 수 있다. 이런 점에서 우리가 배운 CFL에 대한 pumping
lemma는 CFL가 아닌 다양한 언어에 적용할 수 없는 약점을 갖고 있다. 이러한 결점 때문에, W. Ogden은 다음
절에서 소개하는 소위 Ogden‟s lemma라는 pumping lemma를 도입하였다.
Page 57
355
형식언어 및 오토마타 체계 II
12.6 Ogden’s Lemma
Ogden의 lemma는 pumping lemma와 매우 유사하다. 다른 점은 pumping
할 수 있는 string 내의 문자를 아래 lemma의 이탤릭 체 부분과 같이
mark 하여 제한할 수 있다는 것이다.
(1) 크기가 무한한 모든 CFL L에 대하여(2) 다음 조건을 만족하는 상수 p가 존재한다.
(3) |z| p 인 조건을 만족하는 모든 string z L에 대하여z 내의 최소 p 개의 위치에 있는 문자를 mark 했다면,
(4) 다음 조건을 만족하는 string u, v, w, x, y가 존재한다.
(i) z = uvwxy,
(ii) |vwx| p,
(iii) |vx| 1이며 vx 내에 최소 한 개의 mark된 문자가 있을 때,
(iv) 모든 i 0에 대하여, uviwxiy L.
(이 lemma의 증명은 본 과목의 정도를 벗어나므로 약하기로 한다. 흥미 있는 독자는 Hopcroft, Motwani, Ullman 저
“Introduction to Formal Languages, Automata Theory, Languages and Computation” (2001. Addison Wedley)를 참고하기
바란다. )
Page 58
356
형식언어 및 오토마타 체계 IIOgden’s Lemma
앞서 CFL에 대한 pumping lemma를 적용하는데 실패 했던 아래의
언어에 Ogden의 lemma를 적용하여 보자.
L = {xaix | i > 0, x {0,1}+} {x | x {0,1}+}
String z = 1p0
pa1
p0
p= uvwxy을 선택하고, 이 string의 prefix 1
p에 있는
symbol을 전부 mark 했다 하자. Ogden의 lemma에 의하여 |vwx| p이며
vx에 최소 하나의 mark 된 symbol이 있어야 하므로, x는 결코 a를 포함할
수 없다. 따라서 string z' = uv2wx2y는 언어 L의 조건을 만족할 수 없다.
왜냐하면, a의 앞부분의 binary string이 a 다음의 string과 같을 수 없기
때문이다. 따라서 uv2wx2y L. 언어 L은 Ogden의 lemma를 만족하지
않으므로 CFL가 아니다.
Page 59
357
형식언어 및 오토마타 체계 II
Rumination: Ogden’s Lemma 응용
(1) Programming 언어의 syntax 대부분이 context-free 언어의 특성이 있지만, context-dependent 한 부분도 있다. 예를
들면, 아래의 FORTRAN program 예와 같이 matching integer label (예에서 10)을 쓰도록 하는 것이다.
. . . .
DO 10 I = 1, 100, 1
SUM = SUM + I
10 PRO = PRO * I
. . . .
위의 예와 같은 context-dependence 언어 구조는 앞서 Ogden의 lemma의 응용 예로 들었던 다음 언어 L과 같은 구조를 갖고
있음을 알 수 있다.
L = {xaix | i > 0, x {0,1}+} {x | x {0,1}+}
String x는 matching label (예의 10)에 해당하고 ai 대신 임의의 string(프로그램)이 있을 수 있으며, matching label이 없을
수도 있기 때문이다.
Page 60
358
12.7 CFL에 대한 Pumping Lemma: 증명
형식언어 및 오토마타 체계 II
우선 간단한 예를 들어 증명의 바탕이 되는 개념을 설명하고, 형식적인
증명은 약하기로 한다. (예로 제시된 개념을 일반화하는 것은 어렵지
않다 . ) Chomsky normal form(CNF)으로 표현된 다음의 CFG을
고려하여 보자. (모든 CFG는 CNF로 전환할 수 있다는 것을 기억하자.)
이 CFG의 언어의 크기는 무한하다. 예를 들면, 다음 쪽의 parse tree에서
긴 가지에 해당하는 일련의 rule 중에 3개의 rule B FD, F HC, 그리고
C DB를 반복하여 적용할 수 있다. 즉, rule B가 F를 F가 C를, 그리고 C가
다시 B를 생성할 수 있기 때문에, 언어의 크기는 무한하다. 그림은 parse
tree의 가지를 따라 string z = d(hd)3hc(d)3dchdchd를 생성하고 있음을
보여준다.
G: S AB A DE B FD E FC
C DB | c F HC D d H h
Page 61
359
z = d ( h d )3 h c (d)3 d h c d h c d
u v w x y
S AB A DE
E FC
C DB | c
F HC
D d H h
B FD
CFL에 대한 Pumping Lemma: 증명 형식언어 및 오토마타 체계 II
F
CH
h c
d
F
C
B
H
Dh
d
D
d
F
C
B
H
Dh
d D
d
F
C
B
H
Dh
d D
D
B
F
CH
h c
d
S
E
A
D
d
D
d
C
B
F
C
D
dH
h c가장 긴 가지의 ‘마디’ F-C-B가
임의 번 반복할 수 있으며, 여기에
맺은 ‘열매’가 좌측에는 hb 우측엔
d가 반복횟수 만큼 달린다. 즉, for
all i ≥ 0, uviwxiy L(G).
CFG G:
Page 62
360
Parse tree의 가장 긴 줄기에 해당하는 path label에 반복하는 pattern F-
C-B가 있다. 이러한 반복 pattern은 발생하는 언어의 크기가 무한한
grammar의 공통적인 특성이다. 왜냐하면, nonterminal symbol의 수가
상수인데, grammar가 발생하는 string의 길이는 제한이 없기 때문이다.
예에서 반복하는 pattern F-C-B을 제거하여 그 수를 감소시킬 수도 있고,
삽입하여 증가시킬 수도 있다. 반복하는 pattern F-C-B의 왼편과 오른편에
각각 terminal string hd와 d가 발생한다. 따라서, 모든 i 0에 대하여 string
d(hd)ihc(d)idchdchd는 grammar의 언어 L(G)에 속한다.
CFL에 대한 Pumping Lemma: 증명 형식언어 및 오토마타 체계 II
Page 63
361
일반적으로 CNF로 표현된 CFG의 parse tree의 높이가 grammar의
nonterminal symbol의 수보다 크면, 가장 긴 줄기(path) 상에 최소한 한
개의 nonterminal symbol이 반복하여 나타난다. 이 symbol을 A라 하자.
Symbol A부터 다음 A까지 줄기의 왼편 가지에서 생긴 terminal string을
v, 오른편 가지에서 생긴 terminal string을 x, 줄기의 끝에서 생긴
string을 w, 이 외에 줄기의 좌 우편에 발생한 string을 각각 u, y 라 하자.
Grammar의 parse tree가 string z를 생성한다고 하면, z = uvwxy라 쓸
수 있고, 모든 string z' = uviwxiy (i 0)도 역시 주어진 grammar에 의하여
생성할 수 있음을 알 수 있다. VN을 grammar의 nonterminal symbol의
집합이라 하자. Grammar가 CNF로 표현되어 있으므로, 다음 식을
만족하는 상수 p가 있다.
|vwx| p = c|VN| (단, c는 상수.)
CFL에 대한 Pumping Lemma: 증명 형식언어 및 오토마타 체계 II
Page 64
362
(1) 모든 CFL L에 대하여
(2) 다음 조건을 만족하는 상수 p가 있다.
(3) |z| p인 조건을 만족하는 모든 string z L에 대하여
(4) 다음 조건을 만족하는 string u, v, w, x, y가 있다.
(i) z = uvwxy,
(ii) |vwx| p,
(iii) |vx| 1,
(iv) 모든 정수 i 0에 대하여, uviwxiy L.
이상의 분석을 정리하면 다음의 결론을 얻는다.
CFL에 대한 Pumping Lemma: 증명 형식언어 및 오토마타 체계 II
Page 65
363
12.1 Pumping lemma를 이용하여 언어 L = {xxR | x {a, b, c}* }가 regular 가 아님을 다음과 같은 논리로 증명하려 한다.
다음 각 질문에 답하여 증명을 완성하라.
증명. 언어 L이 regular라 하고 lemma의 상수를 n이라 하자. 다음 string 들은 모두 L에 속한다.
(a) abccba (b) a100b100b100a100 (c ) an/2bn/2b n/2an/2 (d) anbnbnan
질문 1: 이 중에 어느 string을 lemma의 string z로 선택하겠는가? 다른 string을 선택하지 않은 이유는? 만일 어느
string도 z로 선택할 수 없다면, L 내의 어느 string을 선택할 것인가?
질문 2: (i) z = uvw, (ii) |uv| n, (iii) |v| 1을 만족하는 string u, v, w {a, b, c}* 를 고려해 보자. String v의 내용은
어떤 것일 까? 가능한 모든 경우를 간략하게 기술하라.
질문 3: Pumping lemma에 의하면, “For all i 0, string uviw L.”라고 했다. 언어 L이 regular 가 아님을 보이려면,
lemma의 이 부분을 어떻게 이용해야 하며, 그 이유는?
12.2 다음 각 언어는 regular 언어인가? 이 질문에 대한 답을 증명하라. 증명의 논리는 명료해야 한다.
L1 = {aibjck | i, j, k > 0 } L2 = {aaaaibjci | i, j > 0 }
12.3 String x에 있는 기호 a, b, c의 수를 각각 #a(x), #b(x), 및 #c(x) 로 표기하기로 하자. 다음 각 언어가 CFL인지를
가리고 증명하라. 증명의 논리는 명료해야 한다.
L3 = { x | x {a,b,c}+, and #a(x) > #b(x) }
L4 = { x | x {a,b,c}+, and #a(x) = #b(x) = #c(x) }
L5 = {x | x {a,b,c}+, and #a(x) < #b(x) < #c(x) }
12.4 언어 { w#wR | w {a, b}* } 는 CFL임을 배웠다. 다음 각 언어는 CFL이 아님을 증명하라.
L6 = {w#w | w {a, b}* } L7 = {xyx | x, y {a, b}* }
연습문제형식언어 및 오토마타 체계 II
Page 66
364
13. Parsing
13.1 Derivation 367
Leftmost derivation, Rightmost-derivation
Derivation과 parse trees
13.2 LL(k) parsing 전략 371
13.3 LL(k) parser 만들기 384
만들기 예
LL(k) grammar 정의
되새김(rumination) 398
13.4 LR(k) parsing 전략 400
13.5 LR(k) parser 만들기 407
만들기 예
LR(k) grammar 정의
되새김(rumination) 426
연습문제 429
Page 68
366
13. Parsing
G1: S aSb | ab
G2: S aA A Sb | b
Parsing
start
(a, Z0/aZ0 )
( a, a/aa )(b, a/ )
(b, a/ )
(, Z0/Z0 )
Parsing은 compiler의 핵심적인 기능 중의 하나로 프로그램, 즉 source code가 해당 프로그래밍 언어의 문법에 맞는지
검토하고, 오류가 없으면, object code를 생성하는 데 필요한 parse tree를 만드는 작업이다. 우리가 배우는 형식언어의
측면에서 볼 때, parsing은 임의의 string w가 주어진 CFG G의 언어에 속한 것인지를 밝히고, 그렇다면, w를 derive 하는
일련의 production rule을 보이는 것이다. 따라서 parsing은 주어진 CFG에 바탕을 두어야 하며, 언어에 바탕을 둔 PDA를
가지고 할 수 있는 일이 아니다. 예를 들어, 아래의 두 CFG G1과 G2는 같은 언어 {aibi | i > 0 }를 발생하며, 이 언어는 그림에
있는 DPDA에 의하여 인식할 수 있다. 그러나 이 DPDA는 주어진 input string이 어느 grammar에 의하여 어떻게
발생하는지에 관한 정보를 제공하지 못한다. 따라서 우리가 지금까지 배운 PDA는 parsing 목적으로 쓸 수 없다.
임의의 CFG G가 주어졌을 때, string x가 x L(G)인지를 dynamic programming 기법을 이용하여 가리는 흥미 있는
algorithm이 있으나, input의 길이가 n일 때, O(n3)의 사간 복잡도를 갖고 있어 compiler에 쓰기에는 실용적인 방법이 되지
못한다. (CYK algorithm이 그 대표적인 예로 부록 F 에 소개하고 있다.) 이 때문에 compiler는 실시간에 가까운 속도로
parsing 할 수 있는 grammar에 한하여, 이들에 대한 parsing 기법을 개발하여 이용하고 있다. 이 장에서는 이러란 목적으로
개발된 두 가지 parsing 모델을 설계하는 방법을 공부한다.
Page 69
367
13.1 Derivation
Grammar가 string을 생성하는 과정을 나타내는 것이 parsing의 주된
목적이라면, parsing 결과를 parse tree로 출력하는 것이 바람직하다.
그러나, 2 차원 parse tree를 구성하여 제시하는 복잡성 때문에, parse
tree 대신 다음 두 derivation 방법을 이용한다.
Leftmost derivation: grammar의 rule을 적용하여 string을 derive 할
때, 항상 sentential form의 가장 왼쪽에 있는 (leftmost) nonterminal
symbol의 rule을 적용한다.
Rightmost derivation: grammar의 rule을 적용하여 string을 derive 할
때 , 항상 sentential form의 가장 오른쪽에 있는 (rightmost)
nonterminal symbol의 rule을 적용한다.
예: S ABC A aa B a C cC | c
Leftmost derivation: S ABC aaBC aaaC aaacC aaacc
Rightmost derivation: S ABC ABcC ABcc Aacc aaacc
Parsing
Page 70
368
이와 같은 derivation은 1차원으로 표현할 수 있기 때문에 편리하다.
그러나 compiler는 parsing 결과를 이용하여 object code를 생성할 때,
parse tree를 이용하므로, 1차원 derivation data 구조를 2차원 parse tree
data 구조로 쉽게 해석할 수 있어야 한다. 아래와 같은 leftmost
derivation을 예로 들어보자. (편의상 rule에 번호를 달아 이용하기로
한다.)
Derivation Parsing
S ABC A aa B bD
C cC | c D bd
(4) (6)(5)
(1) (2) (3)Leftmost derivation:
S ABC aaBC aabDC(1) (2) (3)
aabbdC aabbdcC aabbdcc(6) (4) (5)
Page 71
369
Leftmost derivation에 적용된 일련의 rule들은 parse tree 상에서 볼
때, 위에서 아래로, 좌측에서 우측 순으로 진행하며 (top-down left-
to-right traversal) 적용된 rule들과 일치한다. (여기서 top-down은
depth-first와 같은 의미로 쓴다.)
1 2 3 6 4 5
Cc
c
aa
S
A B C
b D
bd
(1)
(2) (3)
(6)
(4)
(5)
Derivation Parsing
S ABC A aa B bD
C cC | c D bd
(4) (6)(5)
(1) (2) (3)S ABC aaBC aabDC
(1) (2) (3)
aabbdC aabbdcC aabbdcc(6) (4) (5)
Leftmost derivation:
Page 72
370
정규 Derivation Parsing
아래 그림을 보면, 같은 string을 rightmost derivation 할 때 적용된
rule들의 역순은 parse tree를 밑(leaf)에서 위로, 좌측에서 우측으로
(bottom-up left-to-right traversal) 따라가며 적용된 rule들과
일치한다.
Rightmost derivation:
S ABC ABcC ABcc
AbDcc Abbdcc aabbdcc
(1) (4) (5)
(3) (6) (2)
2 6 3 5 4 1
S
Cc
c
aa
A B C
b D
bd
(1)
(4)
(5)
(3)
(6)
(2)
S ABC A aa B bD
C cC | c D bd
(4) (6)(5)
(1) (2) (3)
Page 73
371
13.2 LL(k) Parsing 전략
우리가 배운 PDA는 언어에 기반을 두어 동작하므로 parsing의
요구조건을 충족할 수 없다. Parser는 주어진 CFG G를 바탕으로
만들어야 한다. 아래 그림과 같이, PDA를 고쳐, grammar G를 finite
state control에 저장하여 두고, 이를 참조하여 input tape에 둔 string을
읽으며 derive 하는 순서를 output port를 통하여 알려주는 구조를
생각하여 보자.
Parsing
(1) (2) (3)
G: S AB | AC A aaaaaaaaaa
(4) (5) (6) (7)
B bB | b C cC | c
(a)
a a a a a a a a a a b b b
Z0
output port q0 G
(b)
Page 74
372
LL(k) Parsing Parsing
이러한 구조를 가지고 input string과 같은 string을 stack에 만드는
전략을 시도해 보자. Derivation은 시작기호 S의 rule로 시작해야 한다.
따라서, 그림과 같이 우선 S를 stack에 push하고 state q1으로 간 후,
이 state에서 다음에 적용할 S의 rule을 선택하여 적용하는 방법을
검토하여 보자. (Stack 상단에 nonterminal symbol이 있을 때마다 그
symbol의 rule을 선택하여 적용하는 방안을 적용하려 한다.)
(1) (2) (3)
G: S AB | AC A aaaaaaaaaa
(4) (5) (6) (7)
B bB | b C cC | c
(a)
a a a a a a a a a a b b b
SZ0
output port q1 G
(b)
S ?
Page 75
373
아래 그림 (b)와 같은 시점에서 parser는 S의 rule (1)과 (2) 중에 어는
rule을 택해야 할까? 그림 (a)에 있는 L(G)의 구조를 살펴보면, input
string의 좌측 끝에서 11번째 symbol이 b이면, rule (1)을, c이면 rule
(2)를 적용하여 발생한 것임을 알 수 있다. 그러나, 우리가 배운 PDA는
input string을 미리 내다보아 그 내용에 따라 transition을 달리할 수
없는 model이다.
LL(k) Parsing 전략 Parsing
a a a a a a a a a a b b b
SZ0
output port q1 G
(b)
S ?
(1) (2) (3)
G: S AB | AC A aaaaaaaaaa
(4) (5) (6) (7)
B bB | b C cC | c
(a)
L(G) = {a10x | x = bi or x = ci, i > 0 }
Page 76
374
이 문제를 해결하려고, parser의 input head에 앞으로 읽을 string을
상수 길이만큼 내다볼 수 있는 „망원경‟, 즉 look-ahead 기능을 갖도록
한다. 다시 말하면, 우리가 설계하려는 parser는 DPDA의 input head에
k개의 cell을 앞으로 내다볼 수 있는 기능을 추가한 것이라 할 수 있다.
Look-ahead 하는 거리 k는 input head가 위치한 cell까지 포함한다.
LL(k) Parsing 전략Parsing
(1) (2) (3)
G: S AB | AC A aaaaaaaaaa
(4) (5) (6) (7)
B bB | b C cC | c
(a)
L(G) = {a10x | x = bi or x = ci, i > 0 }
S AB !
a a a a a a a a a a b b b
SZ0
q1 G
(b)
Page 77
375
그림의 예에서 길이 11만큼 내다본 내용이 aaaaaaaaaab이므로 input
string은 rule (1), 즉 S AB를 적용하여 derive 한 것이다. 따라서
parser는 아래 그림 (a)와 같이 stack 상단의 S 대신 선택한 rule의 우측에
있는 string AB를 push하고 동시에 적용한 rule 번호 (1)을 output port로
보낸다.
LL(k) Parsing 전략 Parsing
(1) (2) (3)
G: S AB | AC A aaaaaaaaaa
(4) (5) (6) (7)
B bB | b C cC | c
(a)
L(G) = {a10x | x = bi or x = ci, i > 0 }
a a a a a a a a a a b b b
ABZ0
q1 G(1)
(b)
Page 78
376
LL(k) Parsing 전략 Parsing
아래 그림 (b)와 같이, parser의 현재 state를 q, input tape 상에
앞으로 처리해야 할 input string 부분을 , stack의 내용을 라 할 때,
(q, , )는 parser가 일을 하는 데 필요한 정보이다. 이 세 쌍의 정보를
parser의 configuration(구성) 이라 부른다. 앞으로는 편의상 그림
대신 configuration을 쓰기로 한다.
q1
a a a a a a a a a a b b b
A B Z0
G(1)
(a) Rule 적용
q
G
(b) Configuration (q, , )
Page 79
377
초기 configuration (q0, aaaaaaaaaabbb, Z0)은 시작기호 S를 stack에
push하여 (q1, aaaaaaaaaabbb, SZ0)로 바뀌고, 11자리를 내다본 내용에
의하여 rule (1)을 적용한 결과, configuration은 다음과 같이 바뀐다.
(1) (2) (3) (4) (5) (6) (7)
G: S AB | AC A aaaaaaaaaa B bB | b C cC | c
LL(k) Parsing 전략 Parsing
(q0, aaaaaaaaaabbb, Z0) (q1, aaaaaaaaaabbb, SZ0)
(q1, aaaaaaaaaabbb, ABZ0)
(1)
look-ahead 11 cells
Page 80
378
LL(k) Parsing 전략 Parsing
이제, stack 상단의 A에 대한 rule을 선택해야 하는데, A의 rule은 (3)번
하나밖에 없으므로 앞을 내다볼 필요 없이, 이 rule을 적용하여 A 대신
(3)번 rule의 우측 string을 그림과 같이 stack에 push 한다. Stack 상단에
terminal symbol이 나타나면, 같은 symbol이 input string에 나타나야
하므로, input를 읽어 서로 일치하면 stack 상단의 terminal symbol을 pop
한다. 이 과정을 stack 상단에 nonterminal symbol이 나타나거나,
stack의 바닥기호가 보일 때까지 반복한다.
(1) (2) (3) (4) (5) (6) (7)
G: S AB | AC A aaaaaaaaaa B bB | b C cC | c
(q1, aaaaaaaaaabbb, ABZ0) (q1, aaaaaaaaaabbb, aaaaaaaaaaBZ0)
. . . .(q1, abbb, aBZ0) (q1, bbb, BZ0)
Page 81
379
이제, stack 상단의 B의 rule (4)와 (5) 중 하나를 선택해야 할 차례다.
Input tape에 b가 하나만 있다면, 이 b는 rule (5)가 생성한 것이다. 그러나,
b가 둘 이상이면, 다음에 읽을 b는 rule (4)가 생성한 것이고, 끝에 있는
b가 (5)번 rule이 생성한 것이다. 따라서 parser의 input head는 최소 두
cell을 내다볼 수 있어야 한다. 예에서, 나머지 부분 bbb에 대한
parsing은 다음과 같이 진행한다. (밑 금 친 부분은 look-ahead 영역이다.)
(q1, bbb, BZ0) (q1, bbb, bBZ0) (q1, bb, BZ0) (q1, bb, bBZ0) (4) (4)
(q1, b, BZ0) (q1, b, bZ0) (q1, , Z0) (5)
LL(k) Parsing 전략 Parsing
(1) (2) (3) (4) (5) (6) (7)
G: S AB | AC A aaaaaaaaaa B bB | b C cC | c
. . . .(q1, abbb, aBZ0) (q1, bbb, BZ0) ?
Page 82
380
S AB aaaaaaaaaaB aaaaaaaaaabB aaaaaaaaaabbB aaaaaaaaaabbb(1) (3) (4) (4) (5)
(4)
(4) (5)
(q0, aaaaaaaaaabbb, Z0) (q1, aaaaaaaaaabbb, SZ0)
(q1, aaaaaaaaaabbb, ABZ0) (q1, aaaaaaaaaabbb, aaaaaaaaaaBZ0)
. . . .(q1, abbb, aBZ0) (q1, bbb, BZ0) (q1, bbb, bBZ0)
(q1, bb, BZ0) (q1, bb, bBZ0) (q1, b, BZ0) (q1, b, bZ0) (q1, , Z0)
(1)
(3)
위의 마지막 configuration은, input string을 모두 읽고 (남은 부분이 ),
stack 바닥(Z0)이 드러나, parsing이 성공적으로 끝났음을 보여준다. 이
configuration (q1, , Z0)을 accepting configuration이라 한다. Parsing 중에
적용한 일련의 rule은 input string을 다음과 같이 leftmost derivation 하며
적용한 rule과 일치한다.
LL(k) Parsing 전략 Parsing
Parsing 한 전 과정을 정리하면 다음과 같다.
Page 83
381
S AC aaaaaaaaaaC aaaaaaaaaacC aaaaaaaaaacc(2) (3) (6) (7)
(6)
(7)
(q0, aaaaaaaaaacc, Z0) (q1, aaaaaaaaaacc, SZ0)
(q1, aaaaaaaaaacc, ACZ0) (q1, aaaaaaaaaabbb, aaaaaaaaaaCZ0)
. . . .(q1, acc, aCZ0) (q1, cc, CZ0) (q1, cc, cCZ0)
(q1, c, CZ0) (q1, c, cZ0) (q1, , Z0)
(2)
(3)
LL(k) Parsing 전략 Parsing
같은 전략으로 input string aaaaaaaaaacc을 parsing 하면, 다음과 같은
일련의 configuration을 거치며, parser가 적용한 일련의 rule은 아래와
같이 leftmost derivation 할 때 적용한 것과 일치한다.
(1) (2) (3) (4) (5) (6) (7)
G: S AB | AC A aaaaaaaaaa B bB | b C cC | c
Page 84
382
이 parser는 input string을 좌에서 우로 (Left-to-right) 읽으며, 최대 11
cell을 look-ahead 하는 기능을 가지고, Leftmost derivation에 적용된
rule을 따라 적용하므로 LL(11) parser라 부른다. 이 전략을 이용하여
최대 k cell을 미리 내다보는 parser를 LL(k) parser, 이런 기능으로
parsing 할 수 있는 grammar를 LL(k) grammar라 한다. 형식적으로
LL(k) parser는 parse table로 정의하는데, 앞서 예시한 parser의 parse
table은 다음과 같다.
LL(k) Parsing 전략 Parsing
a10b a10c bbX9 bB10 ccX9 cB10
S
A
B
C
AB AC
a10
bB b
cC c
11 look-ahead (X는 don‟t care 문자)
Stack
top
Parse Table
Page 85
383
LL(k) Parsing 전략 Parsing
표에서 행에는 stack 상단에 있을 수 있는 nonterminal symbol,
열에는 11 look-ahead 내용을 둔다. 표에서 X는 “don‟t care” symbol
(임의의 기호), B는 blank, 은 look-ahead 하지 않음을 뜻한다. 표의
내용 (entry)은 rule을 적용할 때, stack 상단의 nonterminal symbol 대신
push 할 string, 즉 적용하는 rule의 우측 부분이다. 표의 공백 부분은
parsing이 실패하여 reject 한다는 뜻이다.
a10b a10c bbX9 bB10 ccX9 cB10
S
A
B
C
AB AC
a10
bB b
cC c
11 look-ahead (X는 don‟t care 문자)
Stack
top
Parse Table
Page 86
384
13.3 LL(k) Parser 만들기
예 1. 다음 CFG의 언어를 최소의 look-ahead 값 k를 가지고 parsing 할
수 있는 LL(k) parser를 만들라.
S aSb aabbb(1) (2)
S aSb aaSbb aaaSbbb aaaaabbbbbb(1) (1) (1) (2)
이 grammar의 언어는 {aiaabbbbi | i 0 }이다. 이 언어의 string
aaaabbbbb를 LL(k) parsing 전략에 의하여 parsing할 경우를 분석하여
k의 최소값을 알아보자. 이 string의 leftmost derivation은 아래와 같다.
따라서, LL(k) parser는 rule을 (1), (1), (1), (2)의 순으로 적용한다.
Parsing
Page 87
385
LL(k) Parser 만들기 Parsing
이 grammar 언어의 특징을 분석하여 보면, string의 중앙에 있는
aabbb는 (2)번 rule에 의하여 발생하고, 나머지 부분은 (1)번 rule에
의하여 발생한다는 것을 알 수 있다. 따라서 LL(k) parser는 look-
ahead에 aabbb가 보이기 전까지 rule (1)을 적용하고, aabbb가 나오면
rule (2)를 적용하면 되겠다.
이렇게 하려면 얼마나 멀리 내다봐야 할까? Parser가 처한
configuration을 분석하며 k 값을 알아보자. Parser는 우선 S를 push
하고 S의 rule을 선택할 configuration에 이른다.
S aSb aabbb(1) (2)
S aSb aaSbb aaaSbbb aaaaabbbbbb(1) (1) (1) (2)
(q0, aaaaabbbbbb, Z0) (q1, aaaaabbbbbb, SZ0) ?
Page 88
386
이 시점에서 parser는 얼마나 멀리 look-ahead 해야 할까? 만일 input
string이 aabbb일 경우면, rule (2)를 적용해야 한다. 그렇다면, look-
ahead 길이 k를 5로 택할 수도 있으나, aab를 내다볼 수만 있다면
충분하기 때문에 주어진 string을 parse하기 위하여 k = 3으로
가능하다. 세 자리를 내다본 내용이 aaa이므로 input head 밑에 있는
a는 rule (1)이 발생한 것이다. 따라서 parser는 다음과 같이 (1)번
rule을 적용한다 . 그리고 stack 상단에 terminal symbol a가
있으므로 input를 읽고 비교하여 일치하므로 pop 하여 버린다.
(q1, aaaaabbbbbb, SZ0) (q1, aaaaabbbbbb, aSbZ0)
(q1, aaaabbbbbbb, SbZ0) ?
(1)
LL(k) Parser 만들기 Parsing
S aSb aabbb
(1) (2)(q0, aaaaabbbbbb, Z0) (q1, aaaaabbbbbb, SZ0) ?
Page 89
387
Parser는 아래와 같이 다시 S가 stack의 상단에 있으므로, input
string을 3자리 내다본 내용이 aaa이므로 다시 rule (1)을 적용하고, 이
과정을 look-ahead 한 내용이 aab일 때까지 반복한다.
(1)
(1)
(q1, aaaaabbbbbb, SZ0) (q1, aaaaabbbbbb, aSbZ0)
(q1, aaaabbbbbbb, SbZ0) (q1 , aaaabbbbbb, aSbbZ0 )
(q1, aaabbbbbbb, SbbZ0) (q1 , aaabbbbbb, aSbbbZ0 )
(q1 , aabbbbbb, SbbbZ0 ) ?
(1)
Parsing LL(k) Parser 만들기
S aSb aabbb
(1) (2)
… (q1, aaaabbbbbbb, SbZ0) ?
Page 90
388
Parsing LL(k) Parser 만들기
위의 마지막 configuration에서 3 look-ahead 한 내용이 aab이므로
다음과 같이 (2) 번 rule을 적용해야 한다. 이제 stack 상단에 나타나는
terminal symbol들을 차례로 input symbol과 비교하여 일치하면 pop 하는
일을 반복하면, 다음과 같이 input string은 모두 처리되고 stack의
바닥이 드러난 accepting configuration 상태 (q1 , , Z0)에 이른다.
(q1 , aabbbbbb, SbbbZ0 ) (q1 , aabbbbbb, aabbbbbbZ0 )
… (q1 , , Z0)
(2)
S aSb aabbb
(1) (2)
…. (q1 , aabbbbbb, SbbbZ0 ) ?
Page 91
389
지금까지 parser가 적용한 rule은 (1), (1), (1), (2) 순이고, parsing 중
look-ahead 최대 길이는 3이었다. 적용한 rule의 순서는 아래의
leftmost derivation에 적용한 rule의 순서와 일치한다.
S aSb aabbb(1) (2)
S aSb aaSbb aaaSbbb aaaaabbbbbb(1) (1) (1) (2)
위의 분석은 input string aaabbbbbb에 관한 것이지만, grammar가
생성하는 모든 string을 3 look-ahead 기능을 가지고 성공적으로 parse
할 수 있음을 알 수 있다. 이 grammar는 LL(3) grammar이며, parse
table은 다음과 같다.
Parsing
S
aaa aab
aSb aabbb
3 look-ahead
Stack top
Parse Table
LL(k) Parser 만들기
Page 92
390
예 2. 다음 grammar를 위한 최소의 k 값을 가진 LL(k) parser를 설계하라.
(1) (2) (3) (4)
S abA | A Saa | b
(1) (3) (1) (3) (2)S abA abSaa ababAaa ababSaaaa ababaaaa
예 1과 같이, grammar가 발생하는 대표적인 string ababaaaa를
LL(k) 전략에 의하여 parsing하는 절차를 분석하여 k의 값을 구하고,
parse table을 만들기로 한다. 선택한 string은 다음과 같이 leftmost
derivation에 의하여 생성되므로, parser는 선택한 string을 parsing
할 때, 이 순서에 따라 rule을 적용하면 된다.
Parsing LL(k) Parser 만들기
Page 93
391
Parsing LL(k) Parser 만들기
(q0, ababaaaa, Z0) (q1, ababaaaa, SZ0) ?
Parser는 다음과 같이 일상적인 절차에 의하여 S를 stack에 push 한
후 적용할 rule을 선택할 정보를 찾는다. Leftmost derivation에
의하면, rule (1)을 처음 적용해야 하는데, 어떤 근거로 이 rule을
적용할 수 있을까?
S abA |
A Saa | b(3) (4)
(1) (2)
이때 두 자리를 내다본 결과가 ab이므로 input string은 rule (1)을
적용하여 발생한 것이다. (Rule (2)를 적용했다면 내다본 결과가
공백()이거나 aa라야 한다.) 따라서 parser는 stack의 상단에 있는 S에
rule (1)을 적용한 다음 ab를 읽어 처리하고, stack 상단의 A에 대하여
rule (3)과 (4) 중의 하나를 선택하여 적용해야 한다.
Page 94
392
. . . . (q1, abaaaa, AZ0) (q1, abaaaa, SaaZ0) ?(3)
이 시점에서 rule (4)를 적용한다면, input의 다음 symbol은 a가
아니라 b가 되어야 한다. 다음 symbol이 a이므로 rule (3)을 적용하여야
한다. 따라서 위의 마지막 configuration은 rule (3)을 적용한 후 다음과
같이 바뀐다. 이때 look-ahead 길이는 1이면 충분하다.
(q1, ababaaaa, SZ0) (q1, ababaaaa, abAZ0)
. . . . (q1, abaaaa, AZ0) ?
(1)
Parsing LL(k) Parser 만들기
S abA |
A Saa | b(3) (4)
(1) (2)
Page 95
393
다시 stack 상단의 S의 rule을 선택하려고 길이 2 만큼 input string을
내다보니, ab가 보이므로 rule(1)을 적용한다. 이 과정을 반복하다가,
아래와 같이 stack 상단에 S가 있을 때, look-ahead 한 내용이 aa이므로,
마지막으로 rule (2)를 적용한다. Stack에 있는 terminal symbol들은 남은
input string과 비교하며 비워 accepting configuration에 이른다.
Parsing LL(k) Parser 만들기
S abA |
A Saa | b(3) (4)
(1) (2)
. . . . (q1, abaaaa, AZ0) (q1, abaaaa, SaaZ0) ?(3)
(3)
(3) (1)
(q1, abaaaa, AZ0) (q1 , abaaaa, SaaZ0 )
(q1 , abaaaa, abAaaZ0 ) . . .(q1, aaaa, AaaZ0)
(q1, aaaa, SaaaaZ0) (q1, aaaa, aaaaZ0) . . . . (q1, , Z0)(2)
Page 96
394
Parsing LL(k) Parser 만들기
S abA |
A Saa | b(3) (4)
(1) (2)
(3)(q1 , abaaaa, abAaaZ0 ) . . .(q1, aaaa, AaaZ0)
(q1, aaaa, SaaaaZ0) (q1, aaaa, aaaaZ0) . . . . (q1, , Z0)(2)
(3) (1)
(q1, ababaaaa, SZ0) (q1, ababaaaa, abAZ0)
. . . . (q1, abaaaa, AZ0) (q1 , abaaaa, SaaZ0 )
(1)
지금까지 진행한 parsing history를 정리하면 다음과 같다.
Input string이 ababbaa와 같이 rule (4)에서 끝나는 것이라면, parsing
history는 다음과 같을 것이다.
(4)
(3)
(1)
(q1, ababbaa, SZ0) (q1, ababaaaa, abAZ0) . . . . (q1, abbaa, AZ0)
(q1 , abbaa, SaaZ0 ) (q1 , abbaa, abAaaZ0 ) . . .(q1, baa, AaaZ0)
(q1, baa, baaZ0) . . . . (q1, , Z0)
(1)
Page 97
395
Parsing LL(k) Parser 만들기
이상의 parsing 결과를 종합하여 다음과 같은 LL(2) parse table을
만들 수 있다.
2 look-ahead
S
A
Stack
topabA
Saa b
B: blank
X: don‟t care
ab aa bX BB
Saa
Parse Table
S abA |
A Saa | b(3) (4)
(1) (2)
(3)(q1 , abaaaa, abAaaZ0 ) . . .(q1, aaaa, AaaZ0)
(q1, aaaa, SaaaaZ0) (q1, aaaa, aaaaZ0) . . . . (q1, , Z0)(2)
(3) (1)
(q1, ababaaaa, SZ0) (q1, ababaaaa, abAZ0)
. . . . (q1, abaaaa, AZ0) (q1 , abaaaa, SaaZ0 )
(1)
Page 98
396
정의 (LL(k) grammar). G = (VT, VN, P, S)를 임의의 CFG 라 하자. 다음
조건을 만족하면 G는 LL(k) grammar이다: 아래 (1), (2) 처럼, 같은
prefix 를 발생하는 임의의 두 leftmost derivation이 있다고 하자. 단, ,
, (VT VN)*, , x, y VT*, A VN.
(1) S * A * y
(2) S * A * x
만일 (k)x = (k)y이면, = 이어야 한다. 즉, 두 derivation은 같은 A의
rule을 적용한 것이다.
LL(k) grammar가 되려면, CFG가 갖추어야 할 조건은 무엇일까? 이
조건을 제시하기 전에, 간단한 표기법을 도입하기로 한다. 임의의
string 의 길이 k인 prefix를 (k) 로 표기하기로 하자. 만일 < k
이면, (k) = 이다. 예를 들면, (2)ababaa = ab, (3)ab = ab.
Parsing LL(k) grammar (정의)
Page 99
397
위의 조건은 parsing 중에 k cell만큼 내다본 (k)x의 내용에 의하여
stack 상단에 있는 nonterminal symbol A의 rule을 정확히 선택할 수
있다는 뜻이다. 이러한 특성을 갖는 CFG가 있다면 이 grammar의
언어를 LL(k) parsing 전략에 따라 parsing 할 수 있다. 즉, 이 grammar는
LL(k) grammar이다.
Parsing LL(k) grammar 정의
Enjoy Sharing
A young man saw an elderly couple sitting down to lunch at McDonald's. He noticed that they had ordered one meal,
and an extra drink cup. As he watched, the gentleman artfully divided the hamburger in half, then counted out the fries,
one for him, one for her, until each had half of them. Then he poured half of the soft drink into the extra cup and set that
in front of his wife. The old man then began to eat, and his wife sat watching, with her hands folded in her lap.
The young man decided to ask if they would allow him to purchase another meal for them so that they didn't have to
split theirs. The old gentleman said," Oh no. We've been married 50 years, and everything has always been and will
always be shared, 50/50." The young man then asked the wife if she was going to eat, and she replied, "It's his turn with
the teeth.“
- Fred & Wanda -
쉬어 가기
Page 100
398
Rumination: LL(k) Parsing
(1) LL(k) parser를 설계하기 위한 기본적인 접근 방법은, 주어진 input string과 같은 string을 stack 상에서 leftmost
derivation 과정을 따라 생성할 수 있는지, 다음과 같이 시도하는 것이다. Stack 상단에 nonterminal symbol이 나타나면,
이 symbol이 발생하는 string (rule의 우측)을 선택하여 push 한다. 이때 선택할 rule이 여러 개면, 상수 k cell만큼 input
string을 look-ahead (내다보기) 하여, rule을 선택하는 데 필요한 정보를 얻는다. Terminal symbol이 stack 상단에
나타나면, input를 읽어 비교하여 일치하면 pop 하여 버린다. 이 과정에서 적용한 rule의 순서는 leftmost derivation 할 때
적용한 rule의 순서와 일치한다. 이러한 strategy에 의하여 parsing 할 수 있는 CFG는 제한되어 있다. 다음의 CFG G1은
LL(k) grammar가 아니다.
Parsing
Grammar G1이 발생하는 언어는 { anx | n 0, x {0, 1} }이다. 즉, 임의의 수의 a 다음에 rule (1)을 적용하느냐, (2)를
적용하느냐에 따라 0 또는 1로 끝난다. 다음 그림이 예시하는 바와 같이 S가 stack 상단에 있는 상태에서 rule (1) 또는
(2)를 선택해야 하는데 이 선택에 필수적인 정보 0 또는 1이 무한히 멀리 떨어져 있을 수 있기 때문에 LL(k) parser를
만들 수 없다. (k가 constant임을 기억하자.) 같은 언어를 발생하는 G2는 LL(1) grammar이다. (LL(1) parser를 만들어보자.)
G1: S A | B A aA | 0 B aB | 1G2: S aS | D D 0 | 1
SZ0 S ?
aaaa . . . . . . . . . . aaaaaaaa 0
q1 G
Page 101
399
Rumination: LL(k) ParsingParsing
(2) Parser의 중요한 기능은 look-ahead에 있다. 이 기능은 전통적인 PDA model에 없는 기능이다. 그렇다면,
parser를 compiler로 구현할 때 look-ahead 기능이 실현 가능할까? 실제로 LL(k)의 k의 값이 너무 크지 않으면,
문제될 것이 없다. 왜냐하면, memory를 access 할 때, 일반적으로 byte(문자) 단위가 아니라, 여러 개의 분자가
있는 word 단위로 읽기 때문이다.
Page 102
400
13.4 LR(k) Parsing Strategy
LL(k) parser는 programming 언어를 parsing 하는 compiler의 도구로
쓰기에는 기능이 약하다. Parser의 stack 기능을 충분히 활용하여
parsing 능력을 한 단계 높인 것이 LR(k) parser이다. LR(k) parsing
기법은많은 compiler가이용하는핵심기술이다.
LR(k) parser는 LL(k) parser와 같이 look-ahead 기능에 더하여, stack의
윗부분을 들여다보고, 그 내용을 pop 할 수 있는 기능이 있다. LR(k)
parsing 전략은 LL(k) 전략의 역방향이라 할 수 있다. LL(k) parser는
stack 상단에 nonterminal 기호 A가 있으면, rule A 를 찾아 A를 로
대치한다. 반면, LR(k) parser는, 다음 예와 같이, stack 상부를 안에서
밖으로 읽은 내용이 이면, 이를 A로 대치한다.
Parsing
(q, abaaa…, CB…. Z0 ) (q, abaaa…, A…. Z0 ) A BC
Page 103
401
Stack 상부에 이렇게 대치할 내용이 없으면, 다음 input 기호를 읽어
stack에 push 한다. Stack 상부에 있는 string을 발생할 수 있는 rule이
여러 개 있으면, LL(k)와 같이, input tape를 상수 k cell만큼 look-ahead
하여 적용할 rule을 결정한다.
LR(k) Parsing Parsing
Communication Deadlock
“Who is calling?” was the answer to the telephone.
“Watt.”
“What is your name, please?”
“Watt‟s my name.”
“That‟s what I asked you. What‟s your name?”
“That‟s what I told you. Watt‟s my name.”
A long pause, and then from Watt, “Is this James Brown?”
“No, this is Knott.”
“Please, tell me your name.”
“Will Knott.”
Whereupon they both hung up. - Raman -
쉬어 가기
Page 104
402
LR(k) Parsing Parsing
다음의 CFG의 언어를 parsing 하는 LR(k) parser를 설계하여 보자.
Input string aabc가 주어졌다 하자. LR(k) parser는 다음과 같이 rule에
의하여 생성할 수 있는 string, 즉 rule의 우측 (aab, c 또는 d)이 stack의
상부에 나타날 때까지 input를 읽어들인다. (String aab를 읽어 stack에
push 하면, configuration에는 baa와 같이 역순으로 나타난다는 것을
기억하자.) Stack 상부에 있는 aab를 생성할 수 있는 rule이 (3)과 (4) 이다.
다음 input symbol이 c이면 rule (3)을, d이면 rule (4)를 적용한 것이므로,
한 자리를 look-ahead 하면 충분하다.
(q0, aabc, Z0 ) . . . ( q1, c, baaZ0) (q1, c, AZ0) ?(3)
S AC | BD A aab B aab C c D d(1) (2) (3) (4) (5) (6)
Page 105
403
(q0, aabc, Z0 ) . . . ( q1, c, baaZ0) (q1, c, AZ0)
(q1, , cAZ0) (q1, , CAZ0) (q1, , SZ0)
(3)
(5) (1)
위의 configuration에서 stack 상부에 있는 A를 발생할 수 있는 rule이
없으므로, 다음 input c를 읽어들인다. 읽어 넣은 c가 rule (5)에 의하여
발생할 수 있으므로, rule C c을 적용하여 c를 C로 대치한다. 이 결과
stack 상부에 AC가 있게 되고 (stack의 안에서 밖으로 읽는다는 것을
기억하자), 이 AC는 rule (1)이 생성한 것이다. Rule (1) S AC를
적용하면, parser는 accepting configuration (q1, , SZ0 )에 이른다.
S AC | BD A aab B aab C c D d(1) (2) (3) (4) (5) (6)
LR(k) Parsing Parsing
Page 106
404
LR(k) Parsing Parsing
S AC | BD A aab B aab C c D d(1) (2) (3) (4) (5) (6)
Accepting configuration (q1, , SZ0)는 기호 S로 시작하여 rightmost
derivation 절차를 따라 input string을 derive 할 수 있다는 뜻이다. 다음은
input string aabd에 대한 LR(1) parser의 parsing history를 보여준다.
LR(k) parsing에 적용한 rule의 순서는 rightmost derivation의 역순과 같다.
예의 두 string aabc와 aabd의 rightmost derivation은 다음과 같으며,
여기에 적용된 rule의 역순은 예의 parsing에 적용된 rule의 순서와 같다.
S BD Bd aabd(2) (6) (4)
S AC Ac aabc(1) (5) (3)
(q0, aabd, Z0 ) . . . ( q1, d, baaZ0) (q1, d, BZ0)
(q1, , dBZ0) (q1, , DBZ0) (q1, , SZ0)
(4)
(6) (2)
Page 107
405
LR(k) Parsing Parsing
LR(k) parser도 parse table (reduction table이라고도 함)을 가지고
정의한다. 아래의 table은 예로 들었던 LR(1) parser의 parse table이다.
Table의 세로축에는 look-ahead 내용을, 가로축에는 rule의 좌측 기호로
대체할 stack 상부의 내용을 둔다. Table의 내용(entry)은 rule의 좌측에
있는 nonterminal 기호를 두는데, [x, y] = A이면, stack 상부에 x가 있고,
look-ahead 한 내용이 y이면, rule A x를 적용한다는 뜻이다.
S AC | BD A aab
B aab C c D d
(q0, aabc, Z0 ) . . . ( q1, c, baaZ0) (q1, c, AZ0)
(q1, , cAZ0) (q1, , CAZ0) (q1, , SZ0)
(q0, aabd, Z0 ) . . . ( q1, d, baaZ0) (q1, d, BZ0)
(q1, , dBZ0) (q1, , DBZ0) (q1, , SZ0)
c d 1 look-ahead
Parse (reduction) table
stack
상부 ACBDaab
cd
SS
A BCD
Page 108
406
LR(k) Parsing Parsing
임의의 상수 k가 주어졌을 때 앞서 예로 든 CFG를 간단히 수정하여
LR(k) grammar를 만들 수 있다. 예를 들어 k = 5라 하자. 아래의 CFG는
LR(5) grammar임을 쉽게 알 수 있다. ( Rule C c와 D d는 각각
C eeeec와 D eeeed로 바뀌었다. )
S AC | BD A aab B aab C eeeec D eeeed
(q0, aabeeeec, Z0 ) . . ( q1, eeeec, baaZ0)
(q1, eeeec, AZ0) . . . (q1, , ceeeeAZ0)
(q1, , CAZ0) (q1, , SZ0)
(q0, aabeeeed, Z0 ) . . ( q1, eeeed, baaZ0)
(q1, eeeed, BZ0) . . . (q1, , deeeeBZ0)
(q1, , DBZ0) (q1, , SZ0)
eeeec eeeed 5 look-ahead
Parse (reduction) table
stack
상부ACBDaab
eeeeceeeed
SS
A BCD
Page 109
407
S ADC aaaddd A aaa D ddd C Ccc(1) (2) (3) (5) (6)(4)
예 1. 다음 CFG에 대하여 최소의 k 값을 갖는 LR(k) parser를 설계하라.
이 grammar의 언어는 {aaaddd} {aaadddci | i > 0}이다. 이 언어에 있는
string aaabbbccc를 LR(k) parsing 전략에 의하여 어떻게 parse 할 수
있을지 분석하여 보자. 이 string의 rightmost derivation은 아래와
같으므로, LR(k) parser는 이의 역순, 즉 (3)(4)(6)(5)(5)(1)의 순으로
적용하여 parsing 해야성공한다.
Parsing 13.5 LR(k) Parser 만들기
이제, 지금까지 배운 개념을 적용하여 LR(k)를 만드는 예를 들어 LR(k)
parsing 기법을 익히기로 하자.
S ADC ADCc ADCcc ADccc Adddccc aaadddccc(1) (5) (5) (6) (4) (3)
Page 110
408
(q0, aaadddccc, Z0 ) ( q1, aadddccc, aZ0)
(q1, adddccc, aaZ0) (q1, dddccc, aaaZ0) ?
LR(k) parser는 아래와 같이 stack 상단에 rule을 적용할 수 있는
string이 쌓일 때까지 input를 읽어 넣는다. 이 작업은 rightmost
derivation이 마지막으로 적용한 rule (3)가 발생한 string aaa가 stack에
나타날 때까지 진행한다. (이렇게 input tape로부터 stack으로 읽어
넣는 작업을 shift-in이라 한다.)
String aaa가 stack의 상부에 있으면 무조건 rule (3)을 적용할 수 있나?
Rule (2)가 발생한 aaaddd가 input tape에 두었을 때도 stack 상부에 aaa가
나타날 것이다.
Parsing LR(k) Parser 만들기
S ADC aaaddd A aaa D ddd C Ccc(1) (2) (3) (5) (6)(4)
Page 111
409
이 시점에서 LR(k) parser는 rule (2)와 (3) 중의 하나를 선택할 수
있는 정보가 필요하다. 만일 input tape에 aaaddd를 두었다면, 아래와
같이 남아 있는 ddd마저 shift-in한 후 rule (2)을 적용하여 parsing을
성공적으로 마칠 수 있을 것이다. 그렇다고, 위의 시점에서 무조건
ddd를 읽어드릴 수 없다. Rule (3)를 적용할 기회를 놓치기 때문이다.
(2)(q0, aaaddd, Z0 ) ( q1, aaddd, aZ0) . . . .
(q1, , dddaaaZ0) (q1, , SZ0)
Parsing LR(k) Parser 만들기
S ADC aaaddd A aaa D ddd C Ccc(1) (2) (3) (5) (6)(4)
(q0, aaadddccc, Z0 ) ( q1, aadddccc, aZ0)
(q1, adddccc, aaZ0) (q1, dddccc, aaaZ0) ?
Page 112
410
Parsing LR(k) Parser 만들기
S ADC aaaddd A aaa D ddd C Ccc(1) (2) (3) (5) (6)(4)
여기서 parser의 look-ahead 기능이 필요하다. 아래와 같이 4자리를
내다보아, ddd 우측에 c가 있으면 rule (3)을, 비어 있으면(즉, )
끝까지 읽어들여 rule (2)를 적용하면 되겠다.
(q0, aaadddccc, Z0 ) . . (q1, dddccc, aaaZ0) (q1, dddccc, AZ0) ? (3)
이제, stack 상부에 rule (3)을 적용한 후 reduce 할 내용이 없으므로
ddd가 stack 상부에 나타날 때까지 input string을 shift-in하여 넣는다.
. . . (q1, dddccc, AZ0) . . . (q1, ccc, dddAZ0) ?
Page 113
411
이때 ddd가 stack 상부에 있다고 하여 무조건 rule (4)를 적용할 수
없다. Rule (2)를 적용하기 직전에도 stack 상부에 ddd가 있을 수 있기
때문이다. 이 두 경우를 구별하려면, stack 상부의 ddd 밑에 있는
기호를 들여다 볼 수도 있고, input를 한자리 내다볼 수도 있다. 예의
경우, 후자를 선택하여 input를 한자리 look-ahead 하기로 한다. Look-
ahead 한 내용이 c이므로 다음과 같이 rule (4)를 적용하여 ddd를 D로
reduce 한다.
(4). . . (q1, ccc, dddAZ0) (q1, ccc, DAZ0) ?
Parsing LR(k) Parser 만들기
S ADC aaaddd A aaa D ddd C Ccc(1) (2) (3) (5) (6)(4)
Page 114
412
Rule (4)를 적용한 후, stack 상부에 다시 rule을 적용할 수 있는 내용이
없으므로 다음 input symbol c를 stack으로 shift-in 한다. Stack 상단에
나타난 이 c는 rule (6)에 의하여 생성된 것이다. 왜냐하면, string
cc….c는 rule (5)를 반복 적용하여 c를 우측에서 좌측으로 생성하다가
rule (6)를 적용하여 끝나기 때문이다. (만일 rule (5)가 C cC와 같이
바뀌었다면, rule (6)은 오른쪽 끝에 있는 c를 생성한다.) 아래와 같이
c를 shif-in 한 후, 이것이처음 읽은 c라는것은바로 밑에 있는 D를보고
알수 있다. Rule (6)을적용한후의 configuration은다음과같다.
(6). . . (q1, ccc, DAZ0) (q1, cc, cDAZ0) (q1, cc, CDAZ0) ?
Parsing LR(k) Parser 만들기
S ADC aaaddd A aaa D ddd C Ccc(1) (2) (3) (5) (6)(4)
(4). . . (q1, ccc, dddAZ0) (q1, ccc, DAZ0) ?
Page 115
413
(6). . . (q1, cc, cDAZ0) (q1, cc, CDAZ0) ?
위의 configuration에서 stack 상부에 있는 ADC에 rule (1)을 적용할 수
있으나, 아직도 input tape에 cc가 남아 있으므로, 이 rule을 적용하기는
이르다. 이를 확인하려고, parser는 input를 한 자리 내다본다. 만일 c가
남아 있으면, shift-in하여 아래와 같이 rule (5)를 적용하여 stack 상부의
Cc를 C로 reduce 한다. 이 과정을 input에 있는 모든 c가 shift-in될
때까지 반복한 후 , 마지막으로 rule (1)을 적용하여 accepting
configuration에 이른다.
. . . (q1, cc, CDAZ0) (q1, c, cCDAZ0) (q1, c, CDAZ0)
(q1, , cCDAZ0) (q1, , CDAZ0) (q1, , SZ0)(5) (1)
(5)
LR(k) Parser 만들기 Parsing
S ADC aaaddd A aaa D ddd C Ccc(1) (2) (3) (5) (6)(4)
Page 116
414
(3)(q0, aaadddccc, Z0 ) . . . (q1, dddccc, aaaZ0) (q1, dddccc, AZ0)
(4). . . . (q1, ccc, dddAZ0) (q1, ccc, DAZ0) (q1, cc, cDAZ0)
(6)
(q1, cc, CDAZ0) (q1, c, cCDAZ0) (q1, c, CDAZ0) (5)
(q1, , cCDAZ0) (q1, , CDAZ0) (q1, , SZ0)(1)(5)
Parsing LR(k) Parser 만들기
지금까지 분석한 LR(k) parsing history를 모으면 아래와 같고,
적용한 rule의 순서는 아래의 rightmost derivation의 역순과 일치한다.
S ADC aaaddd A aaa D ddd C Ccc(1) (2) (3) (5) (6)(4)
(1) (5) (5) (6) (4) (3)
S ADC ADCc ADCcc ADccc Adddccc aaadddccc
Page 117
415
앞서 우리가 제시한 LR(k) parsing history를 근거로 아래와 같은 LR(4)
parse table을 만들 수 있다. 위의 grammar는 LR(4) grammar이다.
Parsing LR(k) Parser 만들기
dddc dddB BBBB cXXX
aaa
ddd
aaaddd
c*
Cc
ADC
4 look-ahead
Stack
상부 A
D
C
S
CShift-in
X: don‟t care
B : blanks
: no look-ahead
* c의 밑에 C가없음을 확인한다.
S
Shift-in
Parse Table
S ADC aaaddd A aaa D ddd C Ccc(1) (2) (3) (5) (6)(4)
Page 118
416
SEAF EBF EaE a A aaab B aaac F aaad
(1) (2) (3) (4) (5) (6) (7)
예 2. 다음 CFG에 대하여 최소의 k 값을 갖는 LR(k) parser를 설계하라.
이 CFG의 언어는 {aixaaad i 1, x { aaab, aaac} }이다. 이
grammar는 LL(k) 전략으론 parsing이 불가능하다. (왤까? LL(k)
parsing의 rumination을 참조하자.) LR(k) parsing 전략을 적용하여 보자.
앞의 예와 같이 grammar가 발생하는 대표적인 string aaaaaabaaad를
가지고 어떻게 parsing이 진행하는지 분석한 후 parse table을 만들기로
한다. 이 string의 rightmost derivation은 아래와 같이 rule을 적용하므로,
LR(k) parser는 이의 역순으로 rule을 적용해야 한다.
Parsing LR(k) Parser 만들기
S EAF EAaaad Eaaabaaad aEaaabaaad aaEaaabaad aaaaaabaad(1) (7) (5) (3) (3) (4)
Page 119
417
이 grammar가 생성하는 모든 string의 rightmost derivation은 rule (4)를
적용하여 끝난다. 따라서 LR(k) parser는 rule (4)가 발생한 a를 stack으로
shift-in한 후 이 a를 E로 대치할 수 있어야 한다. 이 a를 어떻게 찾을 수
있을까? Grammar의 rule SEAF EBF를 보자. E의 rule (4)가
마지막으로 생성한 a의 우측에는 항상 A 또는 B가 생성한 aaab 또는
aaac가 나타난다.
Parsing LR(k) Parser 만들기
SEAF EBF EaE a A aaab B aaac F aaad
(1) (2) (3) (4) (5) (6) (7)
S EAF EAaaad Eaaabaaad aEaaabaaad aaEaaabaad aaaaaabaad(1) (7) (5) (3) (3) (4)
Page 120
418
이제 stack 상부에 있는 aE는 (항상 stack의 내부에서 상단 쪽으로 읽는
것을 기억하자) rule (3)을 적용하여 E로 reduce 할 수 있다. 이를 두 번
반복한 다음 적용할 rule이 없으므로 rule을 적용할 수 있을 때까지
input를 shift-in 하여 rule (5), (7), (1)의 순서로 적용하면, 다음과 같이
accepting configuration에 이른다.
Parsing LR(k) Parser 만들기
SEAF EBF EaE a A aaab B aaac F aaad
(1) (2) (3) (4) (5) (6) (7)
따라서 parser는 아래와 같이 aaab 또는 aaac가 내다보일 때까지
input를 stack으로 shift-in 하면, stack 상단에 E로 대체할 a가 나타날
것이다. 이를 위하여 parser는 look-ahead 4가 필요하다.
(q0, aaaaaabaaad, Z0) (q1, aaaaabaaad, aZ0) …
(q1, aaabaaad, aaaZ0) (q1, aaabaad, EaaZ0) ?(4)
Page 121
419
…(q1, aaabaaad, EaaZ0) (q1, aaabaaad, EaZ0) (q1, aaabaaad, EZ0)
(q1, aabaad, aEZ0) … (q1, aaad, baaaEZ0) (q1, aaad, AEZ0)
(q1, aad, aAEZ0) ... (q1, , daaaAEZ0) (q1, , FAEZ0) (q1, , SZ0)
(3) (3)
(5)
(7) (1)
Parsing LR(k) Parser 만들기
SEAF EBF EaE a A aaab B aaac F aaad
(1) (2) (3) (4) (5) (6) (7)
지금까지 적용한 rule은 (4), (3), (3), (5),( 7), (1)의 순으로 rightmost
derivation에 적용한 rule의 역순과 일치한다.
S EAF EAaaad Eaaabaaad aEaaabaaad aaEaaabaad aaaaaabaad(1) (7) (5) (3) (3) (4)
Page 122
420
지금까지 분석한 parsing history를 토대로 위의 grammar에 대한
LR(4) parse table을 만들면, 아래와 같다.
Parsing LR(k) Parser 만들기
aaab aaac aaaa 4 look-ahead
a
aE
aaab
aaac
aaad
EE
E
ABF
EAF
EBF
SS
Parse Table
shift-in
SEAF EBF EaE a A aaab B aaac F aaad
(1) (2) (3) (4) (5) (6) (7)
(q0, aaaaaabaaad, Z0) (q1, aaaaabaaad, aZ0)
….(q1, aaabaaad, aaaZ0)
(q1, aaabaad, EaaZ0) (q1, aaabaaad, EaZ0)
(q1, aaabaaad, EZ0) …
(q1, aaad, baaaEZ0) (q1, aaad, AEZ0)
...(q1, , daaaAEZ0) (q1, , FAEZ0)
(q1, , SZ0)
(4)
(3)
(3)
(5)
(7)
(1)
Page 123
421
이 grammar의 언어는 {bibncnccc | i 0, n 1 }이며, derivation은 항상
rule (4)가 bc를 발생하며 끝나는데, 이 bc 는 string bncn의 중앙에 있다.
Parser는 다음과 같이 이 부분을 stack의 상부로 shift-in한 후 rule (4)를
적용한다. 이 과정은 look-ahead 할 필요 없이 진행할 수 있다.
S bS | Accc A bAc | bc(1) (2) (3) (4)
예 3. 다음 CFG에 대하여 최소의 k 값을 갖는 LR(k) parser를 설계하라.
(q0, bbbbbcccccc, Z0)…(q1, ccccc, cbbbbbZ0) (q1, ccccc, AbbbbZ0) ?(4)
Parsing LR(k) Parser 만들기
S bS bbS bbAccc bbbAcccc bbbbAccccc bbbbbcccccc(1) (1) (2) (3) (3) (4)
이 CFG가 발생하는 대표적인 string bbbbbbccccc에 대하여 LR parsing
과정을 분석하여 보자. 이 string의 rightmost derivation은 아래와
같으므로, LR(k) parser는 rule을 이와 역순으로 적용한다.
Page 124
422
이 시점에서 parser는 rule (3)을 적용하여 stack 상부에 있는 bAc를 A로
reduce 할 것인지 c를 더 shift-in 하여 Accc를 만들어 rule (2)를 적용할
것인지 결정해야 한다. 이를 위하여 parser는 3자리를 미리 내다볼
필요가 있다. 왜냐하면, input string의 끝에 있는 ccc가 rule (2)에 의하여
생성된 것이기 때문이다. 만일 내다본 내용이 cc밖에 없으면, 현재
stack의 상단에 있는 c까지 포함하여 ccc가 rule (2)에 의하여 생성된
것이므로 나머지 cc마저 shift-in 한 후 rule (2)를 적용해야 한다.
Parsing LR(k) Parser 만들기
S bS | Accc A bAc | bc(1) (2) (3) (4)
Rule (4)를 적용한 후 다시 적용할 rule이 없으므로 input tape를 읽어
다음 기호 c를 shift-in 한다.
…(q1, ccccc, cbbbbbZ0) (q1, ccccc, AbbbbZ0) (q1, cccc, cAbbbbZ0) ?(4)
Page 125
423
현재의 configuration에서, 3 look-ahead 한 내용이 ccc이므로,
parser는 다음과 같이 c를 shift-in 하고 rule (3)으로 reduce 하는 작업을
input에 cc가 보일 때까지 진행한다.
. . . .(q1, cccc, cAbbbbZ0) (q1, cccc, AbbbZ0)
(q1, ccc, cAbbbZ0) (q1, ccc, AbbZ0) (q1, cc, cAbbZ0) ?
(3)
(3)
Parsing LR(k) Parser 만들기
S bS | Accc A bAc | bc(1) (2) (3) (4)
이제 2 look-ahead 한 내용이 cc 이므로, 이들을 shift-in 하여 다음과
같이 rule (2)를 적용하고, 마지막으로 rule (1)을 두 번 적용하여
accepting configuration에 이른다.
. . .(q1, cc, cAbbZ0) . . . (q1, , cccAbbZ0)
(q1, , SbbZ0) (q1, , SbZ0) (q1, , SZ0)
(2)
(1)(1)
Page 126
424
3 look-aheadccc ccB xxx
bc
bAc
Accc
bS
A
A Shift-in
S
S
Stack
상부
Reduction Table
S bS | Accc
A bAc | bc
(1) (2)
(3) (4)
다음은 지금까지 제시한 parsing history를 모은 것이다. 이를
바탕으로 만든 reduction (parse) table은 아래와 같다.
(q0, bbbbbcccccc, Z0) … . . (q1, ccccc, cbbbbbZ0) (4)
(q1, ccccc, AbbbbZ0) (q1, cccc, cAbbbbZ0) (q1, cccc, AbbbZ0) (3)
(q1, ccc, cAbbbZ0) (q1, ccc, AbbZ0) (q1, cc, cAbbZ0) . . . (3)
(q1, , cccAbbZ0) (q1, , SbbZ0) (q1, , SbZ0) (q1, , SZ0) (2) (1) (1)
Parsing LR(k) Parser 만들기
Page 127
425
정의 (LR(k) grammar). 임의의 CFG G = (VT, VN, P, S)가 있을 때, , ,
V*, x, y VT*, A VN라 하고, x와 y을 rightmost derivation 중에
생성된 두 sentential form이라 하자. 어떤 상수 k에 대하여 다음 조건을
만족하면, grammar G 는 LR(k) grammar 이다.
(i) (k)x = (k)y, S *Ax x, S *Ay y이면
(ii) = 이다.
Parsing
LR(k) Grammar (정의)
LL(k) grammar와 같이, 어떤 CFG가 LR(k) grammar가 될 수 있는
조건은 다음과 같다.
위의 조건이 만족하면, LR(k) parsing 과정에서 stack 상단에 (= )가
있을 때 k만큼 look-ahead 하여 이를 A로 대치(reduce)할 수 있음을 알 수
있다.
Page 128
426
G1 : S Ab | Bc A Aa | a B Ba | a
G2 : S Ab | Bc A aA | a B aB | a
G3 : S aS | aA A b | c
Parsing Rumination: Parsing
(1) Parser는 grammar를 바탕으로 설계된 것이다. 같은 언어일지라도 그 언어를 발생하는 grammar에 따라 parser를 만들
수도 있고, 불가능할 수도 있다. 이러한 이유로, CFG를 놓고 LL(K) grammar 또는 LR(k) grammar라 부를 수 있으며,
LL(k) language라든가, LR(k) language라는 말은 있을 수 없다.
다음의 3 CFG는 같은 언어 {aiX | i 1, X {b, c}}를 발생한다. Grammar G1은 LL(k)나 LR(k), 어느 parsing 전략을
쓰더라도 parsing이 불가능한 CFG이다. G2는 LR(1) grammar이지만, LL(k) grammar가 아니다. G3는 LL(2) grammar이며,
동시에 LR(0) grammar이다. 그 이유를 밝히는 일은 독자의 연습문제로 남겨둔다.
(2) Ambiguous CFG는 여러 개의 leftmost derivation (또는 rightmost derivation)으로 생성할 수 있는 string x가 있다.
우리가 이러한 grammar에 대한 parser를 만들려면, string x을 parsing 할 때는 어느 한 derivation을 따라 parse 하도록
설계할 수밖에 없다. 예를 들어, 아래의 grammar는 ambiguous 하다. LL(0) 또는 LR(0) parser를 만들려면, grammar의
유일한 string a를 발생하는 두 rule S A 또는 S B 중의 하나를 선택하여 parsing 하면 된다.
S A | B A a B a
Page 129
427
(3) LL(k) parser는 초기 state를 포함하여 두 개의 state이면 충분하다. 우리가 예로 든 LR(k) grammar들은 모두 두
state로 parsing이 가능하였지만, grammar에 따라 상수 개의 state가 필요할 때가 있다. 예를 들면, 다음 CFG의 parser는
3개의 state가 필요하다. 그 이유를 알아보자.
Parsing
S aaA | baB | caC
AaA | a B aB | a C aC | a
Rumination: Parsing
이 grammar의 언어는 {xai | x{a,b,c}, i 1}임을 쉽게 알 수 있다. 이 언어의 각 string은 a, b, 또는 c로 시작하고,
derivation은 rule A a, B a 또는 C a를 적용하여 우측 끝 symbol a를 생성하고 끝난다. 이 grammar의 LR(k)
parser가 성공적으로 parsing 하려면, input string의 끝에 있는 a가 stack 상단에 올 때까지 아래의 그림과 같이 input
string을 shift-in 해야 한다. 이때 A a, B a 또는 C a 중 어느 것을 적용해야 할까? 이 문제를 해결하려면, parser는
stack의 바닥에 처음 읽어 넣은 symbol (a, b 또는 c)를 기억하고 있어야 한다. (Parser 는 stack을 유한한 깊이만
들여다 볼 수 있음을 기억하자.)
(q0, baa. . . . aa, Z0) … . . (q1, , aa. . . aabZ0) ?
Page 130
428
(q0, baa. . . . aa, Z0) (qb, aa. . . . aa, bZ0) … . .
(qb, , aa. . . aabZ0) (qb, , Baa. . . aabZ0) (qb, , Ba. . . aabZ0)
. . . . . . (qb, , BabZ0) (qb, , SZ0)
S aaA | baB | caC
AaA | a B aB | a C aC | a
따라서 처음 읽은 기호가 a, b, 또는 c인 각 경우에 따라 아래와 같이 state qa, qb, qc로 각각 천이하여 해당하는
rule을 적용할 수 있게 한다면, LR(1) parsing이 가능하다.
(q0, aaa. . . . aa, Z0) (qa, aa. . . . aa, aZ0) … . .
(qa, , aaa. . . aaaZ0) (qa, , Aaa. . . aaaZ0) (qa, , Aa. . . aaaZ0)
. . . . (qa, , AaaZ0) (qa, , SZ0)
(q0, caa. . . . aa, Z0) (qc, aa. . . . aa, cZ0) … . .
(qc, , aa. . . aacZ0) (qc, , Caa. . . aacZ0) (qc, , Ca. . . aacZ0)
. . . . . . (qc, , CacZ0) (qc, , SZ0)
Parsing Rumination: Parsing
Page 131
429
13.1 다음 각 CFG에 대하여 최소의 k 값을 갖는 LL(k) parser를 아래의 절차 (i), (ii)에 따라 만들라.
(i) Grammar가 발생하는 대표적인 string w에 대한 parsing profile (교과서 예 참조)을 적고, LL(k) parsing이 성공적으로
진행하려면, 어디서 얼마만큼의 look-ahead가 왜 필요한지 명시하라.
(ii) 위의 분석 결과를 바탕으로 LL(k) parse table을 만들어 보이라.
(a) S aS | D D 0 | 1 (b) S aaA A bbS | bbb
(c) S BA | aaab A aAb | aaaaaaab B bBa | bbbb
13.2 (a) 아래의 CFG는 왜 LL(k) grammar가 아닌가? 즉, 어떤 상수 k에 대하여도 이 grammar에 대한 LL(k) parser를 만들 수
없다. 그 이유를 설명하라.
(b) G의 언어와 같은 언어를 발생하는 LL(k) grammar G’를 만들고, 이 grammar에 대한 parse table을 설계하라.
G: S aAb | aBb A aAb | c B aBb | d
13.3 다음 각 CFG에 대하여 아래의 절차 (i) 과 (ii)를 따라 LR(k) parser를 설계하라.
(a) S ABC | BC | C A aaa B aa C a
(b) S aSBb | a B aaaaab
(i) Grammar가 발생하는 대표적인 string w에 대한 LR(k) parsing profile (교과서 예 참조)을 적고, parsing이 성공적으로
진행하려면, 어디서 얼마만큼의 look-ahead가 왜 필요한지 명시하라.
(ii) 위의 분석 결과를 바탕으로 LR(k) parser의 reduction table을 만들어 보이라.
연습문제 Parsing
Page 132
430
Parsing 연습문제
G: S Ahe | Bshe AAwho | who B Bwho | who
13.4 (a) 아래의 CFG는 왜 LR(k) grammar가 아닌가? 그 이유를 설명하라.
(b) G와 동일한 언어를 발생하는 LR(k) grammar G’를 만들고, 이 grammar에 대한 reduction table을 만들어 보이라.
(관례대로 grammar의 대문자는 nonterminal, 소문자는 terminal 기호이다.)
Page 133
431
14. Formal Language 응용
14.1 Hyper Text Markup Language (HTML) 43414.2 Document Type Definition (DTD)과 XML 43714.3 Gene Grammar 445되새김(rumination) 45514.4 Lex와 YACC 456
Page 135
433
14. Formal Language 응용
우리는 3.2절에서 Pascal programming 언어의 syntax를 CFG로 정의할 수 있음을 배웠다. 다른 programming 언어의
syntax도, 한 block 내에서는 같은 변수를 중복 선언할 수 없다는 것, 등 일부 문맥 의존성(context dependence)
syntax를 제외하면, CFG로 정의할 수 있다. 이 장은 먼저 Internet의 등장으로 널리 알려진 Hyper Text Markup
Language(HTML)와 전자상거래(e-commerce)를 목적으로 개발된 Extensible Markup Language (XML)의
syntax를 예로 들어 CFG로 전환하여보기로 한다. 이들 언어를 소개하는 서적을 보면, 대부분의 다른 프로그래밍
언어와 마찬가지로, 언어의 syntax를 형식적인 문법으로 제시하지 않고, 서술형으로 기술하고 있다. 언어를
형식적인 틀에 따라 정의해야 그 언어의 구조와 특성을 체계적으로 분석할 수 있으며, compiler, interpreter, 등과 같은
software를 효과적으로 구현할 수 있기 때문이다.
다음으로 이 장에서 다룰 Gene Grammar는 형식언어를 molecular biology에 응용할 가능성을 보여준다.
유전체(genome)는 네 개의 문자 A, T, C, G로 구성된 서열로 표현하며, 유전체에 있는 유전자(gene)는 일정한 특성이
있는 부문자열(substring)에 해당한다. 체내에서 유전자들이 단백질(protein)로 전환하는 과정은 비교적 자세히
알려져 있는데, 이 장은 이 과정을 grammar로 나타내 보인다.
끝으로 이 장은 compiler의 주요 기능을 담당하는 lexical analyzer와 parser를 각각 만들어주는 software 도구 Lex와
YACC을 간단히 소개한다.
Page 136
434
14.1 Hyper Text Markup Language(HTML)
HTML은 문서의 형식(format)을 정할 목적으로 만들어진 언어이다.
아래 그림의 좌측에는 서술형으로 정의한 HTML의 item list 부분의
grammar를, 우측에는 이를 CFG로 전환한 것을 보여준다. (편의상 주요
항목에 번호를 붙여두었다.) HTML의 다른 부분도 같은 방법으로
CFG로 전환할 수 있다.
Formal Language 응용
(1) Char는 한 개의 문자이다.
(2) Text는 문자열이다.
(3) Doc는 Element 열이다.
(4) 어떤 문자열 x에 대하여
<x>를 tag, </x>를 <x>에대한 matching tag라 한다.
(1) Char a | A | . . . . . | z | Z | . . .
(2) Text CharText |
(3) Doc ElementDoc |
(4) Tag <Text> | </Text>
Page 137
435
(5) Element는 하나의 Text이거나, 한
쌍의 matching tag 사이에 있는 Doc,
또는 unmatching tag를 앞에 둔Doc을 말한다.
(6) ListItem는 document 앞에 tag
<LI> 를 둔 것으로 list의 한목록(item)이다.
(7) List는 일련의 0 또는 하나 이상의ListItem을 말한다.
(5) Element Text |
<x>Doc</x> |
<y>Doc
(6) ListItem <“LI”>Doc
(7) List ListItemList |
Formal Language 응용HTML
전환한 결과, 예의 HTML 부분은 CFL인 것 같이 보인다. 그러나
문제는 (5)번 rule Element <x>Doc</x>의 matching tag에 있다.
정의한 대로 x가 임의의 string이라면, CFG가 임의의 matching tag를
가진 언어를 생성할 수 있는지가 문제이다.
Page 138
436
Formal Language 응용HTML
이 문제는 근본적으로 L = {wcw | w {a, b}* }이 CFL인지를 밝히는
문제와 같다. 언어 L이 CFL이 아니라는 것을 CFG에 대한 pumping
lemma를 가지고 쉽게 증명할 수 있다 (12장 연습문제 12.4 참조). 따라서
matching tag는 HTML을 (context-free가 아닌) context-dependent 하도록
하는 용인이라 할 수 있다. 그러나 matching tag로 쓸 수 있는 상수 개의
특정한 string w1, w2, . . , wk를 정하여 둔다면 (예: <EM>Doc</EM>,
<OL>Doc</OL>, 등), 예의 grammar는 아래와 같이 CFG로 만들 수 있다.
(1) Char a | A | . . . . . | z | Z | . . . (2) Text Char Text |
(3) Doc ElementDoc | (4) Tag <Text> | </Text>
(5) Element Text | <y>Doc | <w1>Doc</w1> | . . . . |<wk>Doc</wk>
(6) ListItem <“LI”>Doc (7) List ListItemList |
Page 139
437
14.2 DTD와 XML
HTML의 한 결점은 document (문서)에 뜻(semantics)을 표현하기가
쉽지 않다는데 있다. 이 결점을 보완하려고 도입된 것이 XML이다.
XML은 DTD (Document Type Definition)라는 형식에 맞게 쓴
document이다. 알고 보면 DTD도 일종의 CFG이다. DTD의 일반적인
형식은 다음과 같다.
Formal Language 응용
<!DOCTYPE name-of-DTD [ List-of-Element-Definitions ]>
여기서 element definitions은 다음과 같은 형식을 갖는다.
<!ELEMENT element-name (Element-Description)>
이를 더 형식적으로 다음과 같이 표현할 수 있다.
DTD <!DOCTYPE name-of-DTD [ List-of-Element-Definitions ]>
List-of-Element-Definitions Element-Definition List-of-Element-Definitions
| Element-Definition
Element-Definition <!ELEMENT element-name (Element-Description)>
Page 140
438
DTD는 grammar의 start symbol S에 해당하며, Element description은
다음과 같이 일종의 변형된 regular expression으로 표현한다.
(1) 다음 (a), (b)는 element description이다.
(a) an element-name.
(b) #PCDATA로 표기된 부분으로 tag가 없는 text.
(2) E1과 E2가 element description이면, E1*, E1+, E1?, (E1, E2), 그리고
E1 | E2도 element description이다.
Formal Language 응용DTD와 XML
DTD <!DOCTYPE name-of-DTD [ List-of-Element-Definitions ]>
List-of-Element-Definitions Element-Definition List-of-Element-Definitions
| Element-Definition
Element-Definition <!ELEMENT element-name (Element-Description)>
Page 141
439
여기서 E1+ = E1(E1)*, E1? = E1+, E1 | E2 = E1+ E2, 그리고 E1,E2는
regular expression E1에 E2를 concatenate한 것을 각각 표현한다. Regular
expression이 표현하는 것은 regular grammar로 생성할 수 있고 regular
grammar는 모두 CFG이므로, Element-Description은 CFG로 표현할 수
있다.
다음 slide의 예는 PC의 명세서(specification)를 정의한 DTD이다.
PC를 거래하는데 쓰는 명세서는 이 DTD에 의하여 정의된 내용을
포함하고 있어야 한다는 뜻이다. 각 줄은 ELEMENT를 정의하며, 들어
쓰기(indentation)는 이해를 돕기 위한 것이다.
Formal Language 응용DTD와 XML
Page 142
440
<!DOCTYPE PcSpecs [
<!ELEMENT PCS (PC*)>
<!ELEMENT PC (MODEL, PRICE, PROCESSOR, RAM, DISK+)>
<!ELEMENT MODEL (\#PCDATA)>
<!ELEMENT PRICE (\#PCDATA)>
<!ELEMENT PROCESSOR (MANF, MODEL, SPEED)>
<!ELEMENT MANF (\#PCDATA)>
<!ELEMENT MODEL (\#PCDATA)>
<!ELEMENT SPEED (\#PCDATA)>
<!ELEMENT RAM (\#PCDATA)>
<!ELEMENT DISK (HARDDISK | CD | DVD) >
<!ELEMENT HARDDISK (MANF, MODEL, SIZE)>
<!ELEMENT SIZE (\#PCDATA)>
<!ELEMENT CD (SPEED)>
<!ELEMENT DVD (SPEED)>
] >
DTD 예: Personal Computer (PC)
Formal Language 응용DTD와 XML
Page 143
441
위의 DTD의 형식에 맞는 XML은 element마다 element-name으로
만든 matching tag로 묶어 표현한 것이다. 이렇게 표현한 XML 역시
CFG로 정의할 수 있다. 다음은 앞서 예로 제시한 DTD PCS의
element를 CFG로 변환하는 예를 보여준다.
<!ELEMENT PC (MODEL, PRICE, PROCESSOR, RAM, DISK+)>
PC <PC>MODEL PRICE PROCESSOR RAM DISK+</PC>
DISK+ <DISK+>DISKS</DISK+> DISKS DISK DISKS | DISK
<!ELEMENT MODEL (\#PCDATA)> MODEL <MODEL>Text</MODEL>
<!ELEMENT PRICE (\#PCDATA)> PRICE <PRICE>Text</PRICE>
Formal Language 응용
<!ELEMENT PCS (PC*)>
PCS <PCS>PCSS </PCS> PCSS PC PCSS |
DTD와 XML
Page 144
442
<!ELEMENT MANF (\#PCDATA)> MANF <MANF>Text</MANF>
<!ELEMENT MODEL (\#PCDATA)> MODEL <MODEL>Text</MODEL>
Formal Language 응용
<!ELEMENT DISK (HARDDISK | CD | DVD) >
DISK <DISK>HARDDISK</DISK> |
<DISK>CD</DISK> | <DISK>DVD</DISK>
. . . . .
. . . . .
<!ELEMENT PROCESSOR (MANF, MODEL, SPEED)>
PROCESSOR <PROCESSOR>MANF MODEL SPEED</PROCESSOR>
DTD와 XML
Page 145
443
앞서 제시한 DTD에 따른 XML document의 한 예를 들면 아래와
같다. 이 예는 XML grammar가 발생한 하나의 string에 해당한다.
<PCS>
<PC>
<MODEL>1234</MODEL>
<PRICE>$3000</PRICE>
<PROCESSOR>
<RAM>512</RAM>
<DISK><HARDDISK>
<MANF>Superdc</MANF>
<MODEL>xx1000</MODEL>
<SIZE>62Gb</SIZE>
</HARDDISK></DISK>
<DISK><CD>
<SPEED>32x</SPEED>
</CD></DISK>
</PC>
<PC> . . . . </PC>
</PCS>
Formal Language 응용DTD와 XML
Page 146
444
되새김: DTD와 XMLFormal Language 응용
XML이 CFL인지는 HTML의 경우와 마찬가지로 matching tag가
임의의 string으로 만들어 쓸 수 있느냐의 문제와 직결된다. 위의 예가
보여주듯이 tag에 쓰는 string들이 MODEL, PRICE, DISK, 등 reserved
word (예약어)로 되어 있으면, XML은 CFL라 할 수 있다. 이 문제는
XML을 처리하는 시스템의 기능과 직결되는 문제이다.
Today’s Quote
The simple solution for disappointment depression: Get up and get moving.
Physically move. Do. Act. Get going.
- Peter McWilliams -
쉬어 가기
Page 147
445
14.3 Gene Grammar (유전자 문법)
Formal Language 응용
세포 내에 있는 DNA의 구조가 1953년에 Watson과 Crick에 의하여
밝혀진 후 학자들은 molecular biology 분야의 지식을 표현할 목적으로
언어학 분야의 용어, 예를 들면, code, express, translate, edit, 등을
인용하기 시작하였다. 이는 molecular biology 관련 지식을 우리가 배운
언어적인 관점에서 접근해 볼 수 있다는 뜻이다 . 이 절은 인간
유전체(human genome)에 있는 유전자(gene)들을 단백질(protein)로
번역하는 과정을 어떻게 grammar로 표현할 수 있는지 알아보기로
한다. 이에 앞서 protein을 만들어내는 과정을 이해하는데 필요한
molecular biology 기초지식을 간단히 소개한다.
Genome은 아래 그림과 같이 긴 나선형 쌍 서열(double helix)로 되어
있는데, 이 두 서열은 A, T, C, G로 각각 표시하는 4종의 화학적인 base
Adenine, Thymine, Cytosine, 및 Guanine으로 구성되어 있다.
Page 148
446
Formal Language 응용Gene Grammar
A G T
T C A
C
GDNA 분자
Genome (double helix)
backbone
bases
DNA 이중서열의 마주 보는 base들은 아래의 예와 같이 A-T, G-C, T-A,
C-G 짝을 이룬다. 이와 같은 DNA 서열의 특성 때문에, 한쪽 서열을
주면, 맞은편 서열을 알 수 있다.
A C T T A A C G G C G A T
T G A A T T G C C G C T A
Page 149
447
TCAAGCT
UCAAGCU
AGTTCGA
RNA
5‟ end
3‟ end3‟ end
5‟ end
(1) RNA Transcription
Gene은 genome의 단일서열 조각, 즉 substring에 해당하는데, gene은
다음 3단계를 거쳐 protein으로 만들어진다. 첫 단계는 이중서열이 아래
그림과 같이 벌어져 gene 부분을 베껴(transcribe) RNA를 만드는
작업이다. RNA는 원 서열의 보서열 (complementary string)이 되는데,
베끼는 과정에서 서열 내의 T는 U(uracil)로 대치된다. 따라서 RNA는
4개의 문자 A, C, G, U로 구성된 string으로 표현할 수 있다.
Formal Language 응용Gene Grammar
Page 150
448
Transcribed RNA
(2) splicing
exons introns
Messenger RNA
(3) Translation
Protein
다음 단계는 복사된 RNA로부터 필요 없는, 소위 intron 부분을
잘라내고 나머지 exon 부분을 결합하여 messenger RNA를 만드는
splicing 작업이다. 마지막 셋째 단계에서 messenger RNA (mRNA)는
ribosome이라는 일종의 번역기(translator)에서 읽혀 protein이 만들어진다.
Formal Language 응용Gene Grammar
Page 151
449
번역은 mRNA의 연속하는 세 base, 즉 codon을 단위로 진행하는데, start
codon ATG로 시작하여 stop codon TAA, TAG, 또는 TGA을 만날 때까지,
각 codon을 amino acid로 대체한다. RNA는 4개의 문자로 되어 있으므로,
길이 3인 codon의 수는 444 = 64개다. 하지만, 이들을 대체할 amino
acid의 수는 20개이므로, 아래의 codon table과 같이 여러 개의 codon이
같은 amino acid로 바뀐다. (관례에 따라 codon은 mRNA의 문자 U 대신
DNA 문자 T를 쓴다.)
Formal Language 응용Gene Grammar
Ala Arg Asp Ans Cys Glu Gln Gly His Ile Leu Lys Met Phe Pro Ser Thr Trp Tyr Var Stop
GCA
GCG
GCT
GCC
AGA
AGG
CGA
CGG
CGT
CGC
GAT
GAC
AAT
AAC
TGT
TGC
GAA
GAG
CAA
CAG
GGA
GGG
GGT
GGC
CAT
CAC
ATA
ATT
ATC
TTA
TTG
CTA
CTG
CTT
CTC
AAA
AAG
ATG(start)
TTT
TTC
CCA
CCG
CCT
CCC
AGT
AGC
TCA
TCG
TCT
TCC
ACA
ACG
ACT
ACC
TGG TAT
TAC
GTA
GTG
GTT
GTC
TAA
TAG
TGA
Codon Table
Page 152
450
Formal Language 응용Gene Grammar
앞서 제시한 gene에서 protein을 얻기까지의 3단계는, 소위 molecular
biology의 central dogma (중심 정설)에 기초를 둔 것으로, 예외적인 경우가
많아 정설이 아니다. 그러나 형식언어가 어떻게 molecular biology에
적용할 수 있는가를 보여주는 좋은 예가 될 것이므로, 이 dogma를
바탕으로 형식 언어 grammar를 만들기로 한다. 제시할 grammar는 David
Sears의 논문 “The Linguistics of DNA” (American Scientist, Vol. 80, 1992)에
게재된 것을 일부 편집한 것이다.
이제, 앞서 공부한 HTML과 XML의 경우와 같이, gene 발현에 관하여
서술적으로 제시된 정보를 바탕으로 grammar를 만들어 보자.
Page 153
451
Formal Language 응용Gene Grammar
• Transcript는 DNA의 gene 부분을 복사(transcribe) 한 것으로 start-
codon으로 시작하는 coding-region을 가운데 두고 앞뒤에 각각 5‟-
untranslated-region과 3‟-untranslated-region이 있다.
<gene> → <transcript>
<transcript> → <5‟-untranslated-region><start-codon><coding-region>
<3‟-untranslated-region>
• Coding-region은 일련의 splice와 codon으로 구성되어 있으며 항상 stop-
codon으로 끝난다. Splice는 GT로 시작하고 AG로 끝나는 intron으로 되어
있다.
<coding-region> → <codon><coding-region> |
<splice><coding-region>|<stop-codon>
<splice> → <intron>
<intron> → GT<intron-body>AG
Page 154
452
Formal Language 응용Gene Grammar
• Stop-codon은 TAA, TAG, TGA 중 하나이며, 이들은 amino acid로
translate 되지 않는다. 나머지 61개의 codon은 앞서 제시한 codon table에
따라 20개 중의 한 amino acid로 바뀐다.
<start-codon> → <Met> <stop-codon> → TAA | TAG | TGA
<codon> → <Ala> | <Arg> | <Asp> | <Asn>| <Cys>| <Glu>| <Gln> |
<Gly> | <His> | <Ile> | <Leu>| <Lys> | <Met>| <Phe>|
<Pro> | <Ser> | <Thr> | <Typ> | <Tyr> | <Val>
• Codon의 처음 2 base가 같으면, 셋째 base가 pyrimidine (C 또는 T)이냐
purine (A 또는 G)이냐에 따라 같은 amino acid로 바뀐다. 다음은 codon
table 일부를 grammar rule로 정의한 것이다.
<Ala> →GC<base> <Arg> → CG<base> <Asp> →GA<pyrimidine>
<Cys>→TG<pyrimidine> <Glu> → GA<purine> <Gln> →CA<purine>
<base>→A|C|G|T <pyrimidine> → C|T <purine>→A|G
Page 155
453
지금까지 제시된 grammar rule은 모두 CFG type이다. 그러나 다음과
같은 현상 때문에, CFG rule만 가지고 gene grammar를 만들 수 없으며,
언어계층에서 한 단계 위에 있는 CSG rule이 필요하다.
• Intron은 좌측 또는 우측으로 천이(transpose) 할 수 있다.
<base><intron> → <intron><base> <intron><base> → <base><intron>
지금까지 도입한 rule을 정리하여 다시 쓰면 다음 쪽의 table이 보여주는
gene grammar를 얻는다.
Formal Language 응용Gene Grammar
Page 156
454
<gene> → <transcript>
<transcript> → <5‟-translated-region><start-codon><coding-region><3‟-translated-region>
<coding-region> → <codon><coding-region> | <splice><coding-region> | <stop-codon>
---------------------------------------------------------------------------
<codon> → <Ala> | <Arg> | <Asp> | <Asn>| <Cys>| <Glu>| <Gln> | <Gly> | <His> | <Ile>|
<Leu>| <Lys>| <Met>| <Phe>| <Pro>| <Ser>| <Thr>| <Typ>| <Tyr>| <Val>
<start-codon> → <Met> <stop-codon> → TAA | TAG | TGA
-----------------------------------------------------------------------------
<Ala> → GC<base> <Arg> → CG<base> <Asp> → GA<pyrimidine> <Cys> → TG<pyrimidine>
<Glu> → GA<purine> <Gln> → CA<purine> <Gly> → GG<base> <His> → CA<Pyrimidine>
<Ile> → AT<pyrimidine> | ATA <Leu> → TT<purine> | CT<base> <Lys> → AA<purine>
<Met> → ATG <Phe> → TT<primidine> <Pro> → CC<base> <Thr> → AC<base>
<Ser> → AG<primidine> | TC<base> <Typ> → TGG <Tyr> → TA<pyrimidine> <Val> → GT<base>
-------------------------------------------------------------------------------
<base> → A | T | G | C <pyrimidine> → C | T <purine> → A | G
-------------------------------------------------------------------------------
<splice> → <intron> <intron> → GT<inton-body>AG
-------------------------------------------------------------------------------
<intron><base> → <base><intron> <base><intron> → <intron><base>
Formal Language 응용Gene Grammar
Page 157
455
Formal Language 응용
Rumination: Gene grammar
제시한 gene grammar는 nonterminal 기호 <5‟-untranslated-region>, <3‟-untranslated-region> 및 <intron-body>에 대한
rule이 정의되어 있지 않아 온전한 grammar라 할 수 없다. Coding-region의 앞뒤에 있는 두 region은 유전자 발현을 여러
방법으로 조절하는 기능이 있는 곳으로 알려졌지만, 문법으로 표현할 수 있는 구체적인 정보가 없다. Intron-body에
해당하는 부분은 일반적으로 긴 반복되는 서열로 알려졌지만, 이 부분 역시 grammar에 반영할 수 있는 구체적인 정보가
없어, 연구가 더 필요한 부분이다.
Dear Dad & Dear Son
Dear Dad,
$chool i$ really great. I am making lot$ of friend$ and $tudying very hard. With all my $tuff, I $imply can`t
think of anything I need, $o if you would like, you can ju$t $end me a card, a$ I would love to hear from you.
Love,
Your $on
The Reply:
Dear Son,
I kNOw that astroNOmy, ecoNOmics, and oceaNOgraphy are eNOugh to keep even an hoNOr student busy.
Do NOt forget that the pursuit of kNOwledge is a NOble task, and you can never study eNOugh.
Love,
Dad
- Adrea -
쉬어 가기
Page 158
456
14.4 Lex와 YACC
Lexical analyzer와 parser는 compiler의 두 주요 기능을 담당하는
program이다. Lexical analyzer는 source program을 읽어 예약어
(reserved word), 연산자, 변수 명(variable names), 등과 같은 의미 있는
기본 요소인 token을 찾아낸다. 그리고 parser는 token들 사이의
문법적인 관계를 나타내는 parse tree를 구한다. 이 절은 lexical
analyzer와 parser를 만들어 주는 두 software tool을 간단히 소개한다.
Formal Language 응용
Page 159
457
Lex는 lexical analyzer를 자동으로 만들어 주는 software이다.
Token들을 regular expression으로 표현하여 입력으로 주면, Lex는 C
언어로 된 lexical analyzer를 만들어 준다. (실제로 이 lexical analyzer는
token을 인식하는 FA를 program으로 구현한 것이다.) Lex에 주는
입력은 다음과 같이 세 부분으로 나누어지는데, 각 부분은 %%로
분리되어 있다.
(1) Token definition
(2) Token description과 actions
(3) User-written codes
Lex
Formal Language 응용
Page 160
458
Formal Language 응용
(1) Token definition
Token definition에서는 아래에 예시한 것과 같이 각 token을 일종의
변형된 regular expression을 써서 정의한다. 다음 예는 우리가 배운
regular expression과 비교해 놓은 것이다.
(a | b)* = (a+b)* (a | b)+ = (a+b)(a+b)* [ab] = (a+b),
[a-z] = a + b + . . . + z (abc)? = (abc + ) abc? = {abc, ab}
(2) Token Descriptions 및 Actions
Lex는 token을 발견하면 parser에게 token이 어떤 것인지 알려준다.
Token Descriptions 및 Action 부는 parser에 알려줄 내용을 기록하고
있다. 예를 들면,
{real} return FLOAT;
{integer} return INTEGER;
Lex
Page 161
459
(3) User-Written Code
Token에 대한 Action 부가 복잡할 때, action을 C 언어로 쓴
function으로 구현하여 이 영역에 두어, Action 부에서 function을 불러
쓸 수 있도록 한다. (Lex에 대한 보다 자세한 내용은 compiler 교재를
참고하기 바란다. )
Formal Language 응용Lex
Today‟s Quote
He who receives a benefit should never forget it;
he who bestow should never remember it.
- Pierre Charron -
쉬어 가기
Page 162
460
YACC
YACC은 입력으로 CFG를 받아 우리가 배운 look ahead LR (일명
LALR) parser를 reduction table과 함께 C program으로 구현하는
software 도구이다. 입력엔 grammar의 각 rule의 의미 (semantics)에
따른 action도 둘 수 있는데, YACC은 이 action을 실행하는 code를
만들어 준다. YACC 의 입력은 Lex의 경우처럼 다음과 같이 3
부분으로 구성되어 있다.
(1) Declarations 및 Definitions
(2) Grammar and Actions
(3) User-written Codes
위의 각 부분의 역할을 간단히 소개한다. 자세한 내용은 compiler
교재나 YACC에 관한 전문서적을 참고하기 바란다.
Formal Language 응용
Page 163
461
YACC
(1) Declarations 및 Definitions
이 부분은 한 개의 기호로 된 operator를 제외한 모든 token을
정의하고, operator precedence와 associativity (left-to-right 또는 right-to-
left)를 알려준다. 그리고 이 부분은 프로그램의 다른 부분과 적절한
link를 설정할 수 있도록, 변수는 어떤 것들이 있으며, 어떤 data type
이 정의되어 있는지 알려준다. 간단한 예를 들면 다음과 같다.
%token ID /*token for identifier */
%token NUMBER /* token for numbers */
%token BEGIN END ARRAY FILE
#include “yylex.c” /* include lexical scanner */
extern int yylval; /* token values from yylex */
int tcount = 0; /* a temporary integer variable */
%start S /* Grammar‟s start symbol */
Formal Language 응용
Page 164
462
(2) Grammar 및 Actions
Grammar는 다음과 같이 BNF(Backus-naur form)로 정의한다 .
• 단일 기호는 terminal 기호로 쓰는데 단일 인용부호 사이에 두고,
nonterminal 기호는 인용부호 없이 한 단어로 쓴다.
• 화살표() 대신 colon( : )을 쓰고 rule의 끝에 semicolon을 둔다.
• Blank는 을 의미한다.
다음 예는 BNF로 쓴 간단한 grammar와 이를 CFG rule로 번역한 것이다.
(예에서 i는 변수.)
E E + T | E – T | T
T T * F | T / F | F
F (E) | I
expr : expr „+‟ term | expr „-‟ term | term ;
term : term „*‟ fact | term „/‟ fact | fact;
fact : „(„ expr „)‟ | ID ;
YACC Formal Language 응용
Page 165
463
(3) User-written codes
main ( )
{
yyparse( );
}
이 부분에는 아래와 같이 yyparse()를 부르는 명령을 두는데,
필요하면 다른 code를 추가할 수 있다.
YACC Formal Language 응용
Page 166
464
15. 형식언어 및 오토마타 체계 III
15.1 TM이 인식할 수 없는 언어 468
Enumeration (헤아리기)
Enumerable (헤아릴 수 있는) 언어TM이 인식할 수 없은 언어
15.2 Universal TM 479
15.3 Enumerable Languages 481
15.4 Recursive Language 491
15.5 Chomsky Hierarchy의 characterization 증명 503
Type 0 grammar와 TM
CSG와 LBA
CFG와 PDA
되새김(rumination) 541
연습문제 542
Page 168
466
다음 쪽에 있는 그림은 5 장에서 배운 형식언어와 오토마타 체계, 즉 Chomsky Hierarchy를 옮겨 놓은 것이다.
그림에서 빨간색 화살표는 7 장과 12 장에서 이미 증명한 관계를 나타낸다. 이 장에서는 형식언어 체계에서 빠뜨릴 수
없는 두 언어, 즉 TM이 인식할 수 없는 언어와, 인식하거나 reject 할 때 항상 정지할 수 있는 TM 언어(일명 recursive
language)를 도입하고, 이들을 추가한 Chomsky 체계에서 우리가 증명해 보이지 못했던 부분을 마무리 한다. 이 장의
내용은 저학년 학부과정에서 다루기에는 정도가 다소 높다고 생각한다 . 그러나 이 장의 여러 증명에서
이용하는 증명법과 그 결과는 매우 흥미로운 것으로 컴퓨터를 전공하는 학생이라면 도전해 볼만한 가치가 있다.
15. 형식언어 및 오토마타 체계 III
Page 169
467
Chomsky Hierarchy
Review형식언어 및 오토마타 체계 III
Finite State
AutomataRegular
Languages(type3)
Regular
Expression
.
.
.
.
.
Post System,
Markov Algorithms,
-recursive Functions
Turing
Machines
Languages (grammars) Automata 기타 Models
Recursively Enumerable
Sets (type 0)
Context-sensitive
Languages (type 1)
Linear-bounded
Automata
Context-free
Languages(type 2)
Pushdown
Automata
Page 170
468
이 장에서 우리가 주로 이용할 증명법의 하나는 1장에서 소개한
대각화 기법(diagonalization technique)이다. 이 기법을 적용하려면,
주어진 input alphabet을 쓰는 모든 TM, 또는 특정한 type의 모든
grammar를 나열(enumerate)할 필요가 있다. 이 문제를 다루기 전에, 어떤
대상을 enumerate 한다는 말의 뜻을 정의할 필요가 있다.
예를 들면, 모든 양의 정수의 집합 또는 문자열의 집합은 크기 순이나
사전 순으로 tape에 기록하는 TM을 설계할 수 있다. 따라서, 이들 집합은
enumerable 하다. (크기가 무한한 집합을 나열하는 TM은 정지하지 않고
나열하는 작업을 계속한다.)
15.1 TM이 인식할 수 없는 언어
정의 15.1(Enumeration). 어떤 집합 S가 주어졌을 때, „S를 enumerate
한다.‟라는 말은 S의 모든 요소들을 일렬로 늘어놓는 (즉, 나열하는)
작업을 말하며, 이런 일을 하는 TM을 enumerator (나열자)라 한다. S가
enumerate 할 수 있는 집합이면, S를 enumerable 집합이라 한다.
형식언어 및 오토마타 체계 III
Page 171
469
Enumerable 한 집합을 countable 하다고도 한다. 왜냐하면, 나열할 수
있다는 말은 헤아릴 수 있다는 뜻과 같기 때문이다. 집합 중에는
enumerator를 설계하는 것이 단순하지 않거나 불가능한 것이 있다. 다음
정리가 그러한 집합이 있음을 보여준다.
다음 그림은 양의 정수를 enumerate 하는 TM의 개념도 이다. 나열할
수가 무한히 많으므로, 이 TM은 정지하지 않는다.
형식언어 및 오토마타 체계 IIITM이 인식할 수 없는 언어
tape에1을 쓴다 최 우측에 있는 수를
우측으로 두 자리띄우고 복사한다.
복사한 수에1을 더한다start
Page 172
470
정리 15.1 유한개의 문자의 집합, 즉 finite alphabet Σ가 있다 하자. Σ로
만든 모든 언어, 즉 Σ*의 모든 subset의 집합은 enumerable 하지 않다.
형식언어 및 오토마타 체계 IIITM이 인식할 수 없는 언어
증명. 대각화 기법을 쓴다. Σ*의 모든 subset (즉 언어)를 L1, L2, L3, . . ,와
같이 나열할 수 있다 하자. 아래 그림처럼, matrix M의 세로축에는 Σ* 내에
있는 모든 string wi를 사전 순으로 나열하고, 가로축에는 언어들을
나열한다. M의 내용은 i번째 string wi가 j번째 언어 Lj에 포함되어 있으면,
M[i, j] = 1, 그렇지 않으면, M[i,j] = 0이 되도록 한다. 이렇게 만든 M의
대각선을 따라가며 0이 있는 행의 string들을 모아 아래와 같이 언어 LD를
만든다.
LD = { wi | M[i, j] = 0 }
L1 L2 L3 L4 L5 . . .w1
w2
w3
w4
0
1
1
0
1 0 1 1
1 0 0 1
1 0 1 0
0 1 1 0..
Page 173
471
언어 LD는 나열된 어느 언어와도 같지 않다. (이 증명은 |Σ| = 1,
예를 들면, Σ = {a}일 때도 성립한다.) 이 주장이 옳지 않다고 하자.
LD는 j(1)번째 언어 Lj와 같아야 한다. 그렇다면, 임의의 string wi에
대하여 다음 두 경우 중의 하나가 참이어야 한다.
형식언어 및 오토마타 체계 IIITM이 인식할 수 없는 언어
LD = { wi | M[i, j] = 0 }
L1 L2 L3 L4 L5 . . .w1
w2
w3
w4
0
1
1
0
1 0 1 1
1 0 0 1
1 0 1 0
0 1 1 0..
(1) M[i, j] = 0, 즉 wiLj. 그러나, wiLj wiLD LD Lj.
(2) M[i, j] = 1, 즉 wiLj. 하지만, wiLj wiLD LD Lj.
두 경우 다 모순에 이른다. 따라서 LD = Lj라는 가정은 잘못이다. 즉,
나열되지 않은 언어가 있으므로 정리는 옳다.
Page 174
472
이제, TM을 enumerate 하는 문제로 돌아가 그 가능성을 검토해
보기로 하자. TM M은 우리가 잘 알다시피, 6-tuple M = (Q, Σ, , , q0,
F)로 정의한다. 여기서 Q, Σ, 는 모두 유한하고, Σ , F Q이다.
모든 TM은 한 개의 accepting state로 충분하므로 F = {q1}, input
alphabet Σ = {a, b}라 하자. (Σ이 유한하면, 같은 논리가 성립하므로
편의상 | Σ | = 2인 경우를 택한다.)
Alphabet Σ = {a, b}로 된 언어를 인식하는 모든 TM을 나열하려면,
모든 크기의 유한한 상태집합 Q와 tape alphabet 을 가지고 정의된
TM을 대상으로 삼아야 한다. (여기서 유한하다는 말은 TM에 따라
상수의 크기를 갖고 있다는 뜻이며, 그 크기에는 상한 치(upper
bound)가 있을 수 없다는 것을 명심하자.)
TM을 enumerate 하기
형식언어 및 오토마타 체계 IIITM이 인식할 수 없는 언어
Page 175
473
형식언어 및 오토마타 체계 IIITM이 인식할 수 없는 언어
Alphabet = {a, b}로 된 언어는 무한히 많으므로, 이들을 인식하는
TM의 수 역시 무한하다. 이들을 일렬로 enumerate 하는 것이 가능할까?
가능하다면, 어떤 방법으로 나열할 수 있을까? TM을 정의할 때 쓰는 state
이름, tape에 쓰는 문자, 그리고 head의 이동 방향을 나타내는 기호를
다음과 같이 무한히 많은 문자 중에 유한 개를 선택하여 쓰기로 한다.
State names: {q0, q1, q2, . . . . }
Tape symbols: {t0, t1, t2, . . . . . }
Head directions: {R, L, N}
여기서 q0는 start state, q1은 accepting state, t0는 blank (B), 그리고 t1 = a, t2
= b로 정하여 쓰기로 하자.
Page 176
474
우리가 알다시피, TM은 (6-tuple을 쓰지 않고) state transition function
나 graph G만으로 정의할 수 있다. 편의상 TM을 로 정의하되, 아래의
예와 같은 형식으로, 를 직선상에 기록한다고 하자.
(q0, a) = (q2, b, R); (q2, a) = (q5, a, L); (q0, b) = (q3, b, R); . . . . .
형식언어 및 오토마타 체계 IIITM이 인식할 수 없는 언어
이러한 TM 정의로부터 , 괄호, 콤마, 공백, 등 부수적으로 쓰는
기호를 제거하여 다음과 같이 간략하게 표현하기로 한다.
q0t1=q2t2R;q2t2=q5t1L;q0t2=q3t3R; . . . . .
이 형식을 보면, 각 transition은 6개의 기호로 되어 있으며, 이웃하는
것과 세미콜론으로 분리되어 있다. 이런 정의는 readability가 좋지 않지만,
논리적으로 원래의 것과 다를 바 없다. (이런 약식 표현을 쓰는 이유는,
TM을 2진수로 전환하는데 따를 번거로움을 덜기 위함이다.)
Page 177
475
형식언어 및 오토마타 체계 IIITM이 인식할 수 없는 언어
E(;) = 010, E(=) = 0120, E(L) = 0130, E(R) = 0140, E(N) = 0150,
E(qi) = 016+2i0, E(ti) = 017+2i0, i ≥ 0.
E를 encoding function이라 하고, TM을 정의할 때 쓰는 기호를
다음과 같이 2진수로 정하자. (E를 homomorphism라고도 한다.)
위의 2진 code를 보면, 양끝에 0이 있고, 그 사이에 있는 1의 수를
달리하여 문자를 알 수 있게 한다. (State 기호는 짝수개의 1, tape 기호는
홀수개의 1을 둔다.) 위에서 예로 든 TM의 각 transition은 다음과 같이
2진 수로 encode 할 수 있다.
q0t1=q2t2R; 01600190012001100011100140010
q2t2=q5t1L; 011000111001200116001900130010
q0t2=q3t3R; 016001110012001120011300140010
. . . . .
Page 178
476
형식언어 및 오토마타 체계 IIITM이 인식할 수 없는 언어
임의의 TM M과 binary string w를 input tape에 주면, w = E(M)인지를
판단하는 TM을 만들 수 있다. State code와 tape symbol code, 0120 (= ),
그리고 state code, tape symbol code, 방향 code 순으로 있는지 확인할 수
있다.
이제 , 우리가 정한 형식으로 encode 한 모든 TM을 나열하는
enumerator를 만들어 보자. 이 enumerator는 tape 상에 모든 2진 string을
길이와 크기 순으로 하나씩 나열하며, string wi가 어떤 TM M의 E(M)인지
검사한다. 검사를 통과하면, 두고 그렇지 않으면 지워 버리고 다음
string을 tape에 쓰고 검사하는 일을 반복한다.
TM enumerator
w1, w2, w5, . .wi . . .
Page 179
477
Encoding function E는 one-to-one function이다. 즉, 두 개의 TM이 같은
binary code로 encoding 될 수 없다는 뜻이다. 어떤 TM M이 인식하는
언어 L(M)은 하나밖에 없으므로, TM을 enumerate 할 수 있다는 사실은
TM이 인식하는 모든 언어도 enumerate 할 수 있다는 뜻이다. (물론
나열된 언어 중에는 중복이 있을 수 있다.) 따라서 우리는 다음과 같은
주장을 할 수 있다.
형식언어 및 오토마타 체계 IIITM이 인식할 수 없는 언어
따라서 다음과 같은 정리가 성립한다.
정리 15.2 E(M)으로 binary encode 한 모든 TM M은 enumerable 하다.
따름정리(corollary). 유한한 기호의 집합 Σ를 alphabet로 하는 모든
type 0 언어는 enumerable 하다.
이런 뜻에서 type 0 언어를 recursively enumerable (R.E.) 언어라 한다.
Page 180
478
정리 15.1에 의하면, 유한한 기호의 집합 Σ를 alphabet로 하는 모든
언어의 집합은 enumerable 하지 않다고 한다. 이 정리와 위에서 제시한
따름정리에 따라 다음과 같은 정리를 얻을 수 있다.
TM이 인식할 수 없는 언어
형식언어 및 오토마타 체계 IIITM이 인식할 수 없는 언어
정리 15.4 Binary encode 한 모든 CSG는 enumerable하다.
정리 15.3 Σ를 임의의 유한한 alphabet라 하자. Σ를 alphabet로 하는 언어
중에는 TM이 인식할 수 없는 언어가 있다.
이 정리는 흥미롭게도 Σ = {a}인 경우에도 성립한다는 것을 알 수 있다.
앞서 제시한 encoding 기법은 TM뿐 아니라 다른 automata와 grammar에도
적용할 수 있다. 예를 들면, CSG도 같은 방법으로 binary encoding 할 수
있으며, 다음 정리도 참임을 같은 방법으로 증명할 수 있다.
Page 181
479
정의 15.2 (Universal TM). 임의의 TM M과 input x를 주면, M이 input
x을 가지고 하는 일을 simulate 하는 TM을 universal TM이라 한다.
Universal TM Tu를 만들어 보자. TU는 E(M)과 E(x), 그리고 M의 현
상태 E(qi)와 head의 위치를 아래 그림과 같이 3개의 track에 기록하여
두고, 이 정보를 가지고 M이 하는 일을 한 step 씩 simulate 한다.
Universal TM Tu
E(M)
E(x)
E(qi)
M의 head 위치
15.2 Universal TM
형식언어 및 오토마타 체계 III
Page 182
480
Universal TM
M이 accept state에 들어가면 TU도 accepting 상태에 들어가고
정의되지 않은 transition이 발생하면, accept 하지 않은 state에서
simulation을 마친다.
TM M은 transition function 에 의하여 L(M)만 인식한다. 따라서
M은 L(M)을 인식하기 위한 특정한 용도(special purpose)의 computer라
할 수 있다. 반면, universal Turing machine TU는, 임의의 E(M)과 E(x)를
주면, M이 input x에 대한 계산 결과를 준다. 따라서 TU는, 프로그램과
입력을 주면, 프로그램을 실행하여 결과를 주는 범용(general purpose)
컴퓨터와 같다.
형식언어 및 오토마타 체계 III
Today‟s Quote
Be slow in choosing a friend, slower in changing.
- Benjamin Franklin -
쉬어 가기
Page 183
481
정리 15.5 (1) 임의의 언어 L이 enumerable 하면, L은 type 0 (R.E.) 언어다.
(2) 임의의 언어 L이 type 0(R.E.)이면, L은 enumerable 하다.
증명 (1). L을 enumerate 하는 TM을 Me라 하자. Me을 가지고 L을
인식하는 TM M을 만든다. M은 아래 그림과 같이 finite control에 둔
Me를 가지고 L을 tape에 enumerate 하면서 다음 string wi가 발생할 때마다
input x와 일치하는지 검사한다. 일치하면 accept 하고, 다르면 다음 string
wi+1을 발생하여 x와 비교하는 작업을 반복한다. TM M은 x L일 때만
accept 한다. 따라서, L은 type 0 언어다.
15.3 Enumerable Languages
형식언어 및 오토마타 체계 III
TM MMe
x
wi
Page 184
482
증명 (2). 언어 L을 인식하는 TM M을 가지고 L(M)을 나열하는
enumerator Me을 설계한다. 이 작업은 (1) 번처럼 간단하지 않다. 언어
L(M)의 alphabet을 라 하자. 아래 그림과 같이 * 내의 string wi를
사전 순으로 생성한 다음 이것을 M이 accept 하면, tape 상에 나열하고,
accept 하지 않으면 무시하면 될 것 같다. 그러나 문제는 M이 주어진
string을 accept 하지 않고 무한 loop에 들어갈 경우다. 왜냐하면,
enumerator는 M이 다음 string을 언젠가 accept 할지, 그렇지 않고 무한
loop에 들어갈지 판단할 방법이 없기 때문이다.
Enumerable Languages 형식언어 및 오토마타 체계 III
w1 w2 w3 w4 . . . .
w2 w4 w7 . . . .
accepted stringsTM MMe
enumerated
strings
Page 185
483
Me는 이 문제를 다음과 같이 해결한다. Me는, 아래 그림과 같이,
*에 있는 string을 사전 순으로 나열하며, 각 string을 입력으로 한
단계씩 점진적으로 그림의 화살표가 지시하는 순서를 따라 M의
계산을 simulate 한다. 즉 w1을 쓴 후, w1을 입력으로 M의 첫째 step을
simulate 하고, w2를 쓴 후, 이를 입력으로 M의 첫째 step을 simulate
하고, 다시 w1을 입력으로 둘째 step을 simulate 한 다음, w3를 쓴 후,
이를 입력으로 첫째 step을 simulate 하는 등의 절차를 계속한다.
이 과정에 accept 하는 string이 있으면, 아래 track으로 옮겨 나열한다.
Enumerable Languages 형식언어 및 오토마타 체계 III
•
•
•
•
•
•
•
•
•
•1
2
3
4..
steps
w1 w2 w2 w4 . . . .
TM M
Me
enumerated
strings
Page 186
484
Chuch의 가정에 따르면, TM의 계산능력을 능가하는 machine model은
없다고 한다. 그렇다면, 우리는 다음과 같은 흥미 있는 질문을 할 수
있다. TM의 능력에 한계가 있을까? 있다면, TM이 인식할 수 없는
언어는 어떤 것이 있나? 우리는 이미 모든 TM은 enumerable 하지만,
주어진 alphabet로 만들 수 있는 모든 언어는 enumerable 하지 않다는
사실에 따라, TM이 인식할 수 없는 언어가 있음을 증명했다.
이 증명은 non-constructive 방법이다. Constructive 한 방법으로 증명할
수 없을까? 다시 말하면, TM이 인식할 수 없는 언어를 만들 수 없나?
다음 정리의 증명은 이 질문에 대한 답을 보여준다.
형식언어 및 오토마타 체계 IIIEnumerable Languages
Page 187
485
형식언어 및 오토마타 체계 IIIEnumerable Languages
정리 15.6 Σ를 크기가 유한한 alphabet라 하자. TM이 인식할 수 없는
언어 L ( Σ*)이 있다.
증명. 모든 TM과 Σ* 내에 있는 모든 string이 enumerable 하다는 사실을
이용하여 대각선(diagonalization) 기법으로 증명한다. (증명은 정리
15.1의 것과 매우 유사하다.) TM은 우리가 정한 형식으로 binary
encoding 되었다고 가정한다.
Matrix M을 만드는데, 다음 쪽의 그림이 예시하는 것과 같이,
세로축에는 Σ*에 있는 string을 사전 순으로 나열하고, 가로축에는 Σ을
input alphabet으로 하는 모든 TM을 나열한다. Matrix 내용은 i번째
string wi를 j번째 TM Mj가 accept 하면 M[i, j] = 1, 그렇지 않으면
M[i, j] = 0가 되도록 한다.
Page 188
486
TM Mi가 인식하는 언어 L(Mi) = { wj | M[j, i] = 1, j 0 }이다. 이제,
matrix M의 대각선을 따라가며 0이 있는 곳의 가로축에 있는 string wi를
모아 만든 언어 L0를 고려해 보자. 이들 wi는 TM Mi가 accept 할 수 없는
string이다. 이제, 어떤 TM도 L0를 인식할 수 없음을 증명한다.
형식언어 및 오토마타 체계 IIIEnumerable Languages
L0 = { wi | M[i, i] = 0, i ≥ 0 } = {w0, w2 . . .}
M0 M1 M2 M3 M4 . . .w0
w1
w2
w3
0
1
0
1
1 0 1 1
1 0 0 1
1 0 1 0
0 1 1 0..
Page 189
487
언어 L0이 어떤 TM Mi이 인식하는 언어, 즉 L0 = L(Mi)라 하자.
String wi를 Mi의 input로 두면 어떻게 될까? (Mi와 wi의 subscript가 같음에
주의하자.) wi L0이거나, 아니면 wi L0이다. 각 경우를 따져보자.
(1) wi L0일 경우: 이는 정의에 의하여 M[i, i] = 0를 뜻한다. 즉, Mi는
wi를 accept 하지 않는다는 뜻이다. 이는 wi L(Mi) = L0를 뜻하므로
모순이다.
(2) wi L0일 경우: 역시 정의에 의하여 M[i, i] = 1를 뜻한다. 즉, Mi는
wi를 accept 한다. 이는 wi L(Mi) = L0를 뜻하므로 역시 모순이다.
따라서 L0 = L(Mi)라는 가정, 즉 L0가 TM이 인식할 수 있는 언어라는 것은
참이 아니다. 따라서 L0는 type 0 (R.E.) 언어가 아니다.
형식언어 및 오토마타 체계 IIIEnumerable Languages
Page 190
488
L0의 complement 언어 L1 = {wi | M[i, i] = 1, i ≥ 0 }은 어떤 언어일까?
아래의 정리는 L1은, L0와 달리, TM이 인식할 수 있는 type 0 언어임을
보여준다.
정리 15.7 L1은 type 0 (R.E.) 언어이다.
형식언어 및 오토마타 체계 IIIEnumerable Languages
L1 = { wi | M[i, i] = 1, i ≥ 0 }
= {w1, w3 . . .}
M0 M1 M2 M3 M4 . . .w0
w1
w2
w3
0
1
0
1
1 0 1 1
1 0 0 1
1 0 1 0
0 1 1 0..
증명. L1을 인식하는 TM MD를 만든다. MD는 모든 TM을 나열하는
enumerator와 Σ* 내의 string을 나열하는 enumerator를 가지고
다음과 같이 L1을 인식한다.
Page 191
489
TM enumerator
Σ*
enumerator
MD
Mi
wi
x
Input tape
형식언어 및 오토마타 체계 IIIEnumerable Languages
MD는 M0, w0, M1, w1, . . . ,와 같이 차례로 TM과 string을
enumerate 하며 input string x와 같은 string wi가 생성될 때까지
계속한다. wi = x이면, MD는 enumeration을 멈추고 input x를
입력으로 Mi simulate 한다. Mi가 x를 accept 하면 MD도 x를 accept
한다. MD는 L1을 인식하는 TM이다. 따라서 L1은 type 0 (R.E.)
언어이다.
Page 192
490
형식언어 및 오토마타 체계 IIIEnumerable Languages
L1의 complement는 L0이므로 다음 주장은 참이다.
따름정리(corollary). Type 0 언어의 보(complement)언어는 type 0
언어가 아닐 수도 있다.
Job Applicant Bloopers
Interviewer: “Do you think you can handle a variety of tasks?”
Applicant: “I should say so. I‟ve had nine totally different jobs in the past five months.”
- Jim -
쉬어 가기
Page 193
491
우리가 정의한 TM은 input string을 accept 하지 않을 때 정지해야
한다는 조건이 없다. Accept 하지 않고 무한 loop를 돌거나, non-
accepting state에 머물러 있을 수도 있다는 뜻이다. 물론 비정상적인
상태, 예를 들면, input alphabet에 없는 문자를 읽을 경우가 발생하면
dead state에서 끝난다. (편의상 이러한 non-accepting state로 가는
transition을 표현하지 않기로 하였음을 기억하자.) TM이 무한 loop에
들어가 input를 accept 하지 않을 때, 사용자에게 이런 상황을
알려줄 수 없다.
15.4 Recursive Languages
형식언어 및 오토마타 체계 III
Page 194
492
형식언어 및 오토마타 체계 IIIRecursive 언어
아래 그림과 같이 Input를 accept 하든, reject 하든 작업이 끝나면
정지하도록 TM을 정의하면 어떨까? 이러한 TM은 user-friendly 한
automata라 할 수 있다. 왜냐하면, 사용자는 TM이 어떤 상태에서
정지할 것인지 알 수 있으므로, 일을 마치기 전에 친절한 message,
예를 들면, “Accept 합니다.” 혹은, “Reject 합니다.”라고 출력하게
만들 수 있기 때문이다. 이런 TM을 recursive TM이라 한다.
Recursive TM은 일반 TM에 보다 언어 인식 능력이 낮다.
Reject and halt
Accept and halt
(a, b, N)
(c, a, N)
Recursive TM
Page 195
493
정의 15.3 (Recursive TM, Recursive Language). 주어진 입력을 처리한
후 항상 정지하는 TM을 recursive TM이라 하며, 이러한 TM이
인식하는 언어를 recursive language라 한다.
형식언어 및 오토마타 체계 IIIRecursive 언어
증명. 임의의 recursive 언어 L을 인식하는 recursive TM을 M이라 하자.
M의 transition graph에서 accept 하여 정지하는 state를 reject 하고
정지하는 state로, reject하고 정지하는 state를 accept 하고 정지하는
state로 바꾼다.이렇게 수정한 TM은 L의 complement 언어를 인식하는
recursive TM이다.
Type 0 언어와 달리, recursive 언어의 complement도 recursive
언어임을 다음의 정리가 보여준다.
정리 15.8 Recursive 언어의 complement 언어도 recursive 언어이다.
Page 196
494
Recursive language class(모음)을 Type-Rec라 표기하기로 하자. 앞서
증명한 정리 15.7의 따름 정리와 정리 15.8에 의하여 다음 정리를
얻는다.
Recursive Languages 형식언어 및 오토마타 체계 III
Type-RecType-0L
정리 15.9 Type-Rec는 type 0 language class Type-0L의 진 부분집합
(proper subset)이다.
Page 197
495
이제, context sensitive language (CSL)의 위치를 검토하여 보기로 하자.
아래의 정리 15.10은 모든 CSL는 recursive 언어임을 보여준다. 이
정리와 앞서 증명한 정리 15.9에 의하여, CSL class는 Type 0 class의
진 부분 집합(proper subset), 즉 Type-1L Type-0L라는 결과를 얻는다.
x
GTM M
Recursive Languages 형식언어 및 오토마타 체계 III
정리 15.10 모든 CSL는 recursive 언어이다.
증명. 임의의 CSG G = (VT, VN, P, S)가 주어졌다 하자. 언어 L(G)을
인식하는 recursive TM M을 아래 그림과 같이 만든다. M의 tape는 두
개의 track을 가지고 있으며, finite state control 내에 grammar G를 look-up
table로 저장하여 이용한다.
Page 198
496
x
S w1 w2 . . .
G
Recursive TM M
M은 둘째 track에 G의 시작 기호 S로 시작하여 rule을 반복 적용하며
생성되는 string wi를 나열한다. 적용할 rule을 선택할 필요가 있으면 (예:
A aA |BC), 그 중 하나를 nondeterministic 하게 선택하여 적용한다. 이
과정을 아래 (1) - (3) 가운데 한 조건이 만족할 때까지 계속한다.
(1) wi = x (2) wi = wj, i < j
(3) (|wi| > |x|) OR (wi (VT)+ AND wi ≠ x)
(1) 번 경우이면 accept하여 정지하고, (2) 번의 경우, 생성과정이 무한
loop에 들어가 x를 발생할 수 없으므로 reject 하여 정지한다. (3) 번은
context sensitive rule의 non-contracting 특성 때문에, x와 같은 string을
생성할 수 없으므로 reject 하여 정지 한다. 따라서 M은 L(G)를 인식하는
recursive TM 이다. 즉, 모든 CSL는 recursive 언어이다.
Recursive Languages 형식언어 및 오토마타 체계 III
Page 199
497
모든 CSL는 recursive 언어라면, 역으로 모든 recursive 언어는 CSL
인가? 다시 말하면, recursive TM이 인식하는 언어는 LBA에 의하여도
인식할 수 있는가? 다음 정리는 이 질문의 답이 부정적임을 보여준다.
정리 15.11 Recursive 언어 가운데 CSL 언어가 아닌 것이 있다.
Recursive Languages 형식언어 및 오토마타 체계 III
증명. Terminal alphabet VT = {a, b}을 쓰는 모든 CSG를 고려하자.
TM을 enumerate 할 때와 같은 방법을 적용하면, VT를 쓰는 모든
CSG를 enumerate 할 수 있다. 이들을 아래 그림과 같이 matrix M의
횡축에 나열하고, {a, b}*에 있는 모든 string을 종축에 나열한다.
G0 G1 G2 G3 G4 . . .w0
w1
w2
w3
w4
0 1 1 1 0
1 0 0 0 01 0 0 1
0 0 1 1 11 1 1 0 0
1
.
.
Page 200
498
L0 = { wi | M[i, i] = 0, i ≥ 0 }
= { w0, w2, w4, , , , }
Matrix 내용으로 i번째 string wi를 binary encoding 한 E(wi)를 j번째 CSG가
발생하는 string이면 M[i, j] = 1, 그렇지 않으면 M[i, j] = 0가 되도록 한다.
이제, 그림과 같이 matrix M의 대각선을 따라가며, 모든 i에 대하여,
wi L(Gi)인 조건 (즉, M[i, i] = 0)을 만족하는 string wi를 모아 만든
언어를 L0라 하고, 이 언어가 갖는 특성을 알아보자.
Recursive Languages 형식언어 및 오토마타 체계 III
G0 G1 G2 G3 G4 . . .w0
w1
w2
w3
w4
0 1 1 1 0
1 0 0 0 01 0 0 1
0 0 1 1 11 1 1 0 0
1
.
.
Page 201
499
Recursive Languages 형식언어 및 오토마타 체계 III
먼저, L0을 인식하는 recursive TM M0을 만들어, L0가 recursive
언어임을 증명한다. (증명은 정리 15.7의 것과 매우 유하다.) M0은 아래
그림과 같이 CSG와 언어 Σ*를 각각 나열하는 두 enumerator를 갖고
있다. M0는 G0, w0, G1, w1, . . . , Gi, wi와 같이 CSG와 string을 번갈아
가며, wi가 input string x와 같을 때까지, enumeration을 계속한다. 이
시점에서 M0는 Gi가 input x를 생성할 수 있는지 검사한다 (검사 방법은
정리 15.10의 증명 참조).
CSG enumerator
Σ*
enumerator
M0
Gi
x
wi
Page 202
500
이제 L0는 CSL가 아니라는 것을 증명한다. 증명은 type 0 언어가
아닌 언어가 있음을 보일 때 이용한 논리를 적용한다 (정리 15.3 증명
참조). L0를 발생하는 CSG Gi가 있다 하자. 같은 index를 가진 string
wi는 언어 L0 내에 있거나, 없다. 각 경우를 분석하여 보자.
(1) wi L0일 때: 이는 정의에 의하여 M[i, i] = 0를 뜻한다. 이는
wi L(Gi) = L0를 뜻하므로 모순이다.
(2) wi L0일 때: 역시 정의에 의하여 M[i, i] = 1를 뜻한다. 이는
wi L(Gi) = L0를 뜻하므로 역시 모순이다.
따라서, L0가 CSG Gi가 발생하는 언어라는 가정은 잘못이다. 따라서
L0는 CSL이 아니다.
Recursive Languages 형식언어 및 오토마타 체계 III
CSG Gi가 x를 생성할 수 있으면, M0는 input x를 reject 하여 정지하고,
그렇지 않으면 , accept 하여 정지한다 . M0는 L0를 인식하는
recursive TM이다. 따라서 L0은 recursive 언어이다.
Page 203
501
이 장에서 우리는 TM이 인식할 수 없는 언어, 입력을 인식한 후
항상 정지하는 recursive TM과 이들이 인식하는 언어를 추가로
도입하고 Chomsky 언어체계 내에 이들의 위치를 밝혔다. 다음
쪽의 표는 이를 종합한 결과를 보여준다. (표의 빨간색 화살표는
이미 증명한 포함관계()와 특성화 관계()를 나타낸다.
Recursive Languages 형식언어 및 오토마타 체계 III
Secrets of Success
The other day I had the opportunity to drop by my department head's office. He's a friendly guy and on the rare
opportunities that I have to pay him a visit, we have had enjoyable conversations. While I was in his office
yesterday I asked him, "Sir, What is the secret of your success?"
He said, "Two words."
"And, Sir, what are they?"
"Right decisions."
"But how do you make right decisions?"
"One word." He responded.
"And, sir, What is that?"
"Experience."
"And how do you get Experience?"
"Two words."
"And, Sir, what are they?"
"Wrong decisions."
- Rubin -
쉬어 가기
Page 204
502
Chomsky Hierarchy
Recursively
Enumerable
Sets (type 0)
Turing
Machines
Regular
Expression
Context-sensitive
Languages(type 1)
Context-free
Languages(type 2)
Regular
Languages(type3)
Linear-bounded
Automata
Pushdown
Automata
Finite State
Automata
Languages Automata
Recursive
Languages
Recursive
Turing Machines
형식언어 및 오토마타 체계 III
Page 205
503
이제 마지막으로 Chomsky 체계의 특성화 관계 중에 증명하지
않았던 부분, 즉 type 0(unrestricted), context-sensitive, context-free
grammar와 이들이 발생하는 언어를 인식하는 계산 model인 TM, LBA,
그리고 PDA 사이의 특성화 관계를 증명하기로 한다. (Recursive TM이
인식하는 recursive 언어만을 발생하는 grammar model은 어떤 것인지
알려진 바 없다. 따라서 이 부분은 증명에서 제외한다.)
15.5 Characterization 증명
Type 0 Grammar 와 TM
형식언어 및 오토마타 체계 III
정리 15.12 (1) Type 0 grammar가 발생하는 언어는 TM이 인식할 수 있다.
(2) TM이 인식하는 언어는 type 0 grammar가 발생할 수 있다.
Page 206
504
증명 (1). Type 0 grammar G가 주어졌다 하자. L(G)를 인식하는 TM M을
다음과 같이 만든다. M은 다음 쪽의 그림과 같이 input tape와 work
tape를 갖고 있으며, grammar G는 look-up table 형식으로 finite state
control에 저장하고 있다. (G의 크기는 유한하므로 TM의 finite state
control에 두는 것이 가능하다.) 편의상, grammar rule의 좌측을 1, 2, . . ,
n, 그리고 rule i의 우측에 있는 string을 i1, i2 , . . , ik라 표기하기로
한다. 다시 말하면, i i1 | i2 |, . . , | ik.
다음 쪽의 그림과같이 M의 input tape에 string x가 주어졌다 하자.
M은 시작기호 S를 work tape에 쓰고, G의 rule을 적용하여 x를 derive
할 수 있으면, input string을 accept 한다. 현재 work tape에 derive 한
string을 w라 하자. M은 w를 좌측에서 우측으로 읽으며, rule의 좌측 i이
있으면, 이를 선택할지를 nondeterministic 하게 결정한다.
형식언어 및 오토마타 체계 IIIType 0 Grammar TM
Page 207
505
Type 0 Grammar TM
Rule i를 선택했다면, rule의 우측 ij를 nondeterministic 하게 선택하여
tape에 i 대신 쓴다. M은 w가 input x와 같아 accept 할 때까지 이 과정을
반복한다. 만일 x L(G)이면, 유한한 시간에 M은 x와 같은 string을
work tape에 발생하고 input string x를 accept 할 것이다. (Grammar G가
x를 derive 할 수 없다면, M은 적용할 rule이 없어, non-accepting
상태에서 정지하거나, derivation을 무한히 계속한다.) 따라서 type 0
grammar G가 발생하는 언어는 TM이 인식할 수 있다. 즉, L(G) = L(M).
형식언어 및 오토마타 체계 III
G
x
S
work tape G
x
x
G
x
i
?G
x
ij
Page 208
506
증명 (2). 임의의 TM M = (Q, Σ, , q0, , F)이 주어졌을 때 L(M)을
생성하는 type 0 grammar를 만든다. Q ={q0, q1, . . , qn}, qf F라 하고,
#와 $는 에 없는 새로운 기호라 하자.
Grammar G는 다음의 세 절차에 의하여 L(M)을 생성한다. (1) x#q0x$를
생성한다. 단, x Σ*. (2) M의 start state q0로 시작하여 생성한 string의
우측에 있는 string x를 input로 M를 simulate 한다. M이 accept state qf에
들어가면, (3) 왼편 string x만 남겨두고, string의 다른 부분을 모두
지워버린다. 첫 단계에서 만든 string에 x를 두 개 만들어 둔 것은 하나는
simulation에 , 다른 것은 simulation 후 M이 x를 accept 하면 ,
x를 생성하려는 것이다. (아래 그림에서 state qi를 대문자 Qi로 쓴
것은 grammar에서 nonterminal 기호를 대문자로 쓰기로 한 관례에
따른 것이며, uv는 M이 accepting 상태에 있을 때 tape의 내용이다.)
Type 0 Grammar TM
S . . . x#Q0x$ . . . . x#uQfv$ . . . . x(1) (2) (3)
형식언어 및 오토마타 체계 III
Page 209
507
Type 0 Grammar TM
Type 0 grammar로 위의 세 과정을 이행하는 것은 어렵지 않다. Input
alphabet을 Σ = {a1, a2, . . ., ak}, 그리고 b, c를 임의의 두 tape 기호, 즉 b, c
라 하자. 아래의 그림은 단계 (1)을 이행하는 데 필요한 rule들을 모아
놓은 것이다. (Rule에 있는 nonterminal 기호 Qi는 M의 state qi에
해당한다.) 이 rule들을 가지고 모든 x Σ*에 대하여 string x#Q0x$을
발생할 수 있다.
형식언어 및 오토마타 체계 III
S A$
A a1Aa1 | a2Aa2 | . . .
|akAak |#Q0
(1)
S . . . x#Q0x$
S . . . x#Q0x$ . . . . x#uQfv$ . . . . x(1) (2) (3)
Page 210
508
Type 0 Grammar TM
이제 단계 (2)의 simulation을 위하여 G가 발생한 string과 M의 현 상황
(configuration)을 아래의 그림이 예시하는 것 같이 대응시키기로 하자.
G가 생성한 string에 Qi가 있고 그 우측에 a가 있으면, TM M은 상태
qi에서 tape 기호 a를 읽는다는 뜻이다.
형식언어 및 오토마타 체계 III
. . . aQib . . . . . . . .a b
qi
. . . Qi# . . . . .a b
qi
. .a b
qi
. . . #Qia . . .
. . . bQi$ . . . a b
qi
. . .
S . . . x#Q0x$ . . . . x#uQfv$(2)(1)
Page 211
509
Type 0 Grammar TM
G의 rule은 M의 에 따라 아래 그림의 (a)와 같이 만든다. 단, B
(blank)를 읽어 쓰는 transition은, (b)와 같이, B가 tape 내용의 우측 끝에
있는 것인지, 좌측 끝에 있는 것인지에 따라, $ 또는 #를 이용하여
적절한 rule을 선택하여 적용한다.
(a) (qi, a) = (qj, b, D), G의 rule (단 a , c {#, $} )
D = R 이면, cQia cbQj
D = L 이면, cQia Qjcb
D = N 이면 cQia cQjb
(b) (qi, B) = (qj, b, D), G의 rule (단 c )
D = R 이면, Qi# #bQj Qi$ bQj$
D = L 이면, Qi# Qj#b cQi$ Qjcb$
D = N 이면 Qi# #Qjb Qi$ Qjb$
형식언어 및 오토마타 체계 III
Page 212
510
Type 0 Grammar TM
이제, 마지막 단계 (3), 즉 M이 accepting state qf에 있을 때, G가 생성한
string (즉, sentential form)의 좌측에 있는 x, 즉 M의 input string만
남겨놓는 rule을 다음과 같이 만든다.
아래 그림의 (a)에 있는 rule은 Qf를 오른쪽으로 $를 만날 때까지
옮기고, (b)에 있는 rule은 Qf를 QE로 바꾼 후, 왼쪽으로 옮기며, #를
만날 때까지, 만나는 모든 문자를 지운다. (그림에서, a .)
(a) Qf# #Qf Qfa aQf
(b) Qf$ QE aQE QE #QE
형식언어 및 오토마타 체계 III
S . . . x#Q0x$ . . . . x#uQfv$ . . . . x(1) (2) (3)
지금까지 만든 G의 rule에 따라, x L(G) x M(x)임을 알 수 있다.
즉, L(G) = L(M).
Page 213
511
정리 15.13 (1) CSG가 발생하는 언어는 LBA에 의하여 인식할 수 있다.
(2) LBA가 인식하는 언어는 CSG에 의하여 발생할 수 있다.
이제, 언어 체계에서 한 단계 내려와, CSG와 automata LBA 사이의
characterization 관계를 증명한다. 증명은 type 0 grammar와 TM 사이의
관계를 증명할 때와 같다. 단, LBA는 tape head가 input 영역을 넘을 수
없다는 것과, CSG rule의 좌편이 우편보다 길 수 없다는 non-
contracting 조건 (단, S 은 예외)을 고려해야 하는 것이 다르다.
CSG와 LBA
형식언어 및 오토마타 체계 III
증명 (1). 정리 15.12 (1)의 증명과 같은 방법으로 CSG G의 언어를
인식하는 LBA M을 만든다. 단, 현재 work tape에 있는 sentential form이
input x보다 길면 input를 reject 한다. 그리고 input가 [] (즉, x = )이고
G가 rule S 을 가지고 있으면, M은 accepting state에 들어간다.
Page 214
512
CSG LBA
증명 (2). 증명은, CSG rule의 non-contracting 조건 때문에, 아래의
3단계로 TM이 인식하는 언어를 생성하는 type 0 grammar rule을 만드는
방법 (다음 그림)을 그대로 적용할 수 없다. 여기에 쓰는 rule을 보면,
string 생성하고 TM을 simulation 하는 단계 (1)과 (2)에 쓰는 rule들은 non-
contracting 하는 것이다. (정리 15.2, 증명 (2) 참조.)
(a) Qf# #Qf Qfa aQf
(b) Qf$ QE aQE QE #QE
형식언어 및 오토마타 체계 III
그러나 단계 (3)에서 input string만 남기는 rule (아래의 (b)부분)은 모두
contracting 하는 것이므로 CSG rule로 쓸 수 없다.
S . . . x#Q0x$ . . . . x#uQfv$ . . . . x(1) (2) (3)
Page 215
513
이 문제를 해결하려고 다음과 같은 아이디어를 쓴다. LBA M의 input
alphabet을 라 하고, x +에 대하여 x = x1x2 . . . xn (n 1)라 하자.
(편의상 x = 인 경우는 증명의 끝에 별도로 다룬다.) CSG G는 M을
simulate 하기 전 단계 (1)에서, x#Q0x$ 대신, 아래와 같은 string을 derive
한다. Q0의 우측에 input string x의 각 문자 쌍으로 된 복합문자열이
있다. 꺾임 괄호 <…> 와 소괄호 (. . .) 내에 있는 것은 모두 복합기호이며,
„[„ 와 ‘]‟는 LBA의 input 양단에 두는 delimiter (경계기호)이다.
CSG LBA 형식언어 및 오토마타 체계 III
단계 (2)에서 G는 위의 string의 각 복합문자의 우측 요소들로 구성된
string [x1x2 . . . xn]를 input로 M을 simulate 하다가 accept 하면, 단계
(3)에서 좌측 요소들로 구성된 원래의 input string만 남기고 모든 기호를
지운다. 이 과정은 non-contracting rule로 가능하다.
S . . . Q0<x1, ([, x1)><x2, x2> . . . . <xn, (xn, ])> . . . .(1) (2)
Page 216
514
(a) S A<a1, (a1, ])> | A<a2, (a2, ])> | . . . | A<ak, (ak, ])>
(b) | Q0<a1, ([, a1, ])> | Q0<a2, ([, a2, ])> | . . . | Q0<ak, ([, ak, ])>
(c) A A<a1, a1> | A<a2, a2> | . . . | A<ak, ak>
(d) | Q0<a1, ([, a1)> | Q0<a2, ([, a2)> | . . . | Q0<ak, ([, ak)>
CSG LBA
단계 (1)을 실현하는 G의 rule은 다음과 같다. 특히 (b) 번 줄의 rule은
input가 하나의 문자만 있을 때에 해당한다.
형식언어 및 오토마타 체계 III
S . . . Q0<x1, ([, x1)><x2, x2> . . . . <xn, (xn, ])> . . . .(1) (2)
Page 217
515
CSG LBA
CSG G의 sentential form의 주요 context와 LBA의 현 상황 (configuration)
사이에는 다음과 같은 관계가 있다.
<xi, a>Qi<xi+1,b>
. . . . .a b
qi
Qi<x1,([,a)>
Qi<x1, ([,],a)>
. .a
qi
[
a
qi
]. . . a
qi
[ ]
Qi<x1,(a,[)>
. .a
qi
[
Qi<xn, (a,])>
Qi<xn,(],a)>
a
qi
]. . .
Qi<x1, ([, a, ])>
a
qi
[ ]
Qi<x1, (],a,[)>
a
qi
[ ]
형식언어 및 오토마타 체계 III
Page 218
516
CSG LBA
이제, G가 LBA M을 simulate하는 rule을, type 0 grammar와 같은
원리로, 아래와 같이 만든다. (앞쪽이 보여주는 G가 생성하는 string의
context와 M의 configuration 사이의 관계를 참조하기 바란다. M은
복합기호의 가장 우측 문자를 읽는다는 것을 기억하자.)
M의 transition G의 rule ( a, b Σ, c, d, e )
(qi, d) = (qj, e, D)
D = R 이면
<a, c>Qi<b, d> <a, c><b, e>Qj
<a, c>Qi<b, (], d)> <a, c>Qi<b, (e, ])>
Qi<a, ([, ], d)> Qi<a, ([, e, ])>
(qi, d) = (qj, e, D)
D = N 이면
(qi, d) = (qj, e, D)
D = L 이면
<a, c>Qi<b, d> <a, c>Qi<b, e>
Qi<a, ([, ], d)> Qi<a, ([, ], e)>
<a, c>Qi<b, d> Qj<a, c><b, e>
<a, c>Qi<b, (], d)> <a, c>Qi<b, (e, ])>
Qi<a, ([, ], d)> Qi<a, (], e, [)>
형식언어 및 오토마타 체계 III
Page 219
517
M의 transition G의 rule ( a, b Σ, c, d, e )
(qi, ]) = (qj, ], L)
(qi, [) = (qj, [, R)
Qi<a, (c, ])> Qi<a, (], c)>
Qi<a, ([, c, ])> Qi<a, ([, ], c)>
Qi<b, (c, [)> Qi<b, ([, c)>
Qi<a, (], c, [)> Qi<a, ([, ], c)>
M은 boundary marker „[„ 또는 ‘]‟를 읽으면, string 쪽으로 움직이므로
다음과 같은 rule을 추가한다.
CSG LBA형식언어 및 오토마타 체계 III
Page 220
518
CSG LBA
G는 simulate 하다가, M이 accepting state qf에 들어가면, 단계 (3)에서
아래의 rule을 써서 input string x만 남겨 놓고 simulation 부산물로 생긴
문자들을 지운다. (이곳의 모든 rule도 non-contracting 조건을 만족하고
있다. (복합문자는 실제로 한 개의 문자이지만 이해를 돕고자 여러 개의
문자를 묶어 표현할 뿐이다. (1.1절의 표기 관례 참조))
아래의 rule에서 a, b Σ, c, d 라 하자. Rule (a)는 Qf를 우측 끝으로
계속 보내고, rule (b)는 input의 우측 끝 문자를 뽑아 내고, rule (c), (d)는
좌측으로 가며 복합문자의 왼쪽 문자들을 모아 input string x를 만든다.
Rule (e)는 input string에 하나의 기호만 있을 때 적용한다.
(a) Qf<a, c> <a, c>Qf (b) Qf<a, (c,])> a
(c) <b, c>a ba (d) <b, ([, c}>a ba
(e) Qf<a, ([, c, ])> a
형식언어 및 오토마타 체계 III
Page 221
519
CSG LBA형식언어 및 오토마타 체계 III
지금까지 마든 CSG는 input string이 non-null, 즉 x +일 때다. 이제,
마지막으로 input string x = 일 때, 즉 input tape에 좌우 경계기호
(delimiter) []만 있을 때, M이 x를 accept 하면, G에 rule S 를
추가하면 된다. 이 경우, M이 읽고 쓸 수 있는 영역이 없으므로, 두
경계기호를 읽고 accept 할지는 M의 transition 함수 (또는 graph)을 보고
알 수 있다. (M이 쓸 수 있는 tape의 영역은 input string x의 길이보다 클
수 없다는 LBA의 제한조건을 기억하자.)
Memories
Two very elderly ladies were enjoying the sunshine on a park bench in Miami. They had been meeting at the park
every sunny day, for over 12 years, chatting, and enjoying each others friendship. One day, the younger of the two
ladies, turns to the other and says, “Please don't be angry with me dear, but I am embarrassed, after all these years...
What is your name ? I am trying to remember, but I just can't.”
The older friend stares at her, looking very distressed, says nothing for 2 full minutes, and finally with tearful
eyes, says, “How soon do you have to know ?”
- overheard by Rubin -
쉬어 가기
Page 222
520
정리 15.14 (1) CFG가 발생하는 언어는 PDA가 인식할 수 있다.
(2) PDA가 인식하는 언어는 CFG에 의하여 발생할 수 있다.
증명 (1). 이 부분의 증명은 다른 automata의 경우와 같이 nondeterministic
연산 개념에 익숙해 있다면, 쉽게 이해할 수 있다. CFG G가 주어졌다
하자. L(G)를 인식하는 NPDA M을 다음과 같이 만든다. M은 우선 G의
start symbol S를 stack에 넣은 다음 아래의 작업을 stack이 빌 때, 즉 stack
상단에 Z0가 나타날 때까지 진행한다. 기호 A를 임의의 nonterminal
기호라 하고, A의 rule이 A 1 | 2 |, . . ., | k와 같이 주어졌다 하자.
(a) Sack 상단에 A가 있으면, A의 production rule의 우측 i, 1 i k를
nondeterministic 하게 선택하여 A 대신 i를 stack에 push 한다.
CFG와 PDA
이제, 마지막으로 PDA와 CFG 사이의 characterization 관계를
증명함으로 Chomsky Hierarchy의 증명을 마무리한다.
형식언어 및 오토마타 체계 III
Page 223
521
G: S aBC B bBc | bc
C bCc |
L(G) = {abncnbmcm | n ≥ 1, m ≥ 0 }
CFG PDA 형식언어 및 오토마타 체계 III
(b) Stack 상단에 terminal 기호, 예를 들어 a가 있으면, input tape를 읽고
a와 같으면, stack 상단이 a를 pop하고, 다르면 input string을 reject 한다.
(c) Stack 상단에 바닥기호 Z0가 나타나면, accept 상태에 들어간다.
예: 아래와 같은 CFG G가 주어졌을 때, L(G)를 인식하는 NPDA는 그림과
같이 만들 수 있다. 임의의 CFG G가 주어졌을 때, 같은 방법으로, 3개의
state만 가지고 L(G)를 인식하는 NPDA를 만들 수 있다.
(, S/aBC), (a, a/ ), (c , c/ )
(, B/bBc), (, B/bc), (b, b/)
(, C/bCc), (, C/),
1
2
(, Z0/SZ0)
(, Z0/Z0)
start
Page 224
522
CFG PDA
증명 (2). 이 증명은 4종의 automata와 grammar 사이의 특성화
(characterization) 관계 증명 가운데 가장 까다로운 부분이다. 그러나
증명이 제시하는 기본 개념을 이해한다면, 그리 난해한 증명이
아니며, 도전해 볼만한 가치가 있다. 증명은 다른 model이 경우와
같이 임의의 PDA M이 있을 때, L(M)을 발생하는 CFG를 만드는
algorithm을 보여 주는 것이다. 이 증명에서 PDA는 다음과 같은
model로 제한한다.
(a) Input는 empty stack에 의하여 accept한다.
(b) Stack operation은 push 또는 pop만 하며, push 할 때는 정확히 한
개의문자만 push 할 수 있다. (이 조건에 의하여 (p, a, A) = (q, B)와
같이 stack 상단의 기호를 바꾸는 operation은 없다는 것에 유의하자.)
조건 (a), 즉 empty stack에 의하여 accept 하는 PDA model과 accepting
상태로 accept 하는 model은 언어인식 능력에 차이가 없음을 6.3절
(여러 형태의 automata)에서 증명하였다.
형식언어 및 오토마타 체계 III
Page 225
523
(a, Z0/AaBZ0)
(, A/B)
(a)
(a, Z0/BZ0)
(, A/XB) (, X/)
(, B/aB)
(, a/Aa)
(b)
앞서 제시한 조건 (b)도 PDA의 언어인식 능력에 영향을 주지 않음을
쉽게 증명할 수 있다. 예를 들면, 아래 그림 (a)와 같이 조건 (2)를
만족하지 않는 transition이 있다면, 그림 (b)와 같이 state를 추가하여
조건에 맞도록 변환할 수 있다. 이러한 변환은 인식하는 언어에 영향을
주지 않음을 알 수 있다.
일단 stack을 비우고 나면 PDA는 멈춘다. 따라서 stack을 비우며
들어가는 state는 하나만 있다고 가정한다. (그러한 state가 여러 개
있으면 하나로 통합하면 된다.)
CFG PDA 형식언어 및 오토마타 체계 III
Page 226
524
CFG PDA
Z0 . . . BA
p
(a)
q
Z0 . . . B
x
(b)
PDA M이 아래 그림과 같이 어떤 state p에서 stack 상단에 A를 갖고
있다 하자. 이 상태에서 M이 동작하다가 A의 바로 밑에 있는 stack 기호
(예를 들면, 그림의 B)가 처음으로 stack 상단에 나타날 때 (그러나 M이
B를 아직 읽기 전)의 state를 q라 하자. 이 기간에 M이 input에서 읽을 수
있는 string의 집합을 stack-top erasing set (STES)라 하고, [p, A, q]라
표기하기로 한다. State p에서 state q로 가는 transition 경로가 없으면, [p,
A, q]는 empty set이다. 일반적으로 B가 stack top에 나타날 때까지
stack의 높이가 여러 번 바뀔 수 있음에 유의하자.
[p, A, q] = {x, y, . . }
(c)
형식언어 및 오토마타 체계 III
Page 227
525
CFG PDA
아래의 그림 (b)는 그림 (a)에 있는 PDA의 모든 STES를 보여준다.
여기에 적혀있지 않은 STES, 예를 들면, [2, A, 5], [1, Z0, 3] 등은 모두
공집합이다.
[5, a, 6] = {b}
[6, A, 7] = {b}
[7, Z0, 4] = {}
[2, A, 7] = {ab}
[2, A, 3] = {b}
[1, Z0, 4] = {aabb, ab}
(b)(a)
52
3
4
7
6
1
(a, Z0/AZ0)
(a, A/aA)(b, a/)
(b, A/)
(, Z0/ )
(, Z0/ )
(b, A/ )
형식언어 및 오토마타 체계 III
Page 228
526
CFG PDA
VT = , VN = { [p, A, q] | p, q Q, A } {S}. 즉, S와 M의 STES를
표현하는 복합기호를 가지고 nonterminal alphabet를 만든다.
(1) M이 stack을 비우고 (즉, Z0를 pop) state t에 들어가면, rule
집합 P에 rule S [q0, Z0, t]를 둔다.
(2) 임의의 p, q Q, A 에 대하여, nonterminal [p, A, q]을 가진 rule이
P에 추가되었다 하자. (추가한 rule이 없으면 algorithm은 끝난다.)
임의의 , a { }, r Q, 그리고 B, C 에 대하여,
(a) (p, a, A) = (r, BC)이면, 각 s Q에 대하여 다음 rule을 P에 둔다.
[p, A, q] a[r, B, s][s, C, q]
(b) (p, a, A) = (q, )이면, rule [p, A, q] a를 P에 둔다.
형식언어 및 오토마타 체계 III
Empty stack에 의하여 input를 accept하고, push 할 때 stack 높이가 1
증가하는 PDA M = (Q, , , , q0, Z0, )이 있다 하자. L(M)을 발생하는
CFG G = (VT, VN, S, P)를 만드는 algorithm은 다음과 같다.
Page 229
527
[p, A, q] . . . . x
(b) G의 derivation
x [p, A, q]
(a) M의 STES
CFG PDA 형식언어 및 오토마타 체계 III
PDA M에서 string x[p, A, q]이면, M을 가지고 만든 CFG G의 rule은
그림과 같이 nonterminal [p, A, q]을 기점으로 string x를 derive 할 수
있게 하였다. 어떻게 이것이 가능할까?
정의에 따라, STES [q0, Z0, t]는 M이 시작 state에서 시작하여 stack를
비울 때까지 읽은 모든 string을 포함하므로, L(M) = [q0, Z0, t]이다.
따라서, G는 nontermial [q0, Z0, t]로 시작하여 L(M)을 발생할 수 있어야
한다. 관례상 S를 시작기호로 쓰기로 했으므로, algorithm은 단계 (1)에서
rule S [q0, Z0, t]을 넣고, 단계 (2)에서 nonterminal 기호 [q0, Z0, t]을
기점으로 L(M)의 모든 string을 derive 할 수 있게 rule을 추가한다.
Page 230
528
CFG PDA 형식언어 및 오토마타 체계 III
이제, algorithm이 단계 (2)에서 어떻게 M이 인식하는 언어를 derive
하는 rule을 만드는지 알아보자. STES [p, A, q]는 정의한 바와 같이
M이 stack 상단에 A가 있고 state가 p인 상황에서 시작하여 state q에
진입하며 A의 바로 밑에 있는 기호 (예: 그림의 B)가 처음으로 stack
상단에 나타날 때까지 읽을 수 있는 input string의 집합이다.
만일 M이, 그림 (b)와 같이 (p, a, A) = (q, )에 따라, state p에서 바로
stack 상단에 있는 기호 A를 pop 하고 state q에 진입한다 하자. 정의에
따라, a [p, A, q]이며, G에 rule [p, A, q]a를 두어 a를 생성케 한다.
Z0 . . . .B
q
a
(a)
Z0 . . . .BA
p
a
(b)
p
q(a, A/)
Page 231
529
CFG PDA 형식언어 및 오토마타 체계 III
Z0 . . .BA
p
Z0 . . BCD
r1
a
마지막으로, 우리가 정의한 STES의 의미를 되새겨 보아, algorithm이
단계 (2) - (a)에서 무엇을 하는지 알아보자.
아래 그림과 같이 M이 pushing transition (p, a, A) = (r1, DC)을
이행했다 하자. (A가 C로 바뀌고 D를 push 했다.) M이 작동 중에 D의
밑에 있는 C가 처음으로 stack 상부에 나타났을 때의 state를 s1, 그리고
D의 밑에 있는(원래 A의 밑에 있었던) B가 처음으로 stack 상부에 나타날
때의 state를 q라 하자. STES [p, A, q]는 a[r1, D, s1][s1, C, q]에 있는 모든
string (예: axy)을 포함한다. 즉, [p, A, q] a[r1, D, s1][s1, C, q].
Z0 . . . .B
q
a x y
Z0 . . BC
s1
a x
Page 232
530
앞서 얻은 포함관계는 아래 그림이 보여주는 M의 state transition
graph을 가지고도 이해할 수 있다.
[p, A, q] (a[r1, D, s11][s11, C, q] a[r1, D, s12][s12, C, q] . . . )
Stack 기호 D의 밑에 있는 C를 처음 stack 상부로 나타날 때의 state (s1)는
그림과 같이 일반적으로 여러 개(s11, s12, …, s1i, . . .) 있을 수 있다.
(그림에서 state r1 및 s1i로부터 나가는 transition label에는 편의상 stack-top
기호만 표시했다.) 따라서, 다음과 같은 포함관계가 성립한다.
s12
(., D/..)
(. , C/. .)
pq
s11
r1
(a, A/DC)
(. , C/. .) (. , B/..)
(., D/..)
(. ./AB)
CFG PDA 형식언어 및 오토마타 체계 III
[p, A, q] a[r1, D, s1][s1, C, q].
Page 233
531
만일 (p, a1, A) = (r1, D1C1), (p, a2, A) = (r2, D2C2), 등과 같이 state
p에서 stack 상단에 A를 두고 stack을 pushing 하는 transition이 여러 개
있다면, 같은 원리로 STES [p, A, q]는 push 한 DiCi 밑의 기호 (예의 B)가
stack 상단에 처음으로 나타날 때까지 읽은 모든 input string 부분을
포함하고 있어야 한다. 따라서, 다음 식이 성립한다.
[p, A, q] a1[r1, D1, s11][s11, C1, q] a1[r1, D1, s12][s12, C1, q] . .
a2[r2, D2, s21][s21, C2, q] a2[r2, D2, s22][s22, C2, q] . . .
. . . . .
CFG PDA 형식언어 및 오토마타 체계 III
p
ri q(ai, A/DiCi)
(.. /AB)
(., Di /..)
sij(., Ci /..)
(., B/..)
Page 234
532
CFG PDA 형식언어 및 오토마타 체계 III
이제, state p 상에서 stack-top A를 pop 하는 transition (p, b1, A) = (q, ),
(p, b2, A) = (q, ), 등이 있다 하자. PDA M은 pushing과 popping만 할 수
있으므로 STES [p, A, q]는 다음과 같은 등식으로 표시할 수 있다.
[p, A, q] = a1[r1, D1, s11][s11, C1, q] a1[r1, D1, s12][s12, C1, q] . .
a2[r2, D2, s21][s21, C2, q] a2[r2, D2, s22][s22, C2, q] . . .
. . . .
{b1} {b2} . . .
M의 state 수가 n이고, state p에서 k1 개의 pushing transition, k2 개의
popping transition이 있다면, 위의 식은 다음과 같이 간단히 표현할 수 있다.
[p, A, q] = k1
i=1n
j=1( ai[ri, Di, sij][sij,Ci, q] )
k2
i=1bi ( )
Page 235
533
CFG PDA 형식언어 및 오토마타 체계 III
M의 STES [p, A, q]를 다음과 같은 식으로 표시할 수 있다고 하자.
STES[p, A, q]이 포함하고 있는 string을 G에서는 아래와 같은
rule로 생성하도록 하면 된다. 이것이 algorithm 단계 (2)가 하는 일이다.
[p, A, q] a1[r1, D1, s11][s11, C1, q] | a1[r1, D1, s12][s12, C1, q] | . .
| a2[r2, D2, s21][s21, C2, q] | a2[r2, D2, s22][s22, C2, q] |. . .
. . . .
| b1 | b2 | . . .
[p, A, q] = a1[r1, D1, s11][s11, C1, q] a1[r1, D1, s12][s12, C1, q] . .
a2[r2, D2, s21][s21, C2, q] a2[r2, D2, s22][s22, C2, q] . . .
. . . .
{b1} {b2} . . .
Page 236
534
CFG PDA
예 1. 그림 (a)의 PDA M이 인식하는 언어 L(M)을 생성하는 CFG는 그림
(b)와 같다. Grammar의 (1)번 rule은 algorithm의 단계 (1)을 따라 만든
것이며, (2) 번 rule은 단계 (2)-(a)에 의하여, 나머지 rule (3), (4)는 단계
(2)-(b)에 의하여 만든 것이다. L(M) = { aba } = L(G)임을 알 수 있다.
rp(a, Z0/AZ0)
q
s
(b, A/)
(a, Z0/)
(a) PDA M
(1) S [p, Z0, q]
(2) [p, Z0, q] a[r, A, s] [s, Z0, q]
(3) [r, A, s] b
(4) [s, Z0, q] a
(b) CFG G
형식언어 및 오토마타 체계 III
이제, algorithm을 적용하여 PDA M을 가지고 L(M)을 생성하는 CFG를
만드는 간단한 예를 들어 보자.
Page 237
예 2. 아래의 PDA는 예 1보다 다양한 transition을 갖고 있다. State
2에서 같은 stack-top 기호 A를 가지고 읽기도 하고, 읽지 않기도
하므로, 이 PDA는 NPDA이다.
535
CFG PDA
S [1, Z0, 4]
[1, Z0, 4] a[2, A, 7] [7, Z0, 4] | a[2, A, 3] [3, Z0, 4]
[2, A, 7] a[5, a, 6][6, A, 7]
[5, a, 6] b [6, A, 7] b [2, A, 3]
[7, Z0, 4] [3, Z0, 4] b
형식언어 및 오토마타 체계 III
L(M) = L(G)
= {aabb, ab }
52
34
7
6
1
(a, Z0/AZ0)(a, A/aA)
(b, A/)
(, Z0/ )(b, Z0/ )
(, A/ )
(b, a/)
start
Page 238
536
CFG PDA 형식언어 및 오토마타 체계 III
예 2에서 얻은 grammar는 rule이 많아 이해하기 어렵다. 우리가
10.2절에서 배운 -production rule과 unit production rule을 제거하는
기법을 적용하면 아래와 같이 간략한 grammar를 얻을 수 있다.
S [1, Z0, 4]
[1, Z0, 4] a[2, A, 7] [7, Z0, 4] | a[2, A, 3] [3, Z0, 4]
[2, A, 7] a[5, a, 6][6, A, 7]
[5, a, 6] b [6, A, 7] b [2, A, 3]
[7, Z0, 4] [3, Z0, 4] b
S aabb | ab
Page 239
537
CFG PDA
예 3. 아래 그림 (a)의 PDA는 우리가 자주 인용했던 언어 L = {aibi | i ≥
1 }을 인식한다. Algorithm을 적용하여 만든 그림 (b)의 CFG는 rule이
많아, 어떻게 L을 생성하는지 분명치 않다. 이 rule들을 다듬어 보자.
형식언어 및 오토마타 체계 III
1
2
4
(a, Z0/AZ0)
(a, A/AA)
(b, A/)3
(b, A/)
(, Z0/)
(a) PDA M(b) CFG G
(1) S [1, Z0, 4]
(2) [1, Z0, 4] a[2, A, 3][3, Z0, 4] |
a[2, A, 2][2, Z0, 4]
(3) [2, A, 4] a[2, A, 3][3, A, 4] |
a[2, A, 2][2, A, 4]
(4) [2, A, 3] a[2, A, 3][3, A, 3] |
a[2, A, 2][2, A, 3] | b
(5) [2, A, 2] (6) [3, A, 4]
(7) [3, A, 3] b (8) [3, Z0 , 4]
Page 240
538
CFG PDA 형식언어 및 오토마타 체계 III
Rule (5)와 (6)을 보자. STES [2, A, 2] = { } = (empty)이다. 왜냐하면,
state 2에서 M은 pushing만 하므로, 후에 state 2로 진입하며 현재 stack-top
기호 A의 밑에 있는 symbol을 stack-top에 오도록 할 수 없기 때문이다.
STES [3, A, 4] = { } = 이다. 왜냐하면, state 3에서 4로 가며 바닥 기호
(Z0)를 pop 했으므로 state 3에서 A의 밑에 있었던 기호가 state 4에서 stack
상부에 나타날 수 없기 때문이다.
1
2
4
(a, Z0/AZ0)
(a, A/AA)
(b, A/)3
(b, A/)
(, Z0/)
. . . .
(5) [2, A, 2] (6) [3, A, 4]
. . . .
Page 241
539
(b) CFG G
CFG PDA 형식언어 및 오토마타 체계 III
(1) S [1, Z0, 4]
(2) [1, Z0, 4] a[2, A, 3][3, Z0, 4]
(4) [2, A, 3] a[2, A, 3][3, A, 3] | b
(7) [3, A, 3] b (8) [3, Z0 , 4]
따라서, G의 nonterminal symbol [2, A, 2]과 [3, A, 4]는 아무 string도
생성할 수 없으므로 불필요하다. 이 두 symbol과 관련 rule들은 우리가
이미 10.3절에서 배운 algorithm을 이용하여 모두 제거할 수 있다. 이들을
제거하면 그림 (b)와 같은 비교적 간단한 grammar를 얻는다.
1
2
4
(a, Z0/AZ0)
(a, A/AA)
(b, A/)3
(b, A/)
(, Z0/)
(a) PDA M
Page 242
540
(1) S A
(2) A aBC
(4) B aBD | b
(7) D b (8) C
앞서 구한 grammar를 더 다듬어 보자. 우선 복합기호들을 단순 기호로
그림 (c)와 같이 대치한다. (복합기호는 모두 nonterminal임을 기억하자.)
그림 (c)의 grammar에서 10.1-2절에서 배운 unit production rule과 -
production rule을 제거하는 기법을 적용하면, 그림 (d)를 얻는다. 이
grammar가 발생하는 언어는 L = {aibi | i ≥ 1 }임을 알 수 있다.
(1) S [1, Z0, 4]
(2) [1, Z0, 4] a[2, A, 3][3, Z0, 4]
(4) [2, A, 3] a[2, A, 3][3, A, 3] | b
(7) [3, A, 3] b (8) [3, Z0 , 4]
(1) S aB
(4) B aBb | b
(b) (c)
(d)
CFG PDA 형식언어 및 오토마타 체계 III
Page 243
541
형식언어 및 오토마타 체계 III
Rumination: PDA를 가지고 CFG 만들기
(a) (p, a, A) = (r, BC)이면, 각 s Q에 대하여 다음 rule을 P에 둔다.
[p, A, q] a[r, B, s][s, C, q]
PDA M을 가지고 CFG를 만드는 algorithm의 단계 (2)-(a) (아래 그림 참조)는, M이 push 할 때마다, 각 state s Q에
대하여 rule [p, A, q] a[r, B, s][s, C, q]을 만든다. 즉 하나의 pushing operation에 대하여 G에 |Q| 개의 rule을
추가한다. 그러나 실제로 앞서 예 3과 같이 많은 nonterminal (즉, M의 STES)들이 string을 발생할 수 없어 제거된다.
예 2의 경우 algorithm을 적용하면 더 많은 rule이 만들어지겠지만, string을 만들 수 없는 nonterminal과 이에 관련된
rule은 transition graph를 보아 알 수 있으므로 적지 않았다. 그러나 transition graph이 복잡할 때, nonterminal이
필요한지를 보아 가려내는 일은 쉽지 않다. 이 목적으로 우리가 10장에서 배운 CFG로부터 불필요한 기호를 찾아
제거하는 algorithm이 유용하게 쓰일 것이다.
CFG PDA
Love
What else is love but understanding and rejoicing in the fact that another person lives, acts, and experiences
otherwise than we do….? - Friedrich Nietzsche –
Just because you love someone doesn‟t mean you have to be involved with them. Love is not a bandage to cover
wounds. - Hugh Elliot -
쉬어 가기
Page 244
542
15.1 임의의 두 enumerable set S1과 S2의 공집합 S1 S2 역시 enumerable 하다는 것을 증명하라.
15.2 모든 실수(real number)의 집합은 enumerable 하지 않다는 것을 증명하라.
15.3 Type 0 언어가 아닌 모든 언어의 집합은 enumerable 하지 않다는 것을 증명하라.
연습문제
형식언어 및 오토마타 체계 III