# 3. ๐Ÿšจ Top-Down Parsing (1) - Recursive Descent Parser ## 3.1 Top-Down Parsing โ†’ Backtracking ํ•„์š” > ยง2.4์—์„œ Parse Tree(=CST)๋ฅผ ๋ณต์›ํ•˜๋Š”(=CST Generator์—์„œ ํ•˜๋Š” ์ผ) > ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•(Top-down / Bottom-up)์„ ์†Œ๊ฐœํ–ˆ๋‹ค. > > ์ด ์ ˆ๋ถ€ํ„ฐ๋Š” Top-down ๋ฐฉ์‹์„ ๊ตฌ์ฒด์ ์œผ๋กœ ๋‹ค๋ฃฌ๋‹ค. > ๋จผ์ € ๋‹จ์ˆœํžˆ ์‹œ๋„ํ•˜๋ฉด ์–ด๋–ค ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ๋Š”์ง€, ๊ทธ ํ•ด๊ฒฐ์ฑ…์ด Backtracking์ž„์„ ํ™•์ธํ•œ๋‹ค. > > ยง3.2์—์„œ Backtracking์„ ์ฒด๊ณ„ํ™”ํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ธ Recursive Descent Parsing์„ ๋‹ค๋ฃฌ๋‹ค. Top-down parsing์€ $S$์—์„œ ์‹œ์ž‘ํ•˜์—ฌ production์„ ์„ ํƒํ•˜๋ฉฐ ์ ์  ํ™•์žฅํ•ด๋‚˜๊ฐ€๋Š” ๋ฐฉ์‹์ด๋‹ค. $S \to \gamma_1 \to \gamma_2 \to \cdots \to \gamma_n \to s$ **๋ฌธ์ œ:** ์ž˜๋ชป๋œ production์„ ์„ ํƒํ•˜๋ฉด ๋ชฉํ‘œ ๋ฌธ์ž์—ด๊ณผ ๋‹ค๋ฅธ ๋ฐฉํ–ฅ์œผ๋กœ ์œ ๋„๋  ์ˆ˜ ์žˆ๋‹ค. **์˜ˆ์‹œ: ๋ง์…ˆ ๋ฌธ๋ฒ•** ```ebnf S ::= E + S | E E ::= [number] | ( S ) ``` ์ž…๋ ฅ: `(1+2+(3+4))+5` ``` S โ†’ E โ†’ ( S ) โ†’ ( E ) โ†’ ( 1 ) โ† ์ž˜๋ชป๋œ ์œ ๋„! ``` ์–ด๋–ค ๊ทœ์น™์ด ๋ฌธ์ œ์˜€์„๊นŒ? ``` // ๋˜๋Œ์•„๊ฐ€๊ธฐ S โ†’ E โ†’ ( S ) โ†’ ( E ) โ†’ ( 1 ) // ๊ด„ํ˜ธ๋ฅผ ์œ ๋ฐœํ•œ ์นœ๊ตฌ๋ฅผ ์ฐพ์ž S โ†’ E โ†’ ( S ) โ† ์—ฌ๊ธฐ๊ฐ€ ๋ฌธ์ œ? S โ†’ E โ†’ 1 โ† ์ด๋ ‡๊ฒŒ ๊ฐ€๋„ ์ด์ƒํ•จ S โ†’ E โ† ๋ฌธ์ œ๋Š” ์—ฌ๊ธฐ! ``` **ํ•ด๊ฒฐ์ฑ…: Backtracking** โ†’ ์ž˜๋ชป๋œ ์„ ํƒ์„ ๊ฐ์ง€ํ•˜๋ฉด ์ด์ „ ์ƒํƒœ๋กœ ๋˜๋Œ์•„๊ฐ€ ๋‹ค๋ฅธ production์„ ์‹œ๋„ํ•œ๋‹ค. ## 3.2 ๐Ÿšจ Recursive Descent Parsing โ€” ์ •์˜ > ยง3.1์—์„œ Backtracking์ด Top-down parsing์˜ ํ•ต์‹ฌ ์•„์ด๋””์–ด์ž„์„ ํ™•์ธํ–ˆ๋‹ค. > ์ด ์ ˆ์—์„œ๋Š” Backtracking์„ ๊ตฌ์ฒด์ ์ธ ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ ์ฒด๊ณ„ํ™”ํ•œ > Recursive Descent Parsing์„ ์ •์˜ํ•œ๋‹ค. > ยง3.3์—์„œ๋Š” ์ด ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ํŠน์ง•๊ณผ ํ•œ๊ณ„๋ฅผ ๋ถ„์„ํ•œ๋‹ค. ### 3.2.1 ์ž…๋ ฅ ๋ฐ ๋ณ€์ˆ˜ > ๐Ÿค“โ˜๏ธ ์ด๊ฑด ๊ฒฐ๊ตญ Parser ๋‚ด๋ถ€ CST Generator์˜ ๋™์ž‘์ž„์„ ์žŠ์ง€ ๋ง์ž! Token์ด ๋ญ์˜€๋Š”์ง€ ํ—ท๊ฐˆ๋ฆฐ๋‹ค๋ฉด? [[1. Lexer]] ์ค‘ ยง1.4 Grammar๊ฐ€ ๋ญ์˜€๋Š”์ง€ ํ—ท๊ฐˆ๋ฆฐ๋‹ค๋ฉด? [[#1.4 Language์˜ ์กฐ๊ฑด โ€” Grammar (๋ฌธ๋ฒ•)]]๊ณผ [[#1.8 ์–ด๋–ค ๊ฒƒ์„ Context-Free Grammar๋ผ๊ณ  ํ•˜๋Š”๊ฐ€?]] ์ฐธ๊ณ . Tree๊ฐ€ ๋ญ์˜€๋Š”์ง€ ํ—ท๊ฐˆ๋ฆฐ๋‹ค๋ฉด? [[#2.2.2 Syntax Tree ์ข…๋ฅ˜ โ€” CST (Concrete Syntax Tree) = Parse Tree]] ์ฐธ๊ณ . ```pseudo ์ž…๋ ฅ: (T, NT, S, P) // Grammar tokens // Token ๋ฆฌ์ŠคํŠธ ๋ณ€์ˆ˜: tree โ† S // Tree node (์†์„ฑ: parent, children, rule) // return ๋˜๋Š” Parse Tree(=CST) focus โ† S // ํ˜„์žฌ ์ฒ˜๋ฆฌ ์ค‘์ธ Tree node // CST๋ฅผ ๋งŒ๋“ค์–ด๊ฐ€๋Š” ๊ณผ์ •์—์„œ // "์ง€๊ธˆ ์–ด๋А ๋…ธ๋“œ๋ฅผ ํ™•์žฅ/๋งค์นญํ•˜๊ณ  ์žˆ๋Š”๊ฐ€? idx โ† 0 // ํ˜„์žฌ Token ์œ„์น˜ // ์ž…๋ ฅ Token list์—์„œ ์–ด๋””๊นŒ์ง€ ์†Œ๋น„ํ–ˆ๋Š”๊ฐ€? stack โ† [] // ์•„์ง ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š์€ ๋…ธ๋“œ๋“ค์˜ ์Šคํƒ ``` ### 3.2.2 ๋ฉ”์ธ ๋ฃจํ”„ ```pseudo while (true) do if (focus โˆˆ NT) then // Non-Terminal // focus๊ฐ€ Non-terminal (์˜ˆ: CSTExpr, CSTStmt ๋“ฑ) // โ†’ ์•„์ง ํ™•์žฅ์ด ์•ˆ ๋œ ๋…ธ๋“œ. production์„ ์ ์šฉํ•ด์„œ ์ž์‹ ๋…ธ๋“œ๋“ค๋กœ ํŽผ์ณ์•ผ ํ•จ // โ†’ ์˜ˆ: focus = S ์ด๋ฉด S โ†’ E + S ๊ฐ™์€ rule์„ ์„ ํƒํ•ด์„œ // E, +, S ์ž์‹์œผ๋กœ ์—ฐ๊ฒฐ goto Case 1 else if (idx < len(tokens) && focus = tokens[idx]) then // Terminal // focus๊ฐ€ Terminal (์˜ˆ: IF, LPAREN, ID ๋“ฑ ์‹ค์ œ ํ† ํฐ) // && ์•„์ง ์ฝ์„ ํ† ํฐ์ด ๋‚จ์•„ ์žˆ๊ณ  (idx < len(tokens)) // && ํ˜„์žฌ focus ๋…ธ๋“œ๊ฐ€ ํ˜„์žฌ ํ† ํฐ๊ณผ ์ผ์น˜ํ•  ๋•Œ (focus = tokens[idx]) // โ†’ "ํŠธ๋ฆฌ๊ฐ€ ๊ธฐ๋Œ€ํ•˜๋Š” ํ† ํฐ"๊ณผ "์‹ค์ œ ์ž…๋ ฅ ํ† ํฐ"์ด ๋งž์œผ๋ฏ€๋กœ ์†Œ๋น„ // โ†’ ์˜ˆ: focus = IF, tokens[idx] = IF ์ด๋ฉด ๋งค์นญ ์„ฑ๊ณต goto Case 2 else if (idx = len(tokens) && stack = []) then // โœ… Success! // focus๊ฐ€ ๋ญ”์ง€๋Š” ์•ˆ ์ค‘์š” // ํ† ํฐ์„ ์ „๋ถ€ ์†Œ๋น„ํ–ˆ๊ณ  (idx = len(tokens)) // && ์Šคํƒ๋„ ๋น„์–ด์žˆ์Œ (์ฒ˜๋ฆฌํ•  ๋…ธ๋“œ๊ฐ€ ๋” ์—†์Œ) // โ†’ ์ž…๋ ฅ ์ „์ฒด๋ฅผ ํŠธ๋ฆฌ๋กœ ์™„์ „ํžˆ ์ปค๋ฒ„ํ–ˆ์œผ๋ฏ€๋กœ ํŒŒ์‹ฑ ์„ฑ๊ณต! return tree else // โ›” Backtrack! // ์œ„ ์„ธ ์กฐ๊ฑด ๋ชจ๋‘ ํ•ด๋‹น ์—†์Œ. ์ฆ‰: // 1) focus๋Š” Terminal์ธ๋ฐ tokens[idx]์™€ ๋ถˆ์ผ์น˜ // โ†’ ์ฆ‰, ์ž˜๋ชป๋œ production์„ ์„ ํƒํ–ˆ์Œ // 2) ๋˜๋Š” ํ† ํฐ์ด ๋‚จ์•˜๋Š”๋ฐ ์Šคํƒ์ด ๋น„์–ด๋ฒ„๋ฆผ (์ž…๋ ฅ์ด ๋” ๋‚จ์•˜๋Š”๋ฐ ํŠธ๋ฆฌ๊ฐ€ ๋๋‚จ) // โ†’ ํ˜„์žฌ ์„ ํƒํ•œ production์ด ํ‹€๋ ธ์œผ๋ฏ€๋กœ ๋˜๋Œ์•„๊ฐ€์„œ ๋‹ค๋ฅธ production ์‹œ๋„ goto Case 3 ``` ### 3.2.3 Case 1: Non-terminal ์ฒ˜๋ฆฌ โ†’ Production ํ˜„์žฌ focus๊ฐ€ Non-terminal์ธ ๊ฒฝ์šฐ, ํ•ด๋‹น Non-terminal์˜ rule ๋ฒˆํ˜ธ์— ํ•ด๋‹นํ•˜๋Š” production์„ ์ ์šฉํ•œ๋‹ค. ```pseudo // Case 1: focus๊ฐ€ NT์ผ ๋•Œ โ€” production์„ ์ ์šฉํ•ด์„œ ํŠธ๋ฆฌ๋ฅผ ํ™•์žฅ // focus๋ฅผ ์ขŒ๋ณ€์œผ๋กœ ๋’€์„ ๋•Œ (NT), ์šฐ๋ณ€์— ์˜ค๋Š” ๊ฒƒ๋“ค ฮฑโ‚ ... ฮฑโ‚™ ๋กœ ํ‘œ์‹œ // P[focus][focus.rule] = focus ๋…ธ๋“œ์— ์ ์šฉํ•  production ์„ ํƒ // ์˜ˆ: focus = S, focus.rule = 0 ์ด๋ฉด P[S][0] = S โ†’ E + S // ์ฆ‰, // ฮฑโ‚ = E, ฮฑโ‚‚ = +, ฮฑโ‚ƒ = S (focus -> ฮฑโ‚ ... ฮฑโ‚™) โ† P[focus][focus.rule] // ๋‹ค์Œ์— ์ด ๋…ธ๋“œ๋กœ backtrackํ–ˆ์„ ๋•Œ ๋‹ค์Œ production์„ ์‹œ๋„ํ•˜๋„๋ก +1 // ์˜ˆ: focus.rule = 0 โ†’ 1 ๋กœ ์˜ฌ๋ ค๋†“์œผ๋ฉด, backtrack ์‹œ P[S][1] = S โ†’ E ์‹œ๋„ focus.rule โ† focus.rule + 1 // ์„ ํƒํ•œ production์˜ ์šฐ๋ณ€์— ์˜ค๋Š” ๊ฒƒ๋“ค(ฮฑโ‚...ฮฑโ‚™)์„ ์ „๋ถ€ ์ž์‹ ๋…ธ๋“œ๋กœ ์—ฐ๊ฒฐ // โ†’ ํŠธ๋ฆฌ๊ฐ€ ์ด ์‹œ์ ์— ํ™•์žฅ๋จ // ์˜ˆ: focus = S, P[S][0] = S โ†’ E + S ์ด๋ฉด // S ๋…ธ๋“œ์— E, +, S ์ž์‹ ๋…ธ๋“œ ์„ธ ๊ฐœ๊ฐ€ ์—ฐ๊ฒฐ๋จ for 1 โ‰ค i โ‰ค n do connect(focus, ฮฑแตข) // ฮฑโ‚‚ ~ ฮฑโ‚™์€ ์Šคํƒ์— push (๋‚˜์ค‘์— ์ฒ˜๋ฆฌํ•  ๊ฒƒ๋“ค) // ๊ทธ๋ ‡๋‹ค๋Š” ๊ฑด ฮฑโ‚์€ ์ง€๊ธˆ ์ฒ˜๋ฆฌํ•˜๊ฒ ๋‹ค๋Š” ๊ฑฐ!! // ์˜ค๋ฅธ์ชฝ๋ถ€ํ„ฐ pushํ•ด์•ผ ๋‚˜์ค‘์— popํ–ˆ์„ ๋•Œ ์™ผ์ชฝ๋ถ€ํ„ฐ ์ˆœ์„œ๋Œ€๋กœ ๋‚˜์˜ด // ์˜ˆ: ฮฑโ‚‚ = +, ฮฑโ‚ƒ = S ์ด๋ฉด S๋ฅผ ๋จผ์ € push, +๋ฅผ ๋‚˜์ค‘์— push // โ†’ popํ•˜๋ฉด +๊ฐ€ ๋จผ์ € ๋‚˜์˜ด (left-most ์ˆœ์„œ ์œ ์ง€) for n โ‰ฅ i โ‰ฅ 2 do stack.push(ฮฑแตข) // ฮฑโ‚(๊ฐ€์žฅ ์™ผ์ชฝ ๊ธฐํ˜ธ)๋กœ focus ์ด๋™ // โ†’ left-most derivation: ํ•ญ์ƒ ๊ฐ€์žฅ ์™ผ์ชฝ ๋…ธ๋“œ๋ถ€ํ„ฐ ์ฒ˜๋ฆฌ focus โ† ฮฑโ‚ ``` ### 3.2.4 Case 2: Terminal ์ฒ˜๋ฆฌ โ†’ ๋‹ค์Œ์œผ๋กœ ํ˜„์žฌ focus๊ฐ€ Terminal์ด๊ณ  ํ˜„์žฌ Token๊ณผ ์ผ์น˜ํ•˜๋Š” ๊ฒฝ์šฐ: ```pseudo // Case 2: T // "ํŠธ๋ฆฌ๊ฐ€ ๊ธฐ๋Œ€ํ•˜๋Š” ํ† ํฐ"๊ณผ "์‹ค์ œ ์ž…๋ ฅ ํ† ํฐ"์ด ๋งž์œผ๋ฏ€๋กœ ์†Œ๋น„ idx โ† idx + 1 // ๋‹ค์Œ ํ† ํฐ์œผ๋กœ ์ด๋™ focus โ† stack.pop() // ์Šคํƒ์—์„œ ๋‹ค์Œ ์ฒ˜๋ฆฌํ•  ๋…ธ๋“œ ๊บผ๋‚ด๊ธฐ ``` ### 3.2.5 ๐Ÿšจ Case 3: Backtrack โ†’ ๋ฐฑํŠธ๋ž™ or ๋งค์นญ ์‹คํŒจ ์‹œ, ๊ฐ€์žฅ ์ตœ๊ทผ Non-terminal๋กœ ์˜ฌ๋ผ๊ฐ€ ๋‹ค์Œ production์„ ์‹œ๋„ํ•œ๋‹ค. ```pseudo // Case 3: Backtrack โ›” while (true) do // ํ˜„์žฌ ์‹คํŒจํ•œ ๋…ธ๋“œ๋ฅผ error๋กœ ์ €์žฅ error โ† focus ???? // ๋ถ€๋ชจ ๊ธฐ์ค€์œผ๋กœ error๊ฐ€ ๋ช‡ ๋ฒˆ์งธ ์ž์‹์ธ์ง€ ์ธ๋ฑ์Šค ์ €์žฅ // โ†’ ์ดํ›„ stack/idx ๋ณต์› ๋ฒ”์œ„๋ฅผ ๊ณ„์‚ฐํ•  ๋•Œ ์‚ฌ์šฉ error_idx โ† focus.children.index(error) // stack, idx๋ฅผ ์ด ๋…ธ๋“œ(focus)๋ฅผ ํ™•์žฅํ•˜๊ธฐ ์ „ ์ƒํƒœ๋กœ ๋ณต์› // โ†’ error_idx ์ดํ›„ ์ž์‹๋“ค์„ stack์—์„œ pop // โ†’ error_idx > 0 ์ด๋ฉด idx๋„ ์™ผ์ชฝ ํ˜•์ œ๊ฐ€ ์†Œ๋น„ํ•œ ํ† ํฐ ์ด์ „์œผ๋กœ ๋˜๋Œ๋ฆผ goto restore ๐Ÿ”„ // focus์˜ ์ž์‹ ๋…ธ๋“œ๋ฅผ ์ „๋ถ€ ์ œ๊ฑฐ // โ†’ ๋‹ค์Œ production์„ ์ƒˆ๋กœ ์‹œ๋„ํ•˜๊ธฐ ์œ„ํ•ด ํŠธ๋ฆฌ๋ฅผ ๊นจ๋—ํ•˜๊ฒŒ ๋น„์›€ goto remove_children ๐Ÿ—‘๏ธ if (focus.rule = len(P[focus])) then // focus์—์„œ ๋‹ค์Œ์— ์‹œ๋„ํ•  P index = Focus๊ฐ€ ์‹œ๋„ํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  P len // ์ด NT์— ๋Œ€ํ•ด ์‹œ๋„ํ•  production์ด ๋” ์ด์ƒ ์—†์Œ if (focus = tree) then // ๋ฃจํŠธ ๋…ธ๋“œ๊นŒ์ง€ ์˜ฌ๋ผ์™”๋Š”๋ฐ๋„ ์‹คํŒจ // โ†’ ์–ด๋–ค production ์กฐํ•ฉ์œผ๋กœ๋„ ํŒŒ์‹ฑ ๋ถˆ๊ฐ€ โ†’ ๊ตฌ๋ฌธ ์˜ค๋ฅ˜ raise Error else // ์•„์ง ์œ„์— ๋ถ€๋ชจ ๋…ธ๋“œ๊ฐ€ ์žˆ์Œ // โ†’ while ๋ฐ˜๋ณตํ•˜์—ฌ ํ•œ ๋‹จ๊ณ„ ๋” ์œ„๋กœ ์˜ฌ๋ผ๊ฐ€์„œ backtrack ๊ณ„์† continue else // ์•„์ง ์‹œ๋„ ์•ˆ ํ•œ production์ด ๋‚จ์•„ ์žˆ์Œ // โ†’ while ํƒˆ์ถœ ํ›„ ๋ฉ”์ธ ๋ฃจํ”„์—์„œ ๋‹ค์Œ production์œผ๋กœ ์žฌ์‹œ๋„ break ``` **๐Ÿ”„ restore** (์ƒํƒœ ๋ณต์›): ```pseudo // focus ๋ณต์› // โ†’ ์‹คํŒจํ•œ ๋…ธ๋“œ์—์„œ ๋ถ€๋ชจ๋กœ ์˜ฌ๋ผ๊ฐ // โ†’ ์ด์ œ ์ด ๋ถ€๋ชจ ๋…ธ๋“œ์˜ ๋‹ค์Œ production์„ ์‹œ๋„ํ•  ๊ฒƒ focus โ† focus.parent // stack ๋ณต์› // โ†’ error_idx ์ดํ›„ ์ž์‹๋“ค(์•„์ง ์ฒ˜๋ฆฌ ์•ˆ ํ•œ ์˜ค๋ฅธ์ชฝ ํ˜•์ œ๋“ค)์€ // Case 1์—์„œ stack.push ํ–ˆ๋˜ ์• ๋“ค์ด๋ฏ€๋กœ ๋‹ค์‹œ popํ•ด์„œ ๋˜๋Œ๋ฆผ // โ†’ ์˜ˆ: error_idx = 1 ์ด๊ณ  ์ž์‹์ด [E, +, S] ๋ฉด // +, S ๋Š” ์•„์ง ์ฒ˜๋ฆฌ ์•ˆ ํ–ˆ์œผ๋‹ˆ stack์—์„œ pop for (error_idx + 1 โ‰ค i < len(focus.children)) do stack.pop() // idx ๋ณต์› // โ†’ error_idx = 0 ์ด๋ฉด ์™ผ์ชฝ ํ˜•์ œ๊ฐ€ ์—†์œผ๋ฏ€๋กœ // ์†Œ๋น„ํ•œ ํ† ํฐ์ด ์—†์Œ โ†’ idx ๋ณต์› ๋ถˆํ•„์š” // โ†’ error_idx โ‰  0 ์ด๋ฉด ์™ผ์ชฝ ํ˜•์ œ๋“ค์ด ์ด๋ฏธ ํ† ํฐ์„ ์†Œ๋น„ํ–ˆ์œผ๋ฏ€๋กœ // ๊ฐ€์žฅ ์™ผ์ชฝ ์ž์‹(children[0])์˜ ์ œ์ผ ์™ผ์ชฝ ๋ terminal์„ ์ฐพ์•„์„œ // ๊ทธ ํ† ํฐ ์œ„์น˜๋กœ idx๋ฅผ ๋˜๋Œ๋ฆผ // โ†’ follow_left_child = ํ•ด๋‹น ๋…ธ๋“œ์—์„œ ์™ผ์ชฝ ์ž์‹์„ ํƒ€๊ณ  ๋‚ด๋ ค๊ฐ€ // ๊ฐ€์žฅ ์ฒซ ๋ฒˆ์งธ terminal ๋…ธ๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜ if (error_idx โ‰  0) then terminal โ† follow_left_child(focus.children[0]) idx โ† tokens.index(terminal) ``` **๐Ÿ—‘๏ธ remove_children** (์ž์‹ ์ œ๊ฑฐ): ```pseudo for (child โˆˆ focus.children) do disconnect(focus, child) ``` ### 3.2.6 ์˜ˆ์‹œ: (์ˆœ์„œ๋ฅผ ๋ฐ”๊พผ) ๋ง์…ˆ ๋ฌธ๋ฒ• > ํ† ํฐ์€ ๊ฐ€์žฅ ์™ผ์ชฝ๋ถ€ํ„ฐ ๋ณด๊ณ , stack ๊ทธ๋ ค์„œ ์Œ“์•„๊ฐ€๋ฉด์„œ ์ดํ•ด ใ„ฑใ„ฑ > ํ•œ ๋ฒˆ ์ดํ•ดํ•œ ๊ฑฐ๋ผ ใ„ฑใ…Š์„๋“ฏ ์ž…๋ ฅ: `(1+2+(3+4))+5` ```ebnf S ::= E | E + S E ::= ( S ) | [number] ``` production ์ธ๋ฑ์Šค ์ •๋ฆฌ: - `P[S][0]` = `S โ†’ E` - `P[S][1]` = `S โ†’ E + S` - `P[E][0]` = `E โ†’ ( S )` - `P[E][1]` = `E โ†’ [number]` #### ์ดˆ๊ธฐ ์ƒํƒœ ``` tree : S focus : S idx : 0 โ†’ ( stack : [] ``` #### STEP 1 `Case 1` โ€” focus=S (NT), `P[S][0]` = `S โ†’ E` ์ ์šฉ ``` tree : S | E โ† focus idx : 0 โ†’ ( stack : [] ``` #### STEP 2 `Case 1` โ€” focus=E (NT), `P[E][0]` = `E โ†’ ( S )` ์ ์šฉ ``` tree : S | E / | \ ( S ) โ† focus=( idx : 0 โ†’ ( stack : [S, )] ``` #### STEP 3 `Case 2` โ€” focus=`(`, tokens\[0]=`(` โœ… ๋งค์นญ ``` tree : S | E / | \ ( S ) โ† focus=S idx : 1 โ†’ 1 stack : [)] ``` #### STEP 4 `Case 1` โ€” focus=S (NT), `P[S][0]` = `S โ†’ E` ์ ์šฉ ``` tree : S | E / | \ ( S ) | E โ† focus idx : 1 โ†’ 1 stack : [)] ``` #### STEP 5 `Case 1` โ€” focus=E (NT), `P[E][0]` = `E โ†’ ( S )` ์ ์šฉ ``` tree : S | E / | \ ( S ) | E / | \ ( S ) โ† focus=( idx : 1 โ†’ 1 stack : [S, ), )] ``` #### STEP 6 `Case 3` โ›” โ€” focus=`(`, tokens[1]=`1` โŒ ๋ถˆ์ผ์น˜ โ†’ Backtrack `E โ†’ ( S )` ์‹คํŒจ. `P[E][1]` = `E โ†’ [number]` ๋กœ ์žฌ์‹œ๋„. restore: focus=E (๋ถ€๋ชจ๋กœ), idx=1 ์œ ์ง€, ์ž์‹ ์ œ๊ฑฐ. ``` tree : S | E / | \ ( S ) | E โ† focus (์ž์‹ ์ œ๊ฑฐ๋จ, rule=1๋กœ ์˜ฌ๋ผ๊ฐ) idx : 1 โ†’ 1 stack : [)] ``` #### STEP 7 `Case 1` โ€” focus=E (NT), `P[E][1]` = `E โ†’ [number]` ์ ์šฉ ``` tree : S | E / | \ ( S ) | E | 1 โ† focus idx : 1 โ†’ 1 stack : [)] ``` #### STEP 8 `Case 2` โ€” focus=`1`, tokens[1]=`1` โœ… ๋งค์นญ ``` tree : S | E / | \ ( S ) | E | 1 โ† focus=) (stack.pop) idx : 2 โ†’ + stack : [] โ†’ pop ํ•˜๋ฉด ) ``` #### STEP 9 `Case 3` โ›” โ€” focus=`)`, tokens[2]=`+` โŒ ๋ถˆ์ผ์น˜ โ†’ Backtrack `S โ†’ E` ๋กœ๋Š” `1` ๋งŒ ์†Œ๋น„ํ•˜๊ณ  ๋๋‚ฌ๋Š”๋ฐ `)` ๊ฐ€ ์™€์•ผ ํ•˜๋Š”๋ฐ `+` ๊ฐ€ ์˜ด. restore: focus=S (๋ถ€๋ชจ), idx=1, ์ž์‹(E) ์ œ๊ฑฐ. `P[S][1]` = `S โ†’ E + S` ๋กœ ์žฌ์‹œ๋„. ``` tree : S | E / | \ ( S ) | S โ† focus (rule=1, ์ž์‹ ์ œ๊ฑฐ๋จ) idx : 1 โ†’ 1 stack : [)] ``` #### STEP 10 `Case 1` โ€” focus=S (NT), `P[S][1]` = `S โ†’ E + S` ์ ์šฉ ``` tree : S | E / | \ ( S ) | S / | \ E + S โ† focus=E idx : 1 โ†’ 1 stack : [+, S, )] ``` #### STEP 11 `Case 1` โ€” focus=E (NT), `P[E][1]` = `E โ†’ [number]` ์ ์šฉ (์ด์ „์— `E โ†’ ( S )` ๊ฐ€ ์‹คํŒจํ•œ ์  ์žˆ๊ณ , ์ง€๊ธˆ tokens[1]=`1` ์ด๋ฏ€๋กœ ๋ฐ”๋กœ [number] ์„ ํƒ) ``` tree : S | E / | \ ( S ) | S / | \ E + S | 1 โ† focus idx : 1 โ†’ 1 stack : [+, S, )] ``` #### STEP 12 `Case 2` โ€” focus=`1`, tokens[1]=`1` โœ… ``` focus : + (stack.pop) idx : 2 โ†’ + stack : [S, )] ``` #### STEP 13 `Case 2` โ€” focus=`+`, tokens[2]=`+` โœ… ``` focus : S (stack.pop) idx : 3 โ†’ 2 stack : [)] ``` #### STEP 14 `Case 1` โ€” focus=S (NT), `P[S][1]` = `S โ†’ E + S` ์ ์šฉ ``` tree : S | E / | \ ( S ) | S / | \ E + S | \ 1 E + S โ† focus=E idx : 3 โ†’ 2 stack : [+, S, )] ``` #### STEP 15 `Case 1` โ€” focus=E, `P[E][1]` = `E โ†’ [number]` ์ ์šฉ ``` E | 2 โ† focus idx : 3 โ†’ 2 ``` #### STEP 16 `Case 2` โ€” focus=`2`, tokens[3]=`2` โœ… ``` focus : + (stack.pop) idx : 4 โ†’ + stack : [S, )] ``` #### STEP 17 `Case 2` โ€” focus=`+`, tokens[4]=`+` โœ… ``` focus : S (stack.pop) idx : 5 โ†’ ( stack : [)] ``` #### STEP 18 `Case 1` โ€” focus=S, `P[S][0]` = `S โ†’ E` ์ ์šฉ ``` S | E โ† focus idx : 5 โ†’ ( stack : [)] ``` #### STEP 19 `Case 1` โ€” focus=E, `P[E][0]` = `E โ†’ ( S )` ์ ์šฉ ``` E / | \ ( S ) โ† focus=( idx : 5 โ†’ ( stack : [S, ), )] ``` #### STEP 20 `Case 2` โ€” focus=`(`, tokens[5]=`(` โœ… ``` focus : S (stack.pop) idx : 6 โ†’ 3 stack : [), )] ``` #### STEP 21 `Case 1` โ€” focus=S, `P[S][1]` = `S โ†’ E + S` ์ ์šฉ ``` S / | \ E + S โ† focus=E idx : 6 โ†’ 3 stack : [+, S, ), )] ``` #### STEP 22 `Case 1` โ€” focus=E, `P[E][1]` = `E โ†’ [number]` ์ ์šฉ ``` E | 3 โ† focus idx : 6 โ†’ 3 ``` #### STEP 23 `Case 2` โ€” focus=`3`, tokens[6]=`3` โœ… ``` focus : + idx : 7 โ†’ + ``` #### STEP 24 `Case 2` โ€” focus=`+`, tokens[7]=`+` โœ… ``` focus : S idx : 8 โ†’ 4 ``` #### STEP 25 `Case 1` โ€” focus=S, `P[S][0]` = `S โ†’ E` ์ ์šฉ ``` S | E โ† focus idx : 8 โ†’ 4 ``` #### STEP 26 `Case 1` โ€” focus=E, `P[E][1]` = `E โ†’ [number]` ์ ์šฉ ``` E | 4 โ† focus idx : 8 โ†’ 4 ``` #### STEP 27 `Case 2` โ€” focus=`4`, tokens[8]=`4` โœ… ``` focus : ) (stack.pop) idx : 9 โ†’ ) stack : [), )] ``` #### STEP 28 `Case 2` โ€” focus=`)`, tokens[9]=`)` โœ… ``` focus : ) (stack.pop) idx : 10 โ†’ ) stack : [)] ``` #### STEP 29 `Case 2` โ€” focus=`)`, tokens[10]=`)` โœ… ``` focus : + (stack.pop) idx : 11 โ†’ + stack : [S] ``` #### STEP 30 `Case 2` โ€” focus=`+`, tokens[11]=`+` โœ… ``` focus : S (stack.pop) idx : 12 โ†’ 5 stack : [] ``` #### STEP 31 `Case 1` โ€” focus=S, `P[S][0]` = `S โ†’ E` ์ ์šฉ ``` S | E โ† focus idx : 12 โ†’ 5 stack : [] ``` #### STEP 32 `Case 1` โ€” focus=E, `P[E][1]` = `E โ†’ [number]` ์ ์šฉ ``` E | 5 โ† focus idx : 12 โ†’ 5 stack : [] ``` #### STEP 33 `Case 2` โ€” focus=`5`, tokens[12]=`5` โœ… ``` focus : stack.pop() โ†’ ์Šคํƒ ๋น„์–ด์žˆ์Œ idx : 13 (= len(tokens)) stack : [] ``` #### STEP 34 โœ… **Success!** โ€” `idx = len(tokens) && stack = []` ์ตœ์ข… CST: ``` S โ””โ”€โ”€ E โ”œโ”€โ”€ ( โ”œโ”€โ”€ S โ”‚ โ””โ”€โ”€ S โ”‚ โ”œโ”€โ”€ E โ”‚ โ”‚ โ””โ”€โ”€ 1 โ”‚ โ”œโ”€โ”€ + โ”‚ โ””โ”€โ”€ S โ”‚ โ”œโ”€โ”€ E โ”‚ โ”‚ โ””โ”€โ”€ 2 โ”‚ โ”œโ”€โ”€ + โ”‚ โ””โ”€โ”€ S โ”‚ โ””โ”€โ”€ E โ”‚ โ”œโ”€โ”€ ( โ”‚ โ”œโ”€โ”€ S โ”‚ โ”‚ โ””โ”€โ”€ S โ”‚ โ”‚ โ”œโ”€โ”€ E โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ 3 โ”‚ โ”‚ โ”œโ”€โ”€ + โ”‚ โ”‚ โ””โ”€โ”€ S โ”‚ โ”‚ โ””โ”€โ”€ E โ”‚ โ”‚ โ””โ”€โ”€ 4 โ”‚ โ””โ”€โ”€ ) โ””โ”€โ”€ ) + S โ””โ”€โ”€ E โ””โ”€โ”€ 5 ``` ## 3.3 Recursive Descent Parsing โ€” ํŠน์ง• > ยง3.2์—์„œ Recursive Descent Parsing ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์™„์ „ํžˆ ์ •์˜ํ–ˆ๋‹ค. > > ์ด์ œ ์ด ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ์„ฑ์งˆ์„ ๋ถ„์„ํ•˜๊ณ , > ํ•ญ์ƒ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€ ์งˆ๋ฌธ์„ ๋˜์ง„๋‹ค. > > ยง3.4์—์„œ๋Š” ์ข…๋ฃŒ๋ฅผ ๋ณด์žฅํ•˜์ง€ ๋ชปํ•˜๋Š” Left-recursion ๋ฌธ์ œ์™€ ๊ทธ ํ•ด๊ฒฐ์ฑ…์„ ๋‹ค๋ฃฌ๋‹ค. ### 3.3.1 `ํŠน์ง•1` Left-most derivation Recursive Descent Parsing์€ ํ•ญ์ƒ Left-most derivation)๋ฅผ ๋”ฐ๋ฅธ๋‹ค. โ†’ ์Šคํƒ ๊ตฌ์กฐ์ƒ ํ•ญ์ƒ ๊ฐ€์žฅ ์™ผ์ชฝ์˜ Non-terminal์„ ๋จผ์ € ์ฒ˜๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ. ### 3.3.2 `ํŠน์ง•2` ํŠน์ง• 2: ์ข…๋ฃŒ ์—ฌ๋ถ€ ํŠน๋ณ„ํ•œ ๋ฌธ๋ฒ•์ด ์•„๋‹Œ ๊ฒฝ์šฐ์—” ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ๋๋‚œ๋‹ค. ํ•˜์ง€๋งŒ ๋‹ค์Œ ์ ˆ์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋“ฏ, ํŠน์ • ๋ฌธ๋ฒ•์—์„œ๋Š” **๋ฌดํ•œ ๋ฃจํ”„**์— ๋น ์งˆ ์ˆ˜ ์žˆ๋‹ค. ### 3.3.3 `ํŠน์ง•3` Backtracking์˜ ๋น„ํšจ์œจ์„ฑ ๋งค๋ฒˆ ์‹คํŒจํ•  ๋•Œ๋งˆ๋‹ค ์ด์ „ ์ƒํƒœ๋กœ ๋Œ์•„๊ฐ€์„œ ๋‹ค์‹œ ์‹œ๋„ํ•˜๋ฏ€๋กœ, ์ตœ์•…์˜ ๊ฒฝ์šฐ ์ง€์ˆ˜ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆด ์ˆ˜ ์žˆ๋‹ค. โ†’ ์‹ค์šฉ์ ์ธ ํŒŒ์„œ์—์„œ๋Š” Backtracking์„ ํ”ผํ•˜๊ธฐ ์œ„ํ•œ ์ตœ์ ํ™”(look-ahead ๋“ฑ)๊ฐ€ ํ•„์š”ํ•˜๋‹ค. ## 3.4 Recursive Descent Parsing โ€” Left-Recursion ๋ฌธ์ œ์™€ ํ•ด๊ฒฐ > ยง3.3์—์„œ Recursive Descent Parsing์ด > ํŠน์ • ๋ฌธ๋ฒ•์—์„œ ์ข…๋ฃŒ๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์„ ์ง€์ ํ–ˆ๋‹ค. > > ๊ตฌ์ฒด์ ์œผ๋กœ ์–ด๋–ค ๋ฌธ๋ฒ•์ด ๋ฌธ์ œ๊ฐ€ ๋˜๋Š”์ง€, > ๊ทธ๋ฆฌ๊ณ  ์–ด๋–ป๊ฒŒ ๊ณ ์น  ์ˆ˜ ์žˆ๋Š”์ง€๋ฅผ ๋‹ค๋ฃฌ๋‹ค. > > ์ดํ›„ ๊ฐ•์˜์—์„œ๋Š” Backtracking ์ž์ฒด๋ฅผ ์—†์• ๋Š”, > ๋ณด๋‹ค ํšจ์œจ์ ์ธ Top-down parsing ๋ฐฉ๋ฒ•์„ ๋‹ค๋ฃฌ๋‹ค. "Recursive Descent Parsing์œผ๋กœ ํ•ญ์ƒ Parsing์ด ๊ฐ€๋Šฅํ•œ ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค." ### 3.4.1 `๋ฌธ์ œ` Left-recursion **๋ฌธ์ œ ์˜ˆ์‹œ:** $S \to Sa,\quad S \to b$ - ์ด ๋ฌธ๋ฒ•์ด ํ‘œํ˜„ํ•˜๋Š” ์–ธ์–ด: $ba^*$ (์ด ์–ธ์–ด๋Š” Regular โ€” Left-Regular ๋ฌธ๋ฒ•) - ํ•˜์ง€๋งŒ Recursive Descent Parsing์„ ์ ์šฉํ•˜๋ฉด: ``` S โ†’ Sa โ†’ Saa โ†’ Saaa โ†’ ... ``` $S$์—์„œ ์ถœ๋ฐœํ•˜๋ฉด ๊ฐ€์žฅ ๋จผ์ € $S \to Sa$๋ฅผ ์ ์šฉ โ†’ ๋‹ค์‹œ $S$๊ฐ€ ๋‚˜์˜ค๊ณ  โ†’ ๋˜ $S \to Sa$ โ†’ **๋ฌดํ•œ ๋ฃจํ”„** **์™œ ์ด๋Ÿฐ ์ผ์ด ์ƒ๊ธฐ๋‚˜?** โ†’ 1. Recursive Descent Parsing์€ Left-most derivation์„ ๋”ฐ๋ฅด๋Š”๋ฐ, 2. left-recursive ๋ฌธ๋ฒ•์—์„œ๋Š” 3. Terminal์„ ๋งŒ๋‚˜๊ธฐ ์ „์— 4. ๊ณ„์† ๊ฐ™์€ Non-terminal๋กœ ๊นŠ๊ฒŒ ํŒŒ๊ณ ๋“ค๊ธฐ ๋•Œ๋ฌธ. ### 3.4.2 `ํ•ด๊ฒฐ` ์ƒˆ๋กœ์šด NT ๋„์ž…ํ•ด Right-Recursive๋กœ ๋งŒ๋“ค๊ธฐ #### 3.4.2.1 $S \to Sa,\quad S \to b$ ์˜ˆ์‹œ ๊ธฐ์กด: $S \to Sa,\quad S \to b$ ๋ณ€ํ™˜: $S \to bS'$ $S' \to aS' \mid \epsilon$ ์ด ๋ฌธ๋ฒ•์€ left-recursive๊ฐ€ ์—†์œผ๋ฏ€๋กœ Recursive Descent Parsing ๊ฐ€๋Šฅ. #### 3.4.2.2 $S \to S\alpha_1 \mid S\alpha_2 \mid \cdots \mid S\alpha_n \mid \beta_1 \mid \beta_2 \mid \cdots \mid \beta_m$ ์˜ˆ์‹œ ๊ธฐ์กด: $S \to S\alpha_1 \mid S\alpha_2 \mid \cdots \mid S\alpha_n \mid \beta_1 \mid \beta_2 \mid \cdots \mid \beta_m$ ๋ณ€ํ™˜: $S \to \beta_1 S' \mid \beta_2 S' \mid \cdots \mid \beta_m S'$ $S' \to \alpha_1 S' \mid \alpha_2 S' \mid \cdots \mid \alpha_n S' \mid \epsilon$ #### 3.4.2.3 $S \to A\alpha \mid \delta, \quad A \to S\beta$ ์˜ˆ์‹œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ง์ ‘์ ์œผ๋กœ ๋ณด์ด์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๋„ ์žˆ๋‹ค: $S \to A\alpha \mid \delta, \quad A \to S\beta$ ๋Œ€์ž…ํ•˜๋ฉด: $S \to S\beta\alpha \mid \delta$ โ†’ ์‚ฌ์‹ค์ƒ left-recursive. ### 3.4.3 `ํ•ด๊ฒฐ` ์ผ๋ฐ˜์ ์ธ Left-recursive โ†’ Right-recursive ```pseudo // Non-terminal๋“ค์„ ์ž„์˜์˜ ์ˆœ์„œ๋กœ ์ •๋ ฌ // (์ˆœ์„œ์— ๋”ฐ๋ผ ๊ฒฐ๊ณผ ๋ฌธ๋ฒ•์ด ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์Œ) Non-terminal NT = {Aโ‚, ..., Aโ‚™}์„ ์ ๋‹นํ•œ ์ˆœ์„œ๋กœ ์ •๋ ฌ for i = 1 to n do for j = 1 to i - 1 do // Aแตข โ†’ Aโฑผฮณ ํ˜•ํƒœ์˜ production์ด ์žˆ์„ ๋•Œ // Aโฑผ์˜ ๋ชจ๋“  production์„ ๋Œ€์ž…ํ•ด์„œ // ๊ฐ„์ ‘ left-recursion์„ ์ง์ ‘ ํ˜•ํƒœ๋กœ ๋“œ๋Ÿฌ๋ƒ„ // ์˜ˆ: Aโฑผ โ†’ ฮดโ‚ | ฮดโ‚‚ ์ด๊ณ  Aแตข โ†’ Aโฑผฮณ ์ด๋ฉด // Aแตข โ†’ ฮดโ‚ฮณ | ฮดโ‚‚ฮณ ๋กœ ๋ฐ”๊ฟˆ // โ†’ ์ด ์‹œ์ ์—์„œ Aโฑผ๋Š” ์ด๋ฏธ ์ฒ˜๋ฆฌ๊ฐ€ ๋๋‚œ NT (j < i ์ด๋ฏ€๋กœ) // ์ฆ‰ Aโฑผ์˜ production์—๋Š” Aแตข๋ณด๋‹ค ์•ž์„  NT๋งŒ ๋“ฑ์žฅ์ด ๋ณด์žฅ๋จ Aโฑผ โ†’ ฮดโ‚ | ฮดโ‚‚ | ... | ฮดโ‚–์™€ Aแตข โ†’ Aโฑผฮณ์— ๋Œ€ํ•ด Aแตข โ†’ ฮดโ‚ฮณ | ฮดโ‚‚ฮณ | ... | ฮดโ‚–ฮณ๋กœ ๋Œ€์ฒด // j ๋ฃจํ”„๊ฐ€ ๋๋‚˜๋ฉด Aแตข์˜ ๋ชจ๋“  ๊ฐ„์ ‘ left-recursion์ด // ์ง์ ‘ left-recursion ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜๋œ ์ƒํƒœ // โ†’ ์ด์ œ ์ง์ ‘ left-recursion๋งŒ ์ œ๊ฑฐํ•˜๋ฉด ๋จ Aแตข์— ๋Œ€ํ•ด์„œ ์ง์ ‘ Left-recursion ์ œ๊ฑฐ ``` #### 3.4.3.1 $S \to A\alpha \mid \delta,\quad A \to S\beta$ ์˜ˆ์‹œ 1. Non-terminal ์ •๋ ฌ: $A, S$ ์ˆœ์„œ 2. $A$์— ๋Œ€ํ•ด: ์•„๋ฌด ์ผ๋„ ์ผ์–ด๋‚˜์ง€ ์•Š์Œ 1. $A$๊ฐ€ `i=1`์ผ ๋•Œ, ์•ˆ์ชฝ ๋ฃจํ”„๊ฐ€ `j = 1 to 0`. **0๋ฒˆ ๋”** โ†’ ๋ฃจํ”„ ์ž์ฒด๊ฐ€ ์‹คํ–‰์ด ์•ˆ ๋จ. 3. $S$์— ๋Œ€ํ•ด: - $A \to S\beta$์ด๊ณ  $S$์—๋Š” $A$๋ฅผ ์•ž์— ์“ฐ๋Š” production์ด ์žˆ์œผ๋ฏ€๋กœ ๋Œ€์ž…: $S \to S\beta\alpha \mid \delta$ - Direct left-recursion ์ œ๊ฑฐ: $S \to \delta S',\quad S' \to \beta\alpha S' \mid \epsilon$ 4. ์ตœ์ข… ๋ฌธ๋ฒ•: $S \to \delta S',\quad S' \to \beta\alpha S' \mid \epsilon$ > **๋‹จ, ์ด ์•Œ๊ณ ๋ฆฌ์ฆ˜๋„ ํ•ญ์ƒ ์ž‘๋™ํ•˜๋Š” ๊ฑด ์•„๋‹ˆ๋‹ค.** ๋ฌธ๋ฒ•์— $\epsilon$-production์ด๋‚˜ ์‚ฌ์ดํด(์˜ˆ: $A \to B,\ B \to A$)์ด ์žˆ์œผ๋ฉด ๋ณ„๋„ ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜๋‹ค. ## 3.5 ์ •๋ฆฌ > ยง3.4์—์„œ Left-recursion์„ ์ œ๊ฑฐํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋‹ค๋ค˜๋‹ค. > ์ด๋กœ์จ Recursive Descent Parsing์˜ ๊ฐœ๋…, ์•Œ๊ณ ๋ฆฌ์ฆ˜, ํ•œ๊ณ„, > ๊ทธ๋ฆฌ๊ณ  ํ•œ๊ณ„๋ฅผ ๊ทน๋ณตํ•˜๋Š” ๋ฐฉ๋ฒ•(๋ฌธ๋ฒ• ๋ณ€ํ™˜)์„ ๋ชจ๋‘ ๋‹ค๋ค˜๋‹ค. > > ๋‹ค์Œ ๊ฐ•์˜์—์„œ๋Š” Backtracking ์ž์ฒด๋ฅผ ์—†์• ๋Š” > ๋ณด๋‹ค ํšจ์œจ์ ์ธ Top-down parsing โ€” **LL(1) Parsing** ์„ ๋‹ค๋ฃฌ๋‹ค. - Recursive Descent Parsing์€ **Top-down parsing์˜ ํ•œ ๋ฐฉ๋ฒ•** - ํ•ต์‹ฌ ์•„์ด๋””์–ด: **Backtracking** - **Left-recursion์ด ์žˆ๋Š” ๋ฌธ๋ฒ•์—์„œ๋Š” ๋™์ž‘ํ•˜์ง€ ์•Š๋Š”๋‹ค** (๋ฌดํ•œ ๋ฃจํ”„) - ํ•ด๊ฒฐ: Left-recursive ๋ฌธ๋ฒ•์„ Right-recursive ๋ฌธ๋ฒ•์œผ๋กœ ๋ณ€ํ™˜ - Backtracking์€ ๋น„ํšจ์œจ์  โ†’ ๋ณด๋‹ค ํšจ์œจ์ ์ธ Top-Down Parsing์ด ํ•„์š”ํ•จ --- # 4. Top-Down Parsing (2) - LL(1) Parser ## 4.1 Backtracking์˜ ์›์ธ โ†’ Production ์„ ํƒ์„ LL(k) Parsing์œผ๋กœ ํ’€์–ด๋ณด์ž > ยง4.1์—์„œ๋Š” Recursive Descent Parsing์˜ ํ•ต์‹ฌ ํ•œ๊ณ„์ธ backtracking์ด ์™œ ๋ฐœ์ƒํ•˜๋Š”์ง€ ์งš๋Š”๋‹ค. ์ด ์›์ธ ํŒŒ์•…์ด ยง4.2 ์ดํ›„์— ๋“ฑ์žฅํ•˜๋Š” LL(1) Parsing ์ „์ฒด์˜ ์ถœ๋ฐœ์ ์ด๋‹ค. Recursive Descent Parsing์€ non-terminal์„ ๋งŒ๋‚  ๋•Œ๋งˆ๋‹ค production์„ ํ•˜๋‚˜ ๊ณจ๋ผ expandํ•œ๋‹ค. ๋ฌธ์ œ๋Š” **์–ด๋–ค production์„ ๊ณจ๋ผ์•ผ ํ• ์ง€ ๋ชจ๋ฅธ๋‹ค๋Š” ๊ฒƒ**์ด๋‹ค. ์ž˜๋ชป ์„ ํƒํ•˜๋ฉด ํ‹€๋ฆฐ ๊ฒƒ์„ ์ธ์‹ํ•˜๊ณ  ๋˜๋Œ์•„์™€์•ผ ํ•œ๋‹ค(backtracking). ์ด ๋น„ํšจ์œจ์„ ์—†์• ๋ ค๋ฉด, 1. lookahead token์„ ๋ณด๊ณ  2. **์˜ฌ๋ฐ”๋ฅธ production์„ ๋ฏธ๋ฆฌ ์˜ˆ์ธก**ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค. ### 4.1.1 LL(k) Parsing - **L**eft-to-right์œผ๋กœ ์ž…๋ ฅ์„ ์ฝ์œผ๋ฉด์„œ - **L**eft-most derivation์„ ๊ตฌ์„ฑํ•˜๊ณ  - **k**๊ฐœ์˜ token์„ ๋ฏธ๋ฆฌ ์‚ดํŽด๋ณด๊ณ (lookahead) production์„ ๊ฒฐ์ •ํ•œ๋‹ค. - ๋ง์…ˆ ๋ฌธ๋ฒ•์—์„œ, E์˜ P๋ฅผ ์„ ํƒํ•  ๋•Œ - ๋‹ค์Œ token์ด 1์ด๋‹ˆ๊นŒ - \[number] ์„ ํƒ ์šฐ๋ฆฌ๊ฐ€ ๋‹ค๋ฃจ๋Š” ๊ฒƒ์€ k=1์ธ **LL(1) Parsing**์ด๋‹ค. ### 4.1.2 LL(1)์—์„œ ์šฐ๋ฆฌ๊ฐ€ ํ’€์–ด์•ผ ํ•  ํ•ต์‹ฌ ๋ฌธ์ œ $A \to \alpha \mid \beta$ ์™€ $a = \text{tokens}[\text{idx}+1]$ ์ด ์ฃผ์–ด์กŒ์„ ๋•Œ, - `idx`๊ฐ€ ๋ญ์˜€์ง€? [[#3.2.1 ์ž…๋ ฅ ๋ฐ ๋ณ€์ˆ˜]] ์ฐธ๊ณ ! $A \to \alpha$ ์™€ $A \to \beta$ **์ค‘ ํ•˜๋‚˜๋ฅผ backtracking ์—†์ด ์„ ํƒ**ํ•˜๋Š” ๊ฒƒ. ### 4.1.3 Recursive Descent Parsing๊ณผ์˜ ๋น„๊ต โ€” ์‚ฌ์น™์—ฐ์‚ฐ ๋ฌธ๋ฒ• ์•„๋ž˜์˜ ๋ฌธ์ œ๋ฅผ, ์ด๋ฏธ ์•Œ๊ณ  ์žˆ๋Š” Recursive Descent Parsing์œผ๋กœ ํ’€์–ด๋ณด์ž. ```plain // ์‚ฌ์น™์—ฐ์‚ฐ ๋ฌธ๋ฒ• 1: Left-Recursive E ::= E + T | E - T | T T ::= T * F | T / F | F F ::= [id] | [num] | ( E ) ``` `์‚ฌ์น™์—ฐ์‚ฐ ๋ฌธ๋ฒ• 1`์€ Left-Recursiveํ•จ. โ†’ Recursive Descent Parsing์€ Left-Most Derivation์„ ๋”ฐ๋ฅด๋Š”๋ฐ, [[#4.1.1 LL(k) Parsing]] โ†’ Left-Recursive๋Š” T๋ฅผ ๋งŒ๋‚˜๊ธฐ ์ „์— ๊ณ„์† NT๋กœ ๊ฐ โ†’ ๋ฌดํ•œ ๋ฃจํ”„ [[#3.4.1 `๋ฌธ์ œ` Left-recursion]] ํ•ด๊ฒฐ์„ ์œ„ํ•ด์„œ๋Š”, [[#3.4.3 `ํ•ด๊ฒฐ` ์ผ๋ฐ˜์ ์ธ Left-recursive โ†’ Right-recursive]] ์ฒ˜๋Ÿผ Right-Recursive๋กœ ๋ณ€ํ™˜ํ•ด์•ผ ํ•จ. ```plain // ์‚ฌ์น™์—ฐ์‚ฐ ๋ฌธ๋ฒ• 2: Left-Recursive๋ฅผ Right-Recursive๋กœ ๋ณ€ํ™˜ E ::= T E' E' ::= + T E' | - T E' | T ::= F T' T' ::= * F T' | / F T' | F ::= [id] | [num] | ( E ) ``` `์‚ฌ์น™์—ฐ์‚ฐ ๋ฌธ๋ฒ• 2`๋Š” Right-Recursive โ†’ ์ด์ œ Recursive Descent Parsing ์‹œ๋„ ๊ฐ€๋Šฅ. ```plain // Recursive Descent Parsing ๊ณผ์ • 1 Focus = E' Tokens[idx] = - ``` ์—ฌ๊ธฐ์„œ ์–ด๋–ค Production์„ ํƒํ•ด์•ผ ํ• ๊นŒ? > [[#3.2 ๐Ÿšจ Recursive Descent Parsing โ€” ์ •์˜]] ์˜ ๊ณผ์ •์„ ๋‹ค์‹œ ๋ณต๊ธฐํ•ด๋ณด๋ฉด, > Focus๊ฐ€ NT์— ์žˆ์„ ๊ฒฝ์šฐ Case 1๋กœ ๋„˜์–ด๊ฐ€ Production์„ ๊ฒฐ์ •ํ•œ๋‹ค. > ์—ฌ๊ธฐ์„œ๋Š” Focus๊ฐ€ E'์— ์žˆ์œผ๋‹ˆ Case 1๋กœ ๋„˜์–ด๊ฐ€ Production์„ ๊ฒฐ์ •ํ•ด์•ผ ํ•œ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” 1๋ฒˆ์งธ(0-base) rule์ธ `E' โ†’ - T E'` ์„ ํƒํ•˜๋ฉด, `Tokens[idx] = -` ์ด๋ฏ€๋กœ, ๋ฐฑํŠธ๋ž˜ํ‚น์€ ์ข€ ํ•˜๊ฒ ์ง€๋งŒ Production ๊ณ ๋ฅด๋Š” ๋ฐ ์„ฑ๊ณตํ•œ๋‹ค. ```plain // Recursive Descent Parsing ๊ณผ์ • 2 Focus = E Tokens[idx] = ( ``` ๋‹ค์Œ ๊ณผ์ •์œผ๋กœ ๋„˜์–ด์™€์„œ, ์—ฌ๊ธฐ์„œ๋Š” ์–ด๋–ค Production์„ ํ•ด์•ผ ํ• ๊นŒ? ์ง๊ด€์ ์œผ๋กœ `(` ๋ฅผ ์†Œ๋น„ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด `F โ†’ ( E )`๊ฐ€ ๋งž๋Š” ์„ ํƒ์ด์ง€๋งŒ, ๋” ๋ณต์žกํ•œ ๊ณผ์ •์ด ํ•„์š”ํ•˜๋‹ค. E์˜ production์ด `E โ†’ T E'` ํ•˜๋‚˜๋‹ˆ๊นŒ ์ด๊ฑธ ์„ ํƒํ•ด ๋ณด์ž. โ†’ production์ด ํ•˜๋‚˜๋ผ์„œ ๊ดœ์ฐฎ์„๊นŒ? โ†’ ๊ทผ๋ฐ `E โ†’ T E'`๋ฅผ ์„ ํƒํ•˜๋ฉด T๋กœ ๋‚ด๋ ค๊ฐ€๊ณ , โ†’ `T โ†’ F T'`๋กœ ๋‚ด๋ ค๊ฐ€๊ณ  โ†’ `F โ†’ ( E )`... ์ด๋ ‡๊ฒŒ ๊ณ„์† expandํ•ด์•ผ ํ•œ๋‹ค. โ†’ ๊ฒฐ๊ตญ, ๊ฐ™์€ ๋ฌธ์ œ๋ฅผ ๋‹ค์Œ ๋‹จ๊ณ„์—์„œ ๊ณ„์† ๋ฐ˜๋ณต. ### 4.1.4 Recursive Descent Parsing๊ณผ์˜ ๋น„๊ต โ€” ๊ฐ„๋‹จํ•œ ๋ฌธ๋ฒ• ๋‹ค๋ฅธ ์˜ˆ์‹œ๋ฅผ ๋ณด์ž. ์ด๋ฒˆ์—๋„ Recursive Descent Parsing์„ ์‹œ๋„ํ•œ๋‹ค. ```plain // ๊ฐ„๋‹จํ•œ ๋ฌธ๋ฒ• S ::= A a | B b | c A ::= x | B ::= y | ``` ํŒŒ์‹ฑ ์‹คํ–‰ ์ค‘์— ์ด๋Ÿฐ ๊ณผ์ •๋„ ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค. ```plain // Recursive Descent Parsing ๊ณผ์ • 1 Focus = S Tokens[idx] = a ``` ์—ฌ๊ธฐ์„œ๋Š” ์–ด๋–ค Production์„ ํƒํ•ด์•ผ ํ• ๊นŒ? ์ง๊ด€์ ์œผ๋กœ a๋ฅผ ์†Œ๋น„ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด `S โ†’ A a`์—์„œ `A โ†’ `๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์œผ๋‹ˆ `S โ†’ A a`๋กœ ๊ฐ€๋Š” ๊ฒŒ ๋งž์ง€๋งŒ, ๊ทธ๋Ÿด ์ˆ˜๊ฐ€ ์—†๋‹ค. ์•Œ ๋ฐฉ๋ฒ•์ด ์—†์œผ๋‹ˆ๊นŒ ;; A๊ฐ€ nullable์ด๋ผ `A a` ์—์„œ ์ฒซ ํ† ํฐ์ด `a`๊ฐ€ ๋  ์ˆ˜ ์žˆ๊ณ , B๋Š” nullable์ด์ง€๋งŒ `B b` ์—์„œ ์ฒซ ํ† ํฐ์€ `y` ์•„๋‹ˆ๋ฉด `b`์ง€ `a`๊ฐ€ ๋  ์ˆ˜ ์—†๋‹ค. ์ฆ‰ ์ด๊ฑธ ํŒ๋‹จํ•˜๋ ค๋ฉด, "`A a` ๋กœ๋ถ€ํ„ฐ ์ฒซ ๋ฒˆ์งธ๋กœ ๋‚˜์˜ฌ ์ˆ˜ ์žˆ๋Š” terminal์ด ๋ญ”๊ฐ€"๋ฅผ **์ฒด๊ณ„์ ์œผ๋กœ ๊ณ„์‚ฐ**ํ•ด์•ผ ํ•œ๋‹ค โ†’ ์šฐ์„ , FIRST๋ผ๋Š” ๊ฐœ๋…์„ ๋„์ž…ํ•ด๋ณด์ž. ## 4.2 FIRST(ฮณ) โ†’ ฮต ์œ ๋„ ๊ฐ€๋Šฅ์„ฑ์€ ์–ด๋–ป๊ฒŒ ์ฐพ์ง€? > ยง4.1์—์„œ "lookahead token์„ ๋ณด๊ณ  production์„ ์˜ˆ์ธกํ•˜์ž"๋Š” ์•„์ด๋””์–ด๋ฅผ ์–ป์—ˆ๋‹ค. > ยง4.2์—์„œ๋Š” ๊ทธ ์˜ˆ์ธก์˜ ๊ทผ๊ฑฐ๊ฐ€ ๋˜๋Š” FIRST ์ง‘ํ•ฉ์„ ์ •์˜ํ•˜๊ณ  ๊ณ„์‚ฐํ•˜๋Š” ๋ฒ•์„ ๋‹ค๋ฃฌ๋‹ค. > > ๊ทธ๋Ÿฐ๋ฐ ยง4.2.3์—์„œ ๋ณด๋“ฏ, > FIRST๋งŒ์œผ๋กœ๋Š” ฮต-production์ด ์žˆ๋Š” ๊ฒฝ์šฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜์ง€ ๋ชปํ•œ๋‹ค. > ์ด ๋ฌธ์ œ๋Š” ยง4.3์˜ NULLABLE๊ณผ ยง4.4์˜ FOLLOW๋กœ ์ด์–ด์ง„๋‹ค. ### 4.2.1 FIRST(ฮณ) ์ •์˜ > ๐Ÿ’ก $\gamma \in (T \cup NT)^+$ ์˜€๋‹ค. NT, T ๋‹ค ํฌํ•จ๋œ ๋ฌด์–ธ๊ฐ€์ธ๋ฐ $\epsilon$์€ ์•„๋‹Œ ๊ฒƒ. $\text{FIRST}(\gamma) = { a \in T \mid \gamma \Rightarrow^* a\beta \text{ for some } \beta }$ ฮณ๋กœ๋ถ€ํ„ฐ ์œ ๋„๋  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ๋ฌธ์žฅ์˜ **๊ฐ€์žฅ ์ฒ˜์Œ์— ๋“ฑ์žฅํ•  ์ˆ˜ ์žˆ๋Š” terminal๋“ค์˜ ์ง‘ํ•ฉ**์ด๋‹ค. #### 4.2.1.1 FIRST(ฮณ) ์˜ˆ์‹œ โ€” ์‚ฌ์น™์—ฐ์‚ฐ ๋ฌธ๋ฒ• ``` // ์‚ฌ์น™์—ฐ์‚ฐ ๋ฌธ๋ฒ• F ::= [id] | [num] | ( E ) // FIRST(ฮณ) ์˜ˆ์‹œ FIRST(F) = { [id], [num], ( } ``` #### 4.2.1.2 FIRST(ฮณ) ํšจ๊ณผ - $A \to \gamma_1 \mid \gamma_2 \mid \cdots \mid \gamma_n$ ์ผ ๋•Œ, - ๋ชจ๋“  ์Œ์— ๋Œ€ํ•ด $\text{FIRST}(\gamma_i) \cap \text{FIRST}(\gamma_j) = \emptyset$ ์ด๋ฉด (์„œ๋กœ์†Œ์ด๋ฉด) - $\forall i, j, \text{FIRST}(\gamma_i) \cap \text{FIRST}(\gamma_j) = \emptyset$ - lookahead token ํ•˜๋‚˜๋งŒ ๋ณด๊ณ  backtracking ์—†์ด production์„ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. โ†’ ๊ทธ๋Ÿผ ์ด๊ฑด ์–ด๋–ป๊ฒŒ ๊ณ„์‚ฐํ• ๊นŒ? ### 4.2.2 FIRST(ฮณ) ๊ณ„์‚ฐ ์•„์ด๋””์–ด โ€” NT๋ฅผ ๊ณ„์† ํ™•์žฅํ•˜์ž | ๊ทœ์น™ ํ˜•ํƒœ | ๊ท€๊ฒฐ | | -------------------------------------- | ------------------------------------------- | | $A \to a$ (T) | $\{a\} \subseteq \text{FIRST}(A)$ | | $A \to B$ (NT) | $\text{FIRST}(B) \subseteq \text{FIRST}(A)$ | | $A \to BC$, $B \to \epsilon \vert ...$ | $\text{FIRST}(C) \subseteq \text{FIRST}(A)$ | ์„ธ ๋ฒˆ์งธ ๊ฒฝ์šฐ, $B$๊ฐ€ $\epsilon$์„ ๋งŒ๋“ค ์ˆ˜ **์žˆ์„ ๋•Œ๋งŒ** C์˜ FIRST๊ฐ€ A์˜ FIRST์— ํฌํ•จ๋œ๋‹ค. ์ด๊ฒƒ์ด NULLABLE์˜ ํ•„์š”์„ฑ์œผ๋กœ ์ด์–ด์ง„๋‹ค. ### 4.2.3 FIRST ๊ณ„์‚ฐ์˜ ํ•œ๊ณ„ โ†’ NULLABLE์ด ํ•„์š”ํ•œ ์ด์œ  $A \to B,C$ ์ด๊ณ  $B \to \epsilon$ ์ด ์ง์ ‘ ์—†์ง€๋งŒ $B \Rightarrow^* \epsilon$ ์ธ ๊ฒฝ์šฐ, ๊ทธ ๊ฒฝ์šฐ์—๋„ B๊ฐ€ ์‚ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์œผ๋‹ˆ๊นŒ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ FIRST(C) โІ FIRST(A) ๊ฐ€ ์„ฑ๋ฆฝํ•ด์•ผ ํ•œ๋‹ค. ํ•˜์ง€๋งŒ, ๋‹จ์ˆœํžˆ production ๊ทœ์น™๋งŒ ๋ณด์•„์„œ๋Š” B๊ฐ€ *์ตœ์ข…์ ์œผ๋กœ* ์‚ฌ๋ผ์งˆ ์ˆ˜ ์žˆ๋Š”์ง€ ์•Œ ์ˆ˜ ์—†๋‹ค. ์ฆ‰, ฮต ์œ ๋„ ๊ฐ€๋Šฅ์„ฑ - **NULLABLE** - ์„ ๋ณ„๋„๋กœ ๊ณ„์‚ฐํ•ด์•ผ ํ•œ๋‹ค. ## 4.3 NULLABLE(X) โ€” ฮต ์œ ๋„ ๊ฐ€๋Šฅ์„ฑ ํŒ๋ณ„ > ยง4.2.3์—์„œ FIRST ๊ณ„์‚ฐ์ด ๋ง‰ํžˆ๋Š” ์ง€์ ์„ ํ™•์ธํ–ˆ๋‹ค. > P ์—ฌ๋Ÿฟ์„ ๊ฑฐ์ณ ฮต์œผ๋กœ ์œ ๋„๋  ๊ฒฝ์šฐ, ๋ฌธ๋ฒ•๋งŒ ๋ด์„œ๋Š” ์•Œ ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. > > ยง4.3์—์„œ๋Š” ๊ทธ ๋ง‰ํžŒ ์ง€์ ์„ ๋šซ์–ด์ฃผ๋Š” NULLABLE์„ ์ •์˜ํ•˜๊ณ  ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ ๊ณ„์‚ฐํ•œ๋‹ค. > ์ด ๊ฒฐ๊ณผ๋Š” ยง4.2์˜ FIRST ์•Œ๊ณ ๋ฆฌ์ฆ˜๊ณผ ยง4.4์˜ FOLLOW ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ชจ๋‘์—์„œ ์‚ฌ์šฉ๋œ๋‹ค. ### 4.3.1 NULLABLE(X) ์ •์˜ $X$๋กœ๋ถ€ํ„ฐ $\epsilon$์„ ์œ ๋„ํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด, NULLABLE($X$) = true. ์ˆ˜์‹์œผ๋กœ ์“ฐ๋ฉด, $\text{NULLABLE}(X) = \text{true} \iff X \Rightarrow^* \epsilon$ โ†’ ๊ทธ๋Ÿผ ์ด๊ฑด ์–ด๋–ป๊ฒŒ ๊ณ„์‚ฐํ• ๊นŒ? ### 4.3.2 NULLABLE(X) ๊ณ„์‚ฐ ์•„์ด๋””์–ด โ€” NT๋ฅผ ๊ณ„์† ํ™•์žฅํ•˜์ž [[#4.2.2 FIRST(ฮณ) ๊ณ„์‚ฐ ์•„์ด๋””์–ด โ€” NT๋ฅผ ๊ณ„์† ํ™•์žฅํ•˜์ž]] ์™€ ๊ฐ™์€ ์•„์ด๋””์–ด! ์ตœ์ข…์ ์œผ๋กœ $\epsilon$์— ๋‹ฟ๋Š” ๊ฒŒ ๋ชฉํ‘œ๋‹ˆ๊นŒ, NT๋ฅผ ์ญ‰์ญ‰์ญ‰ P๋กœ ํ™•์žฅํ•˜๋ฉฐ T๋ฅผ ์ฐพ์•„๊ฐ€๋ฉด ๋œ๋‹ค. ### 4.3.3 NULLABLE(X) ์•Œ๊ณ ๋ฆฌ์ฆ˜ โ€” ์ฝ”๋“œ ``` // NULLABLE(X) ๊ณ„์‚ฐ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ž…๋ ฅ: (T, NT, S, P) // Grammar ๋ณ€์ˆ˜: // Map<T โˆช NT, bool> // ์ดˆ๊ธฐ๊ฐ’: ๋ชจ๋“  ฮฑ์— ๋Œ€ํ•ด NULLABLE[ฮฑ] = false NULLABLE โ† {} NULLABLE' // ์ด๋ฒˆ iteration์—์„œ ๋ณ€ํ™”๊ฐ€ ์žˆ์—ˆ๋Š”์ง€ ์ฒดํฌํ•˜๊ธฐ ์œ„ํ•œ ๋ณต์‚ฌ๋ณธ do // ์ด๋ฒˆ ๋ฃจํ”„ ์‹œ์ž‘ ์ „ ์ƒํƒœ๋ฅผ ์ €์žฅ NULLABLE' โ† copy(NULLABLE) // T, NT ์ค‘ ํ•˜๋‚˜์ธ ฮฑ์— ๋Œ€ํ•ด for ฮฑ โˆˆ T โˆช NT do // ์ด๋ฏธ nullable๋กœ ํŒ๋ช…๋‚œ ๊ฑด ์Šคํ‚ต if NULLABLE[ฮฑ] = true then continue // ฮฑ๊ฐ€ T์ผ ๊ฒฝ์šฐ elif ฮฑ โˆˆ T then // ํ„ฐ๋ฏธ๋„์€ ์ ˆ๋Œ€ ฮต์„ ์œ ๋„ํ•  ์ˆ˜ ์—†์Œ // ์ขŒ๋ณ€์ด๋‹ˆ๊นŒ~ NULLABLE[ฮฑ] = false; continue // ฮฑ๊ฐ€ T์ผ ๊ฒฝ์šฐ ๋‹ค ๊ฑธ๋Ÿฌ์กŒ์œผ๋‹ˆ๊นŒ // ์—ฌ๊ธฐ์„œ๋ถ€ํ„ฐ ฮฑ๋Š” NT A // A์˜ P ์ง‘ํ•ฉ ์ค‘ ํ•˜๋‚˜ ฮณ๋ฅผ A๋กœ ๋‘๊ณ , A์— ๋Œ€ํ•ด for A โ† ฮณ โˆˆ P[A] do // ฮณ = ฮณโ‚ฮณโ‚‚...ฮณโ‚™ ์ด๋ผ ํ•  ๋•Œ if ฮณ = ฮต then // production์ด ์ง์ ‘ ฮต์ด๋ฉด ๋ฐ”๋กœ nullable NULLABLE[A] = true; break elif all NULLABLE[ฮณแตข] = true then // ฮณ๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๋ชจ๋“  ๊ธฐํ˜ธ๊ฐ€ nullable์ด๋ฉด // A โ†’ ฮณโ‚ฮณโ‚‚...ฮณโ‚™ โ†’* ฮต ์ด ๊ฐ€๋Šฅ // ์ฆ‰ A๋„ nullable NULLABLE[A] = true; break // NULLABLE์ด ์ด๋ฒˆ ๋ฃจํ”„์—์„œ ํ•œ ๋ฒˆ๋„ ์•ˆ ๋ฐ”๋€Œ์—ˆ์œผ๋ฉด ์ข…๋ฃŒ // (๋” ์ด์ƒ ์ƒˆ๋กœ nullable๋กœ ํŒ๋ช…๋  ๊ธฐํ˜ธ๊ฐ€ ์—†์Œ) while (NULLABLE โ‰  NULLABLE') ``` ### 4.3.4 NULLABLE(X) ์•Œ๊ณ ๋ฆฌ์ฆ˜ โ€” ์ข…๋ฃŒ์„ฑ NULLABLE ๋งต์˜ ๊ฐ’์€ `false โ†’ true` ๋ฐฉํ–ฅ์œผ๋กœ๋งŒ ๋ฐ”๋€” ์ˆ˜ ์žˆ๋‹ค. $T \cup NT$๊ฐ€ ์œ ํ•œํ•˜๋ฏ€๋กœ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ํšŸ์ˆ˜๋Š” ์œ ํ•œํ•˜๊ณ , ๊ทธ๋Ÿฌ๋ฏ€๋กœ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ๋ฐ˜๋“œ์‹œ ์ข…๋ฃŒ๋œ๋‹ค. ### 4.3.4 NULLABLE(X) ์•Œ๊ณ ๋ฆฌ์ฆ˜ โ€” ์˜ˆ์‹œ ```plain // ์‚ฌ์น™์—ฐ์‚ฐ ๋ฌธ๋ฒ• 3 S ::= E E ::= T E' E' ::= + T E' | - T E' | T ::= F T' T' ::= * F T' | / F T' | F ::= S [id] | [num] | ( E ) ``` NULLABLE์„ ํ‘œ๋กœ ํ‘œํ˜„ํ•˜๋ฉฐ ๋”ฐ๋ผ๊ฐ€ ๋ณด์ž. ์‹œ์ž‘ ์ƒํƒœ | | NULLABLE | | --- | -------- | | S | false | | E | false | | E' | false | | T | false | | T' | false | | F | false | ๊ณผ์ • ```plain ฮฑ = S ฮฑ๊ฐ€ NT์ด๋ฏ€๋กœ P[S]์˜ production ์ˆœํšŒ: - S โ†’ E ฮณ = E, ฮณ = ฮต ์•„๋‹˜ NULLABLE[E] = false์ด๋ฏ€๋กœ all NULLABLE[ฮณแตข] = true ๋ถˆ๋งŒ์กฑ โ†’ NULLABLE[S] ๋ณ€ํ™” ์—†์Œ (false ์œ ์ง€) ฮฑ = E ฮฑ๊ฐ€ NT์ด๋ฏ€๋กœ P[E]์˜ production ์ˆœํšŒ: - E โ†’ T E' ฮณ = TE', ฮณ = ฮต ์•„๋‹˜ NULLABLE[T] = false์ด๋ฏ€๋กœ all NULLABLE[ฮณแตข] = true ๋ถˆ๋งŒ์กฑ โ†’ NULLABLE[E] ๋ณ€ํ™” ์—†์Œ (false ์œ ์ง€) ฮฑ = E' ฮฑ๊ฐ€ NT์ด๋ฏ€๋กœ P[E']์˜ production ์ˆœํšŒ: - E' โ†’ + T E' ฮณ = +TE', ฮณ = ฮต ์•„๋‹˜ NULLABLE[+] = false์ด๋ฏ€๋กœ ๋ถˆ๋งŒ์กฑ - E' โ†’ - T E' ฮณ = -TE', ฮณ = ฮต ์•„๋‹˜ NULLABLE[-] = false์ด๋ฏ€๋กœ ๋ถˆ๋งŒ์กฑ - E' โ†’ ฮต ฮณ = ฮต โ†’ NULLABLE[E'] = true; break โ†’ NULLABLE[E'] = true๋กœ ๋ณ€๊ฒฝ! โœ… ฮฑ = T ฮฑ๊ฐ€ NT์ด๋ฏ€๋กœ P[T]์˜ production ์ˆœํšŒ: - T โ†’ F T' ฮณ = FT', ฮณ = ฮต ์•„๋‹˜ NULLABLE[F] = false์ด๋ฏ€๋กœ ๋ถˆ๋งŒ์กฑ โ†’ NULLABLE[T] ๋ณ€ํ™” ์—†์Œ (false ์œ ์ง€) ฮฑ = E' ์ด๋ฏธ NULLABLE์ด๋ฏ€๋กœ ์Šคํ‚ต ฮฑ = T' ฮฑ๊ฐ€ NT์ด๋ฏ€๋กœ P[T']์˜ production ์ˆœํšŒ: - T' โ†’ * F T' ฮณ = *FT', ฮณ = ฮต ์•„๋‹˜ NULLABLE[*] = false์ด๋ฏ€๋กœ ๋ถˆ๋งŒ์กฑ - T' โ†’ / F T' ฮณ = /FT', ฮณ = ฮต ์•„๋‹˜ NULLABLE[/] = false์ด๋ฏ€๋กœ ๋ถˆ๋งŒ์กฑ - T' โ†’ ฮต ฮณ = ฮต โ†’ NULLABLE[T'] = true; break โ†’ NULLABLE[T'] = true๋กœ ๋ณ€๊ฒฝ! โœ… ฮฑ = F ฮฑ๊ฐ€ NT์ด๋ฏ€๋กœ P[F]์˜ production ์ˆœํšŒ: - F โ†’ [id] NULLABLE[[id]] = false์ด๋ฏ€๋กœ ๋ถˆ๋งŒ์กฑ - F โ†’ [num] NULLABLE[[num]] = false์ด๋ฏ€๋กœ ๋ถˆ๋งŒ์กฑ - F โ†’ ( E ) NULLABLE[(] = false์ด๋ฏ€๋กœ ๋ถˆ๋งŒ์กฑ โ†’ NULLABLE[F] ๋ณ€ํ™” ์—†์Œ (false ์œ ์ง€) // 1ํšŒ ์ˆœํšŒ ๊ฒฐ๊ณผ: // E', T'๋งŒ true๋กœ ๋ฐ”๋€œ โ†’ NULLABLE โ‰  NULLABLE' โ†’ ๋ฃจํ”„ ๊ณ„์† // ----------------------------------------------- // 2๋ฒˆ์งธ iteration ฮฑ = S - S โ†’ E NULLABLE[E] = false โ†’ ๋ถˆ๋งŒ์กฑ โ†’ ๋ณ€ํ™” ์—†์Œ ฮฑ = E - E โ†’ T E' NULLABLE[T] = false โ†’ ๋ถˆ๋งŒ์กฑ (T'๊ฐ€ true์—ฌ๋„ T๊ฐ€ false๋ผ ์•ˆ๋จ) โ†’ ๋ณ€ํ™” ์—†์Œ ฮฑ = E' โ†’ ์ด๋ฏธ true โ†’ continue ฮฑ = T - T โ†’ F T' NULLABLE[F] = false โ†’ ๋ถˆ๋งŒ์กฑ โ†’ ๋ณ€ํ™” ์—†์Œ ฮฑ = T' โ†’ ์ด๋ฏธ true โ†’ continue ฮฑ = F - F โ†’ [id], [num], (E) ์ „๋ถ€ false โ†’ ๋ณ€ํ™” ์—†์Œ // 2ํšŒ ์ˆœํšŒ ๊ฒฐ๊ณผ: // ์•„๋ฌด๊ฒƒ๋„ ์•ˆ ๋ฐ”๋€œ โ†’ NULLABLE = NULLABLE' โ†’ ์ข…๋ฃŒ! // ์ตœ์ข… ๊ฒฐ๊ณผ: // E' = true, T' = true, ๋‚˜๋จธ์ง€ ์ „๋ถ€ false ``` ์ตœ์ข… ๊ฒฐ๊ณผ | | NULLABLE | | --- | -------- | | S | false | | E | false | | E' | false | | T | false | | T' | false | | F | false | ## 4.4 FIRST(ฮณ) โ€” NULLABLE์„ ๋ฐ˜์˜ํ•œ ์™„์ „ํ•œ ๋ฒ„์ „ > ยง4.3์—์„œ NULLABLE์„ ๊ตฌํ–ˆ๋‹ค. > ยง4.4์—์„œ๋Š” ๊ทธ๊ฒƒ์„ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›์•„ FIRST๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๊ณ„์‚ฐํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ œ์‹œํ•œ๋‹ค. > ์ด FIRST ๊ฒฐ๊ณผ๋Š” ยง4.5์˜ FOLLOW ์•Œ๊ณ ๋ฆฌ์ฆ˜๊ณผ ยง4.6์˜ select ํ•จ์ˆ˜์—์„œ ์‚ฌ์šฉ๋œ๋‹ค. ### 4.4.1 FIRST ์•Œ๊ณ ๋ฆฌ์ฆ˜ โ€” ํ•ต์‹ฌ ์›๋ฆฌ $A \to \alpha,\gamma,\beta$ ์ผ ๋•Œ, $\text{NULLABLE}(\alpha) = \text{true}$ ์ด๋ฉด ์ฆ‰, $\alpha$๊ฐ€ NULLABLE์ด๋ฉด $\alpha$๊ฐ€ ์ „๋ถ€ ์‚ฌ๋ผ์ง€๊ณ  $\gamma$๊ฐ€ ์ฒซ ์ž๋ฆฌ์— ์˜ฌ ์ˆ˜ ์žˆ๋Š”๋ฐ, ๊ทธ๋ ‡๋‹ค๋ฉด "$A$๋กœ๋ถ€ํ„ฐ ์œ ๋„๋˜๋Š” ๋ฌธ์žฅ์˜ ๋งจ ์ฒซ terminal์ด $\gamma$์—์„œ ๋‚˜์˜ฌ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ" $\text{FIRST}(\gamma) \subseteq \text{FIRST}(A)$ ### 4.4.2 FIRST ์•Œ๊ณ ๋ฆฌ์ฆ˜ โ€” ์ฝ”๋“œ ``` ์ž…๋ ฅ: (T, NT, S, P) // Grammar NULLABLE // ์•ž์„œ ๊ณ„์‚ฐํ•œ NULLABLE ๋งต. Map<NT, bool> ๋ณ€์ˆ˜: // ๊ฐ ๊ธฐํ˜ธ์˜ FIRST ์ง‘ํ•ฉ์„ ์ €์žฅ. ์ดˆ๊ธฐ๊ฐ’์€ ๋ชจ๋‘ ๊ณต์ง‘ํ•ฉ FIRST โ† {} // Map<T โˆช NT, Set<T>> FIRST' // ์ด๋ฒˆ iteration์—์„œ ๋ณ€ํ™”๊ฐ€ ์žˆ์—ˆ๋Š”์ง€ ์ฒดํฌํ•˜๊ธฐ ์œ„ํ•œ ๋ณต์‚ฌ๋ณธ do FIRST' โ† copy(FIRST) for ฮฑ โˆˆ T โˆช NT do if ฮฑ โˆˆ T then // ํ„ฐ๋ฏธ๋„ a์˜ FIRST๋Š” ์ž๊ธฐ ์ž์‹  // ex) FIRST(+) = {+} FIRST[a] = {a}; continue // ์—ฌ๊ธฐ์„œ๋ถ€ํ„ฐ ฮฑ๋Š” non-terminal A for A โ† ฮณ โˆˆ P[A] do // ฮณ = ฮณโ‚ฮณโ‚‚...ฮณโ‚™ (๊ฐ ฮณแตข๋Š” T ๋˜๋Š” NT) // ฮณ๋ฅผ ๋Œ๋ฉฐ for 1 โ‰ค i โ‰ค n do if i = 1 then // ์ฒซ ๋ฒˆ์งธ ๊ธฐํ˜ธ์˜ FIRST๋Š” ๋ฌด์กฐ๊ฑด A์˜ FIRST์— ํฌํ•จ // ex) A โ†’ B C ์—์„œ FIRST(B) โІ FIRST(A) FIRST[A] = FIRST[A] โˆช FIRST[ฮณโ‚] elif NULLABLE[ฮณแตขโ‚‹โ‚] = false then // ๋ฐ”๋กœ ์•ž ๊ธฐํ˜ธ ฮณแตขโ‚‹โ‚์ด nullableํ•˜์ง€ ์•Š์œผ๋ฉด // ฮณแตขโ‚‹โ‚์ด ๋ฐ˜๋“œ์‹œ ๋ญ”๊ฐ€๋ฅผ ๋งŒ๋“ค์–ด๋‚ด๋ฏ€๋กœ // ฮณแตข ์ดํ›„๋Š” ์ฒซ ๋ฒˆ์งธ๋กœ ์˜ฌ ์ˆ˜ ์—†์Œ โ†’ ๋” ๋ณผ ํ•„์š” ์—†์Œ break else // ฮณแตขโ‚‹โ‚์ด nullableํ•˜๋ฉด ฮณแตขโ‚‹โ‚์ด ์‚ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ // ฮณแตข๊ฐ€ ์ฒซ ๋ฒˆ์งธ๋กœ ์˜ฌ ์ˆ˜ ์žˆ์Œ // โ†’ FIRST[ฮณแตข] โІ FIRST[A] FIRST[A] = FIRST[A] โˆช FIRST[ฮณแตข] // FIRST๊ฐ€ ์ด๋ฒˆ ๋ฃจํ”„์—์„œ ํ•œ ๋ฒˆ๋„ ์•ˆ ๋ฐ”๋€Œ์—ˆ์œผ๋ฉด ์ข…๋ฃŒ // (๋” ์ด์ƒ ์ถ”๊ฐ€๋  ์›์†Œ๊ฐ€ ์—†์Œ) while (FIRST โ‰  FIRST') ``` ### 4.4.3 FIRST ์•Œ๊ณ ๋ฆฌ์ฆ˜ โ€” ์ข…๋ฃŒ์„ฑ FIRST ์ง‘ํ•ฉ์˜ ์›์†Œ๋Š” ์ถ”๊ฐ€๋งŒ ๋˜๊ณ  ์‚ญ์ œ๋˜์ง€ ์•Š๋Š”๋‹ค. Terminal ์ง‘ํ•ฉ์ด ์œ ํ•œํ•˜๋ฏ€๋กœ ๋ฐ˜๋“œ์‹œ ์ข…๋ฃŒ๋œ๋‹ค. ### 4.4.4 FIRST ์•Œ๊ณ ๋ฆฌ์ฆ˜ โ€” ์˜ˆ์‹œ ์ดˆ๊ธฐ ์ƒํƒœ (๋ชจ๋‘ ๋น„์–ด ์žˆ์Œ) | ๊ธฐํ˜ธ | NULLABLE | FIRST | | --- | -------- | ----- | | S | false | | | E | false | | | E' | true | | | T | false | | | T' | true | | | F | false | | ๊ณผ์ • ๋‚˜์ค‘์— ์‹œ๊ฐ„ ๋˜๋ฉด ๋ณด์ž; ์ดํ•ด๋Š” ํ–ˆ์œผ๋‹ˆ๊นŒ ์ตœ์ข… ๊ฒฐ๊ณผ | ๊ธฐํ˜ธ | NULLABLE | FIRST | | --- | -------- | ------------------ | | S | false | { [id], [num], ( } | | E | false | { [id], [num], ( } | | E' | true | { +, - } | | T | false | { [id], [num], ( } | | T' | true | { *, / } | | F | false | { [id], [num], ( } | ## 4.5 FOLLOW(ฮณ) โ€” NULLABLEํ•œ production ์„ ํƒ์„ ์œ„ํ•œ ๋„๊ตฌ > ยง4.4๊นŒ์ง€ ๊ตฌํ•œ FIRST๋งŒ์œผ๋กœ๋„ ๋งŽ์€ ๊ฒฝ์šฐ production์„ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. > ๊ทธ๋Ÿฌ๋‚˜ ยง4.5.1์˜ ์˜ˆ์‹œ์ฒ˜๋Ÿผ, focus๊ฐ€ NULLABLEํ•œ non-terminal์ด๊ณ  lookahead token์ด FIRST์— ์—†์„ ๋•Œ๋Š” "ฮต-production์„ ์„ ํƒํ•ด๋„ ๋˜๋Š”๊ฐ€?"๋ฅผ ํŒ๋‹จํ•  ์ˆ˜ ์—†๋‹ค. ยง4.5์—์„œ๋Š” ์ด ํŒ๋‹จ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๋Š” FOLLOW๋ฅผ ์ •์˜ํ•˜๊ณ  ๊ณ„์‚ฐํ•œ๋‹ค. FIRST์™€ FOLLOW๊ฐ€ ๋ชจ๋‘ ์ค€๋น„๋˜๋ฉด ยง4.6์˜ select ํ•จ์ˆ˜๋ฅผ ์™„์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค. ### 4.5.1 FOLLOW๊ฐ€ ํ•„์š”ํ•œ ์ƒํ™ฉ ๋‹ค์‹œ Recursive Descent Parsing์„ ์ˆ˜ํ–‰ ์ค‘์ผ ๋•Œ, ``` Focus = E' Tokens[idx] = ) E' ::= + T E' | - T E' | ``` lookahead `)`๋Š” FIRST(E')์— ์—†๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด $E' \to \epsilon$์„ ์„ ํƒํ•ด๋„ ๋˜๋Š”๊ฐ€? โ†’ `)` ๊ฐ€ E' ๋‹ค์Œ์— ์˜ฌ ์ˆ˜ ์žˆ๋Š” token์ด๋ผ๋ฉด ๊ฐ€๋Šฅํ•˜๋‹ค. ์ด๊ฒƒ์ด FOLLOW์ด๋‹ค. ### 4.5.2 FOLLOW(ฮณ) ์ •์˜ $\text{FOLLOW}(\gamma) = { a \in T \mid \exists, \alpha, \beta,, S \Rightarrow^* \alpha,\gamma,a,\beta }$ ฮณ์˜ **๋ฐ”๋กœ ์˜ค๋ฅธ์ชฝ์— ๋“ฑ์žฅํ•  ์ˆ˜ ์žˆ๋Š” terminal๋“ค์˜ ์ง‘ํ•ฉ**. - $\{)\} \subseteq \text{FOLLOW}(E)$ - $F \to (E)$ ์—์„œ E ์˜ค๋ฅธ์ชฝ์— `)` - $\text{FOLLOW}(S) = \{\$\}$ โ€” S๋Š” ์‹œ์ž‘ ๊ธฐํ˜ธ์ด๋ฏ€๋กœ ์˜ค๋ฅธ์ชฝ์—” EOF($)๋งŒ ### 4.5.3 FOLLOW ์•Œ๊ณ ๋ฆฌ์ฆ˜ โ€” ํ•ต์‹ฌ ์›๋ฆฌ | ๊ทœ์น™ ํ˜•ํƒœ | ๊ท€๊ฒฐ | | --------------------------------------------------------------------------------- | ------------------------------------------------------ | | $A \to \alpha \gamma \beta \delta$, $\text{NULLABLE}(\beta) = \text{true}$ | $\text{FIRST}(\delta) \subseteq \text{FOLLOW}(\gamma)$ | | $A \to \alpha \gamma \beta \delta$, $\text{NULLABLE}(\beta\delta) = \text{true}$ | $\text{FOLLOW}(A) \subseteq \text{FOLLOW}(\gamma)$ | | | | - ฮณ ๋ฐ”๋กœ ๋‹ค์Œ์— ฮฒ๊ฐ€ ์žˆ๋Š”๋ฐ, ฮฒ๊ฐ€ nullable์ด๋ฉด ฮฒ๊ฐ€ ์‚ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์Œ. - ๊ทธ๋Ÿฌ๋ฉด ฮณ ๋‹ค์Œ์— ฮด๊ฐ€ ๋ฐ”๋กœ ์˜ฌ ์ˆ˜ ์žˆ์œผ๋‹ˆ๊นŒ, - ฮด์˜ ์ฒซ ๋ฒˆ์งธ terminal๋“ค์ด ฮณ์˜ FOLLOW์— ํฌํ•จ. - ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, ฮฒฮด๊ฐ€ NULLABLE์ด๋ฉด ฮฒฮด๊ฐ€ ๋ชจ๋‘ ์‚ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์Œ. - ๊ทธ๋Ÿฌ๋ฉด ฮณ ์ดํ›„๊ฐ€ ์ „๋ถ€ ์‚ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์Œ. - ๊ทธ๋ ‡๋‹ค๋ฉด ฮณ ๋‹ค์Œ์— ์˜ฌ ์ˆ˜ ์žˆ๋Š” ๊ฒŒ ๊ณง $A$ ๋‹ค์Œ์— ์˜ฌ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ๊ณผ ๊ฐ™์•„์ง. > ๐Ÿ’ก $\text{NULLABLE}(\beta\delta) = \text{NULLABLE}(\beta) \wedge \text{NULLABLE}(\delta)$ ### 4.5.4 FOLLOW ์•Œ๊ณ ๋ฆฌ์ฆ˜ โ€” ์ฝ”๋“œ ``` ์ž…๋ ฅ: (T, NT, S, P), NULLABLE, FIRST ๋ณ€์ˆ˜: FOLLOW โ† {} // MAP<T U NT, Set<T>> FOLLOW' โ† {} // ๋ณต๋ถ™ํ•ด์„œ iteration๋งˆ๋‹ค ํ™•์ธ์šฉ do FOLLOW' โ† copy(FOLLOW) for ฮฑ โˆˆ T โˆช NT do // ํ„ฐ๋ฏธ๋„์€ production์˜ ์ขŒ๋ณ€์ด ๋  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ ์ถ”์ ํ•  ํ•„์š” ์—†์Œ if ฮฑ โˆˆ T then continue // ์—ฌ๊ธฐ์„œ๋ถ€ํ„ฐ ฮฑ๋Š” non-terminal A for A โ† ฮณ โˆˆ P[A] do // ฮณ = ฮณโ‚ ฮณโ‚‚ โ€ฆ ฮณโ‚™ // ฮณ ์•ˆ์˜ ๊ฐ ๊ธฐํ˜ธ ฮณแตข์— ๋Œ€ํ•ด FOLLOW๋ฅผ ๊ณ„์‚ฐ for 1 โ‰ค i โ‰ค n do if โˆ€j โˆˆ {i+1,โ€ฆ,n} NULLABLE(ฮณโฑผ) then // ฮณแตข ๋’ค์˜ ๋ชจ๋“  ๊ธฐํ˜ธ(ฮณแตขโ‚Šโ‚โ€ฆฮณโ‚™)๊ฐ€ ์ „๋ถ€ nullable์ด๋ฉด // ฮณแตข ์ดํ›„๊ฐ€ ์ „๋ถ€ ์‚ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์Œ // โ†’ ฮณแตข๊ฐ€ ์‚ฌ์‹ค์ƒ A์˜ ๋งจ ๋์ด ๋˜๋ฏ€๋กœ // โ†’ A ๋‹ค์Œ์— ์˜ค๋Š” ๊ฒƒ์ด ๊ณง ฮณแตข ๋‹ค์Œ์— ์˜ฌ ์ˆ˜ ์žˆ์Œ FOLLOW(ฮณแตข) = FOLLOW(ฮณแตข) โˆช FOLLOW(A) for i < j โ‰ค n do if โˆ€k โˆˆ {i+1,โ€ฆ,j-1} NULLABLE(ฮณโ‚–) then // ฮณแตข์™€ ฮณโฑผ ์‚ฌ์ด์˜ ๋ชจ๋“  ๊ธฐํ˜ธ๊ฐ€ nullable์ด๋ฉด // ๊ทธ ์‚ฌ์ด๊ฐ€ ์ „๋ถ€ ์‚ฌ๋ผ์ ธ์„œ ฮณโฑผ๊ฐ€ ฮณแตข ๋ฐ”๋กœ ๋‹ค์Œ์— ์˜ฌ ์ˆ˜ ์žˆ์Œ // โ†’ ฮณโฑผ์˜ ์ฒซ terminal์ด ฮณแตข ๋‹ค์Œ์— ์˜ฌ ์ˆ˜ ์žˆ์Œ FOLLOW(ฮณแตข) = FOLLOW(ฮณแตข) โˆช FIRST(ฮณโฑผ) while (FOLLOW โ‰  FOLLOW') ``` ### 4.5.5 FOLLOW ์•Œ๊ณ ๋ฆฌ์ฆ˜ โ€” ์ข…๋ฃŒ์„ฑ FOLLOW ์ง‘ํ•ฉ๋„ ๋‹จ์กฐ ์ฆ๊ฐ€ํ•˜๋ฉฐ Terminal ์ง‘ํ•ฉ์ด ์œ ํ•œํ•˜๋ฏ€๋กœ ๋ฐ˜๋“œ์‹œ ์ข…๋ฃŒ๋œ๋‹ค. ### 4.5.6 FOLLOW ์•Œ๊ณ ๋ฆฌ์ฆ˜ โ€” ์˜ˆ์‹œ ์•„ ์ด๊ฒƒ๋„ ๋‚˜์ค‘์— ใ…ˆใ„ด๊ธ‰ํ•จ์ง€๊ธˆ |๊ธฐํ˜ธ|NULLABLE|FIRST|FOLLOW| |---|---|---|---| |S|false|[id] [num] (|$| |E|false|[id] [num] (|$ )| |E'|true|+ -|$ )| |T|false|[id] [num] (|$ + - )| |T'|true|* /|$ + - )| |F|false|[id] [num] (|$ + - * / )| ## 4.6 LL(1) Parsing ์•Œ๊ณ ๋ฆฌ์ฆ˜ โ€” select์™€ Parsing Table > ยง4.2~4.5์—์„œ NULLABLE, FIRST, FOLLOW๋ฅผ ๋ชจ๋‘ ๊ตฌํ–ˆ๋‹ค. > ยง4.6์—์„œ๋Š” ์ด ์„ธ ๊ฐ€์ง€๋ฅผ ์‹ค์ œ production ์„ ํƒ ํ•จ์ˆ˜ select๋กœ ํ†ตํ•ฉํ•˜๊ณ , > ์ด๋ฅผ 2D ํ…Œ์ด๋ธ”๋กœ ๊ตฌํ˜„ํ•˜์—ฌ O(1)์— production์„ ๊ฒฐ์ •ํ•˜๋Š” Parsing Table์„ ๋งŒ๋“ ๋‹ค. ### 4.6.1 LL(1) Parsing ์•Œ๊ณ ๋ฆฌ์ฆ˜ โ€” ์ฝ”๋“œ โ†’ select๊ฐ€ ๋ญ˜๊นŒ? ```pseudo // ์ „์ฒด ์ž…๋ ฅ: (T, NT, S, P) // Grammar tokens // Token๋“ค์˜ list (Lexer๊ฐ€ ์คฌ์œผ๋‹ˆ!) ๋ณ€์ˆ˜: tree โ† S // ํŒŒ์ŠคํŠธ๋ฆฌ์˜ ๋ฃจํŠธ ๋…ธ๋“œ (์†์„ฑ: parent, children, rule) focus โ† S // ํ˜„์žฌ ์ฒ˜๋ฆฌ ์ค‘์ธ ํŠธ๋ฆฌ ๋…ธ๋“œ idx โ† 0 // ํ˜„์žฌ ์ฝ๊ณ  ์žˆ๋Š” token์˜ ์œ„์น˜ stack โ† [] // ์•„์ง ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š์€ ๋…ธ๋“œ๋“ค์„ ์Œ“์•„๋‘๋Š” ์Šคํƒ while (true) do if (focus โˆˆ NT) then // focus๊ฐ€ non-terminal์ด๋ฉด production์„ ์„ ํƒํ•ด expand goto Case 1 else if (idx < len(tokens) && focus = tokens[idx]) then // focus๊ฐ€ terminal์ด๊ณ  ํ˜„์žฌ token๊ณผ ์ผ์น˜ํ•˜๋ฉด ์†Œ๋น„ goto Case 2 else if (idx = len(tokens) && stack = []) then // ๋ชจ๋“  token์„ ์†Œ๋น„ํ–ˆ๊ณ  ์Šคํƒ๋„ ๋น„์—ˆ์œผ๋ฉด ํŒŒ์‹ฑ ์„ฑ๊ณต return tree // LL(1)์—์„œ๋Š” backtracking ์—†์Œ // else goto Case 3 // Backtrack โ†’ ์‚ญ์ œ๋จ ``` ```pseudo // Case 1 // Recursive Descent ๋ฒ„์ „ (์‚ญ์ œ๋จ): // (focus โ†’ ฮฑโ‚...ฮฑโ‚™) โ† P[focus][focus.rule] // focus.rule โ† focus.rule + 1 // โ†’ production์„ ์ˆœ์„œ๋Œ€๋กœ ํ•˜๋‚˜์”ฉ ์‹œ๋„ํ–ˆ์Œ (backtracking ๋ฐœ์ƒ ์›์ธ) // ๊ธฐ์กด Recursive Descent์™€์˜ ์ฐจ์ด // production์„ `focus.rule` ์ˆœ์„œ๋กœ ์‹œ๋„ํ•˜๋Š” ๋Œ€์‹ , // Parsing Table ์กฐํšŒ ํ•œ ๋ฒˆ์œผ๋กœ production์„ ๋ฐ”๋กœ ๊ฒฐ์ •. // ๊ทธ๋Ÿฌ๋ฏ€๋กœ Backtracking๋„ ์‚ฌ๋ผ์ง„๋‹ค. // LL(1) ๋ฒ„์ „: // select๋กœ lookahead token์„ ๋ณด๊ณ  production์„ ๋”ฑ ํ•˜๋‚˜ ๊ฒฐ์ • (focus โ†’ ฮฑโ‚...ฮฑโ‚™) โ† select(P, focus, tokens[idx+1]) for 1 โ‰ค i โ‰ค n do // ์„ ํƒํ•œ production์˜ ๊ธฐํ˜ธ๋“ค์„ ํŠธ๋ฆฌ์— ์ž์‹์œผ๋กœ ์—ฐ๊ฒฐ connect(focus, ฮฑแตข) for n โ‰ฅ i โ‰ฅ 2 do // ์ฒซ ๋ฒˆ์งธ(ฮฑโ‚) ๋นผ๊ณ  ๋‚˜๋จธ์ง€๋ฅผ ์—ญ์ˆœ์œผ๋กœ ์Šคํƒ์— push // (๋‚˜์ค‘์— ์ˆœ์„œ๋Œ€๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด) stack.push(ฮฑแตข) // ์ฒซ ๋ฒˆ์งธ ์ž์‹์„ ๋‹ค์Œ focus๋กœ focus โ† ฮฑโ‚ ``` ```pseudo // Case 2 // focus๊ฐ€ terminal์ด๊ณ  ํ˜„์žฌ token๊ณผ ์ผ์น˜ํ•˜๋Š” ์ƒํ™ฉ // ํ˜„์žฌ token์„ ์†Œ๋น„ํ•˜๊ณ  ๋‹ค์Œ token์œผ๋กœ ์ด๋™ idx โ† idx + 1 // ์Šคํƒ์—์„œ ๋‹ค์Œ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ๋…ธ๋“œ๋ฅผ ๊บผ๋ƒ„ focus โ† stack.pop() ``` ### 4.6.2 LL(1) Parsing ์•Œ๊ณ ๋ฆฌ์ฆ˜ โ€” select(P, focus, lookahead) #### 4.6.2.1 select โ€” ์•„์ด๋””์–ด select๋Š” ๊ฒฐ๊ตญ ์–ด๋–ค Production์„ ๊ณจ๋ผ์•ผ ํ•˜๋Š”์ง€ ์„ ํƒํ•จ. focus๊ฐ€ A๊ณ , A -> a | b | c ... ๋ญ ์ด๋Ÿฐ ์‹์œผ๋กœ ์žˆ๋‹ค๊ณ  ์น˜๋ฉด, production์ด ์—ฌ๋Ÿฌ ๊ฐœ์ผ ๋•Œ, lookahead token์„ ๋ณด๊ณ  **์–ด๋–ค production์„ ๊ณจ๋ผ์•ผ ํ•˜๋Š”๊ฐ€**๋ฅผ ๊ฒฐ์ •! focus $\leftarrow \alpha$ ์— ๋Œ€ํ•ด: focus๊ฐ€ $\alpha$๋กœ ์ „๊ฐœ๋˜๋Š” ๊ฒฝ์šฐ์—, focus๊ฐ€ A์ผ ๋•Œ, $A \to \alpha$ ๋ผ๋Š” production ํ›„๋ณด์— ๋Œ€ํ•ด: **๊ฒฝ์šฐ 1:** $\text{lookahead} \in \text{FIRST}(\alpha)$ ์ด๋ฉด โ†’ $\alpha$๋ฅผ ์ „๊ฐœํ–ˆ์„ ๋•Œ ์ฒซ ๋ฒˆ์งธ๋กœ lookahead๊ฐ€ ๋‚˜์˜ฌ ์ˆ˜ ์žˆ์œผ๋‹ˆ๊นŒ โ†’ **$A \to \alpha$ ์„ ํƒ** **๊ฒฝ์šฐ 2:** $\text{NULLABLE}(\alpha) = \text{true}$ ์ด๊ณ  $\text{lookahead} \in \text{FOLLOW}(\alpha)$ ์ด๋ฉด โ†’ $\alpha$๊ฐ€ ํ†ต์งธ๋กœ ์‚ฌ๋ผ์งˆ ์ˆ˜ ์žˆ๊ณ , ์‚ฌ๋ผ์ง„ ํ›„์— lookahead๊ฐ€ ๋ฐ”๋กœ ์˜ฌ ์ˆ˜ ์žˆ์œผ๋‹ˆ๊นŒ โ†’ **$A \to \alpha$ ์„ ํƒ** ๋‘˜ ๋‹ค ํ•ด๋‹น ์—†์œผ๋ฉด โ†’ ์ด production์€ ํ›„๋ณด์—์„œ ํƒˆ๋ฝ. | ์กฐ๊ฑด | ์„ ํƒ | | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------- | | $\text{lookahead} \in \text{FIRST}(\alpha)lt;br>โ†’ $\alpha$๋ฅผ ์ „๊ฐœํ–ˆ์„ ๋•Œ ์ฒซ ๋ฒˆ์งธ๋กœ ๋‚˜์˜ฌ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ๋“ค ์ค‘์—<br>โ†’ lookahead๊ฐ€ ์žˆ์œผ๋‹ˆ๊นŒ<br>โ†’ **$A \to \alpha$ ์„ ํƒ** | focus $\leftarrow \alpha$ ์„ ํƒ | | $\text{NULLABLE}(\alpha) = \text{true}$ ์ด๊ณ  $\text{lookahead} \in \text{FOLLOW}(\alpha)lt;br>โ†’ $\alpha$๊ฐ€ ํ†ต์งธ๋กœ ์‚ฌ๋ผ์งˆ ์ˆ˜ ์žˆ๊ณ ,<br>โ†’ ์‚ฌ๋ผ์ง„ ํ›„์— ๊ทธ ๋’ค๋กœ lookahead๊ฐ€ ๋ฐ”๋กœ ์˜ฌ ์ˆ˜ ์žˆ์œผ๋‹ˆ๊นŒ <br>โ†’ **$A \to \alpha$ ์„ ํƒ**<br> | focus $\leftarrow \alpha$ ์„ ํƒ | #### 4.6.2.2 select โ€” ์˜ˆ์ œ **๋ฌธ๋ฒ•** ``` S ::= E E ::= T E' E' ::= + T E' | - T E' | ฮต T ::= F T' T' ::= * F T' | / F T' | ฮต F ::= [id] | [num] | ( E ) ``` **NULLABLE / FIRST / FOLLOW ํ‘œ** | |NULLABLE|FIRST|FOLLOW| |---|---|---|---| |S|false|[id] [num] (|$| |E|false|[id] [num] (|$ )| |E'|true|+ -|$ )| |T|false|[id] [num] (|$ + - )| |T'|true|* /|$ + - )| |F|false|[id] [num] (|$ + - * / )| **select ํ‘œ** = Parsing Table | | + | - | * | / | [id] | [num] | ( | ) | $ | | --- | ------- | ------- | ------- | ------- | ------ | ------- | ----- | --- | --- | | S | | | | | Sโ†’E | Sโ†’E | Sโ†’E | | | | E | | | | | Eโ†’TE' | Eโ†’TE' | Eโ†’TE' | | | | E' | E'โ†’+TE' | E'โ†’-TE' | | | | | | E'โ†’ | E'โ†’ | | T | | | | | Tโ†’FT' | Tโ†’FT' | Tโ†’FT' | | | | T' | | | T'โ†’*FT' | T'โ†’/FT' | | | | T'โ†’ | T'โ†’ | | F | | | | | Fโ†’[id] | Fโ†’[num] | Fโ†’(E) | | | ### 4.6.3 LL(1) Parsing ์•Œ๊ณ ๋ฆฌ์ฆ˜ โ€” Parsing Table select๋ฅผ 2์ฐจ์› ํ…Œ์ด๋ธ”๋กœ ๊ตฌํ˜„ํ•œ ๊ฒƒ. - **Row**: focus (non-terminal) - **Column**: lookahead (terminal) - **Entry**: ์„ ํƒํ•  production - **๋นˆ ์นธ**: ์˜ค๋ฅ˜(Error) | | + | - | * | / | [id] | [num] | ( | ) | $ | | --- | ------- | ------- | ------- | ------- | ------ | ------- | ----- | --- | --- | | S | | | | | Sโ†’E | Sโ†’E | Sโ†’E | | | | E | | | | | Eโ†’TE' | Eโ†’TE' | Eโ†’TE' | | | | E' | E'โ†’+TE' | E'โ†’-TE' | | | | | | E'โ†’ | E'โ†’ | | T | | | | | Tโ†’FT' | Tโ†’FT' | Tโ†’FT' | | | | T' | | | T'โ†’*FT' | T'โ†’/FT' | | | | T'โ†’ | T'โ†’ | | F | | | | | Fโ†’[id] | Fโ†’[num] | Fโ†’(E) | | | ## 4.7 LL(1) Parsing์˜ ํ•œ๊ณ„ โ€” Conflict > ยง4.6์˜ Parsing Table์ด ์ž˜ ๋™์ž‘ํ•˜๋ ค๋ฉด ๊ฐ ์นธ์— production์ด **์ •ํ™•ํžˆ ํ•˜๋‚˜**์—ฌ์•ผ ํ•œ๋‹ค. ยง4.7์—์„œ๋Š” ์นธ์— production์ด ๋‘ ๊ฐœ ์ด์ƒ ๋“ค์–ด์˜ค๋Š” ์ถฉ๋Œ(Conflict) ์ƒํ™ฉ๊ณผ ๊ทธ ํ•ด๊ฒฐ ์ „๋žต์„ ๋‹ค๋ฃฌ๋‹ค. ### 4.7.1 FIRST/FIRST Conflict โ†’ Left Factoring์œผ๋กœ ํ•ด๊ฒฐ $A \to \alpha \mid \beta$ ์ผ ๋•Œ $\text{FIRST}(\alpha) \cap \text{FIRST}(\beta) \neq \emptyset$ (์„œ๋กœ์†Œ๊ฐ€ ์•„๋‹Œ) ๊ฒฝ์šฐ โ†’ ๊ฐ™์€ lookahead์— production์ด ๋‘ ๊ฐœ ๋Œ€์‘๋œ๋‹ค. (Parsing Table์˜ ํ•œ ์นธ์— ๋‘ P๊ฐ€ ๋“ค์–ด์˜จ๋‹ค) **๋Œ€ํ‘œ ์›์ธ: Left-recursion** ``` E ::= E + a | b โ†’ FIRST(E + a) = FIRST(E) = { b } โ†’ FIRST(b) = { b } โ†’ ์ถฉ๋Œ! ``` **Left-recursion์ด ์—†์–ด๋„ ๋ฐœ์ƒ ๊ฐ€๋Šฅ** ``` S ::= E | E a E ::= b | ``` E๊ฐ€ nullable์ด๋‹ˆ๊นŒ: - FIRST(E) = {b} ์ด๊ณ  NULLABLE(E) = true - FIRST(E a) = FIRST(E) โˆช {a} = {b, a} (E๊ฐ€ nullable์ด๋‹ˆ๊นŒ a๋„ ํฌํ•จ) ๊ทธ๋Ÿฌ๋ฉด select ํ‘œ์—์„œ focus = S, lookahead = `b` ์ผ ๋•Œ: (๋ฌธ๋ฒ• ๋ณด๊ณ  ์ƒ๊ฐํ•ด๋ณด๋ฉด) - Sโ†’E : b โˆˆ FIRST(E) โ†’ ๊ฒฝ์šฐ 1 โ†’ ํ•ด๋‹น - Sโ†’E a : b โˆˆ FIRST(E a) โ†’ ๊ฒฝ์šฐ 1 โ†’ ํ•ด๋‹น โ†’ ๊ฐ™์€ ์นธ์— ๋‘ ๊ฐœ โ†’ **FIRST/FIRST Conflict** **ํ•ด๊ฒฐ: Right-recursion์œผ๋กœ ๋ณ€ํ™˜ + Left Factoring** ๊ณตํ†ต prefix๋ฅผ factoringํ•˜์—ฌ ๋ถ„๋ฆฌํ•œ๋‹ค. ``` // ์›๋ณธ (์ถฉ๋Œ) S ::= E | E a E ::= b | // Left Factoring ํ›„ // S์˜ ์šฐ๋ณ€์ด E, E a๋ฏ€๋กœ E๋ผ๋Š” ๊ณตํ†ต prefix๊ฐ€ ์žˆ์Œ // ๊ทธ๋Ÿฌ๋‹ˆ๊นŒ ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„์„ S'๋กœ ๋บŒ S ::= E S' S' ::= | a E ::= b | ``` ๊ทธ๋Ÿฌ๋ฉด select ํ‘œ์—์„œ: - focus = S์ผ ๋•Œ๋Š” ๋ฌด์กฐ๊ฑด Sโ†’E S' ํ•˜๋‚˜๋ฟ โ†’ conflict ์—†์Œ - focus = S'์ผ ๋•Œ lookahead๊ฐ€ `a`๋ฉด S'โ†’a, `
๋‚˜ ๋‹ค๋ฅธ ๊ฑฐ๋ฉด S'โ†’ โ†’ conflict ์—†์Œ ### 4.7.2 FIRST/FOLLOW Conflict โ†’ Substition์œผ๋กœ ํ•ด๊ฒฐ NULLABLEํ•œ production์ด ์žˆ์„ ๋•Œ, **lookahead๊ฐ€ FIRST์—๋„ ์†ํ•˜๊ณ  ๋™์‹œ์— FOLLOW์—๋„ ์†ํ•˜๋ฉด** select์˜ ๊ฒฝ์šฐ 1๊ณผ ๊ฒฝ์šฐ 2๊ฐ€ ๋™์‹œ์— ์ ์šฉ๋˜์–ด ์ถฉ๋Œ์ด ๋ฐœ์ƒํ•œ๋‹ค. **์˜ˆ์‹œ:** ``` // ๋ฌธ๋ฒ• S ::= A a b A ::= a | // ์ถฉ๋Œ ์˜ˆ์‹œ โ†’ FIRST(A) = { a }, FOLLOW(A) = { $, a } โ†’ lookahead = a ์ผ ๋•Œ: Aโ†’a (๊ฒฝ์šฐ 1)์™€ Aโ†’ (๊ฒฝ์šฐ 2) ๋ชจ๋‘ ํ•ด๋‹น โ†’ ์ถฉ๋Œ ``` **ํ•ด๊ฒฐ: Substitution โ†’ ์ดํ›„ Left Factoring** A์˜ production์„ A๊ฐ€ ์“ฐ์ธ ์ž๋ฆฌ์— **์ง์ ‘ ๋Œ€์ž…**. ``` // ์›๋ž˜ ๋ฌธ๋ฒ• S ::= A a b A ::= a | // Substitution ์ ์šฉ S ::= a a b | a b // ์ด๋Ÿฌ๋‹ˆ๊นŒ FIRST/FIRST Conflict ์ถ”๊ฐ€ ๋ฐœ์ƒ // Left Factoring ์ถ”๊ฐ€ ์ ์šฉ S ::= a S' S' ::= a b | b ``` > ๐Ÿ’ก > Substitution์˜ ๊ฒฐ๊ณผ๋กœ FIRST/FIRST Conflict๊ฐ€ ์ƒˆ๋กœ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค. > ๊ทธ ๊ฒฝ์šฐ Left Factoring์„ ์ถ”๊ฐ€๋กœ ์ ์šฉํ•œ๋‹ค. ### 4.7.3 FOLLOW/FOLLOW Conflict ``` A ::= B | C B ::= C ::= โ†’ FOLLOW(B) โˆฉ FOLLOW(C) โ‰  โˆ… ``` $A \to B \mid C$ ์ธ๋ฐ B๋„ C๋„ ๋‘˜ ๋‹ค nullable์ผ ๋•Œ, ๊ฐ™์€ lookahead์— ๋Œ€ํ•ด B๋ฅผ ์„ ํƒํ•ด์•ผ ํ• ์ง€ C๋ฅผ ์„ ํƒํ•ด์•ผ ํ• ์ง€ ๊ฒฐ์ •ํ•  ์ˆ˜ ์—†๋Š” ์ƒํ™ฉ. ๋‘˜ ๋‹ค ์–ด์ฐจํ”ผ ฮต์ด ๋˜๋‹ˆ๊นŒ FOLLOW(B)๋ž‘ FOLLOW(C)๊ฐ€ ๋‘˜ ๋‹ค FOLLOW(A)๋ฅผ ํฌํ•จํ•˜๊ฒŒ ๋˜๊ณ , Conflict ๋ฐœ์ƒํ•˜๊ฒŒ ๋จ. ์ด ๊ฒฝ์šฐ๋Š” **๋ฌธ๋ฒ• ์ž์ฒด๊ฐ€ ๋ชจํ˜ธ(ambiguous)ํ•จ**์„ ์˜๋ฏธํ•˜๋ฏ€๋กœ ํ†ต์ƒ์ ์œผ๋กœ๋Š” ๋ณ„๋„๋กœ ๋‹ค๋ฃจ์ง€ ์•Š๋Š”๋‹ค. ($A \to B \to \epsilon$ ๊ณผ $A \to C \to \epsilon$ ์ด ๋™์‹œ์— ์„ฑ๋ฆฝํ•˜์—ฌ ๊ฐ™์€ ๋ฌธ์ž์—ด์— ๋‘ ๊ฐœ์˜ ํŒŒ์ŠคํŠธ๋ฆฌ๊ฐ€ ์ƒ๊ธด๋‹ค.) ### 4.7.4 Conflict ์ œ๊ฑฐ ๊ฐ€๋Šฅ ๋ฒ”์œ„ ``` Context-Free Grammar โ”œโ”€โ”€ LL(1) Grammar โ† Conflict๋ฅผ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ฒ”์œ„ โ”‚ โ””โ”€โ”€ Regular Grammar โ””โ”€โ”€ Ambiguous Grammar โ† Conflict ์ œ๊ฑฐ ๋ถˆ๊ฐ€ ``` **Conflict๋Š” LL(1) ๋ฌธ๋ฒ•์ธ ๊ฒฝ์šฐ์—๋งŒ ํ•ญ์ƒ ์ œ๊ฑฐ ๊ฐ€๋Šฅํ•˜๋‹ค.** ## 4.8 ์ข…ํ•ฉ ์˜ˆ์ œ โ€” ๋ง์…ˆ ๋ฌธ๋ฒ•์˜ LL(1) ๋ณ€ํ™˜๊ณผ Parsing > ยง4.7๊นŒ์ง€ ๋ฐฐ์šด FIRST/FIRST Conflict์™€ Left Factoring์„ ์‹ค์ œ ๋ฌธ๋ฒ•์— ์ ์šฉํ•˜๊ณ , > ยง4.2~4.5์—์„œ ๋ฐฐ์šด NULLABLEยทFIRSTยทFOLLOW ๊ณ„์‚ฐ์„ ๊ฑฐ์ณ > ์ตœ์ข… Parsing Table์„ ์™„์„ฑํ•˜๋Š” ์ „์ฒด ํ๋ฆ„์„ ํ™•์ธํ•œ๋‹ค. ### 4.8.1 ์›๋ณธ ๋ฌธ๋ฒ• โ†’ FIRST/FIRST Conflict ํ™•์ธ ``` S ::= E | E + S E ::= ( S ) | [number] ``` $\text{FIRST}(E) = \text{FIRST}(E + S) = {(,, [\text{number}]}$ โ†’ **FIRST/FIRST Conflict** ๋ฐœ์ƒ. ### 4.8.2 Left Factoring์œผ๋กœ ๋ฌธ๋ฒ• ๋ณ€ํ™˜ ``` S ::= E S' S' ::= | + S E ::= ( S ) | [number] ``` ### 4.8.3 NULLABLE ยท FIRST ยท FOLLOW ๊ณ„์‚ฐ |๊ธฐํ˜ธ|NULLABLE|FIRST|FOLLOW| |---|---|---|---| |S|false|(, [number]|$, )| |S'|**true**|+|$, )| |E|false|(, [number]|$, +, )| ### 4.8.4 Parsing Table ์™„์„ฑ | |+|(|)|[number]|$| |---|---|---|---|---|---| |S||Sโ†’ES'||Sโ†’ES'|| |S'|S'โ†’+S||S'โ†’ฮต||S'โ†’ฮต| |E||Eโ†’(S)||Eโ†’[number]|| ๊ฐ ์นธ์— production์ด ํ•˜๋‚˜์”ฉ๋งŒ ๋“ค์–ด์žˆ๋‹ค โ†’ **Conflict ์—†์Œ, LL(1) ๋ฌธ๋ฒ•**. ### 4.8.5 ์ž…๋ ฅ `(1+2+(3+4))+5` ํŒŒ์‹ฑ ๊ฒฐ๊ณผ Parsing Table์— ๋”ฐ๋ผ backtracking ์—†์ด ํŒŒ์ŠคํŠธ๋ฆฌ๋ฅผ ์œ ์ผํ•˜๊ฒŒ ๋ณต์›ํ•œ๋‹ค: ``` S โ”œโ”€โ”€ E โ†’ ( S ) โ”‚ โ””โ”€โ”€ S โ”‚ โ”œโ”€โ”€ E โ†’ [1] โ”‚ โ””โ”€โ”€ S' โ†’ + S โ”‚ โ””โ”€โ”€ S โ”‚ โ”œโ”€โ”€ E โ†’ [2] โ”‚ โ””โ”€โ”€ S' โ†’ + S โ”‚ โ””โ”€โ”€ S โ”‚ โ”œโ”€โ”€ E โ†’ ( S ) โ”‚ โ”‚ โ””โ”€โ”€ S โ”‚ โ”‚ โ”œโ”€โ”€ E โ†’ [3] โ”‚ โ”‚ โ””โ”€โ”€ S' โ†’ + S โ”‚ โ”‚ โ””โ”€โ”€ S โ”‚ โ”‚ โ”œโ”€โ”€ E โ†’ [4] โ”‚ โ”‚ โ””โ”€โ”€ S' โ†’ ฮต โ”‚ โ””โ”€โ”€ S' โ†’ ฮต โ””โ”€โ”€ S' โ†’ + S โ””โ”€โ”€ S โ”œโ”€โ”€ E โ†’ [5] โ””โ”€โ”€ S' โ†’ ฮต ```