Context-free grammar
Context-free grammar(CFG)๋ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์ ์ฝ๋๋ฅผ parsing ํ๋ ๋ฐ์ ์ ์ฉํ ์ด๋ก ์ ๋๊ตฌ๋ก ์ฐ์
๋๋ค. ์ผ๋ก๋ก, parsing ๋๊ตฌ ์ค ํ๋์ธ Yacc๋ CFG์ฉ parser๋ฅผ ์์ฑํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ค์ ๋ก๋ ๋ค์์ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด๊ฐ context-free ํ์ง ์์ ๋ฌธ๋ฒ์ ๊ฐ์ง๋๋ค.
C
C๋ ๋๋ฆฌ ์ฌ์ฉ๋๋ ์ธ์ด ์ค ํ๋์ด๋ฉฐ ๊ฑฐ์ context-free ํ ๋ฌธ๋ฒ์ ๊ฐ์ ธ ์ ๋ด์ฉ์ ์ค๋ช
ํ๊ธฐ ์ข์ ์์
๋๋ค.
CFG๋ ํ์ ์ธ์ด ๋ฐ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์ ๊ด๋ จํ์ฌ ๋ค์ํ ๋ฐฉ์์ผ๋ก ์ ์๋ฉ๋๋ค. ๋ณธ ๊ธ์์๋ ๋ช
๋ช
๋ฒ์ ๋ํด ๊น์ด ํ๊ณ ๋ค์ง๋ ์์ต๋๋ค-์ด์ ๊ดํ ๋ด์ฉ์ด ๊ถ๊ธํ๋ค๋ฉด ๊ด๋ จ ํ ๋ก ์ ์ฐธ๊ณ ํ์ธ์. ๋ณธ ๊ธ์์ C์ ๋ฌธ๋ฒ์ด CFG๊ฐ ์๋๋ผ๊ณ ํ๋ ๊ฒ์, Yacc์ ์ฃผ์ด์ง ๋ฌธ๋ฒ์ด ๋ค๋ฅธ ๊ณณ์์ ์ค๋ ๋ช๋ช context information์ ์ฐธ์กฐํ์ง ์๊ณ ๋ C๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ parsing ํ๊ธฐ์ ์ถฉ๋ถํ์ง ์๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. ๋ช ๊ฐ์ง ์๋ฅผ ๋ค์ด๋ณด๊ฒ ์ต๋๋ค.
{
ย T (x);
...
}
Plain Text
๋ณต์ฌ
์์ํ ์๋ ์์ง๋ง, T๊ฐ type์ด๋ฉด ์๊ธฐ C ์ฝ๋๋ type T์ x์ ๋ํ ์ ํจํ ์ ์ธ์
๋๋ค. ๊ทธ๋ฌ๋ T๊ฐ ์๋ ค์ง type์ด ์๋๋ฉด argument x๋ฅผ ๊ฐ์ง function T์ ๋ํ ํธ์ถ์ด ๋ฉ๋๋ค. C parser๋ T๊ฐ ์ด์ ์ typedef์ ์ํด ์ ์๋์๋์ง ์ฌ๋ถ๋ฅผ ์์ง ๋ชปํ ์ฑ ์ด๋ป๊ฒ parsing ํ ๋ฐฉ๋ฒ์ ์ ์ ์์๊น์?
ํน์๋ "ํ์ง๋ง ๋๊ฐ ์ด๋ฐ ์ฝ๋๋ฅผ ์์ฑํ๋์?"๋ผ๊ณ ํ ์๋ ์์ ๊ฒ๋๋ค. ์ข์์, ๊ทธ๋ ๋ค๋ฉด ์ข ๋ ํ์ค์ ์ธ ์ฝ๋๋ฅผ ๋ณด์ฃ :
{
ย T * x;
...
}
Plain Text
๋ณต์ฌ
์ด๊ฒ์ T์ ๋ํ pointer๋ก x๋ฅผ ์ ์ธํ ๊ฒ์ผ๊น์, ์๋๋ฉด variable T์ x์ ๊ณฑ์
์ผ๊น์? ๋ฉ๋ชจ๋ฆฌ์ typedef๋ก ์ ์๋ type์ ๋ํ table์ด ์์ผ๋ฉด ์ ์ ์์ต๋๋ค-์ด๋ context-sensitive information์
๋๋ค.
๋ค๋ฅธ ์๊ฐ ์์ต๋๋ค:
func((T) * x);
Plain Text
๋ณต์ฌ
T๊ฐ type์ด๋ฉด x๋ฅผ ์ญ์ฐธ์กฐํ ๊ฒฐ๊ณผ๊ฐ T๋ก ํ๋ณํ๋์ด func์ ์ ๋ฌ๋ฉ๋๋ค. T๊ฐ type์ด ์๋๋ฉด T์ x์ ๊ณฑ์
์ด func์ ์ ๋ฌ๋ฉ๋๋ค.
์ ๋ชจ๋ ์์์, ๋ฌธ์ ๋ฅผ ์ ๋ฐํ ์ ์๋ ๋ถ๋ถ์ ๋๋ฌํ๊ธฐ ์ ์ ์ฝ๋์์ context-sensitive information์ ์์งํ์ง ์์ผ๋ฉด parser๋ ์ ์์ ์ผ๋ก ์๋ํ์ง ๋ชปํฉ๋๋ค. ์ด ๋ฌธ์ ๋ compilation/C ์ปค๋ฎค๋ํฐ์์ "typedef-name: identifier" ๋ฌธ์ ๋ก ๋ถ๋ฆฝ๋๋ค. K&R2๋ ๋ถ๋ก์์ C์ ๋ฌธ๋ฒ์ ์ ์ํ ๋ ์ด๋ฅผ ์ธ๊ธํฉ๋๋ค:
With one further change, namely deleting the production typedef-name: identifier and making typedef-name a terminal symbol, this grammar is acceptable to the YACC parser-generator.
๋คํํ๋ ์ด ๋ฌธ์ ๋ ๊ฐ๋จํ ํด๊ฒฐํ ์ ์์ต๋๋ค. Parsing์ด ์งํ๋๋ ๋์ typedef๋ก ์ ์๋ type์ symbol table์ ์ ์งํ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค. Lexer์์ ์ identifier๊ฐ ์ธ์๋ ๋๋ง๋ค ์ด identifier๊ฐ ์ ์๋ type์ธ์ง ํ์ธํ๊ณ ์ฌ๋ฐ๋ฅธ token์ parser์ ๋ฐํํฉ๋๋ค. Parser๋ identifier์ ์ ์๋ type์ด๋ผ๋ ๋ ๊ฐ์ง terminal์ ๊ฐ์ง๋ฉฐ, ์ด์ ๋จ์ ๊ฒ์ typedef ๋ฌธ์ parsing์ด ์๋ฃ๋ ๋๋ง๋ค symbol table์ ์
๋ฐ์ดํธํ๋ ๊ฒ์
๋๋ค. ์ด๊ฒ์ด ์ด๋ป๊ฒ ์๋ํ๋์ง ๋ ์ ์ดํดํ๊ธฐ ์ํด c2c์ ์ฝ๋์์ C parser์ lexer ๊ด๋ จ ๋ถ๋ถ์ ์ดํด๋ด
์๋ค. ๋ค์์ Lex ํ์ผ์ ์ผ๋ถ์
๋๋ค:
identifier ([a-zA-Z_][0-9a-zA-Z_]*)
<INITIAL,C>{identifier}
{
ย GetCoord(&yylval.tok);
ย yylval.n = MakeIdCoord(UniqueString(yytext),
ย ย ย ย ย ย ย ย ย ย ย ย ย yylval.tok);
ย if (IsAType(yylval.n->u.id.text))
ย ย RETURN_TOKEN(TYPEDEFname);
ย else
ย ย RETURN_TOKEN(IDENTIFIER);
}
Plain Text
๋ณต์ฌ
์ฌ๊ธฐ์ Lex์ syntax๋ฅผ ์์ธํ ์ค๋ช
ํ์ง ์๋๋ผ๋, ์ด๊ฒ์ด ๊ธฐ๋ณธ์ ์ผ๋ก ๋งํ๋ ๊ฒ์ identifier๊ฐ ๋ฐ๊ฒฌ๋ ๋๋ง๋ค ํด๋น identifier๊ฐ type์ธ์ง ํ์ธํ๋ค๋ ๊ฒ์
๋๋ค. Type์ด๋ฉด TYPEDEFname token์ด ๋ฐํ๋๊ณ , type์ด ์๋๋ฉด IDENTIFIER๊ฐ ๋ฐํ๋ฉ๋๋ค. Yacc ๋ฌธ๋ฒ์์ ์ด ๋์ ๋ณ๋์ terminal์
๋๋ค.
Rust
Rust์ lexical ๋ฌธ๋ฒ์ context-free ํ์ง ์์ต๋๋ค. Raw string literal์ด ๊ทธ ์์ธ์
๋๋ค. Raw string literal์ r์ ์ด์ N๊ฐ์ hash(N์ 0์ผ ์ ์์), ๋ฐ์ดํ, ์์์ ๋ฌธ์๋ค, ๋ฐ์ดํ ๊ทธ๋ฆฌ๊ณ N๊ฐ์ hash๋ก ๊ตฌ์ฑ๋ฉ๋๋ค. ์ค์ํ ๊ฒ์ ์ฒซ ๋ฒ์งธ ๋ฐ์ดํ ์ ์์ ๋ค๋ฅธ ๋ฐ์ดํ๊ฐ ๋ค์ด์ค๋ฉด ๊ทธ ๋ค์ N๊ฐ์ hash๊ฐ ์ฐ์์ ์ผ๋ก ์ฌ ์ ์๋ค๋ ๊ฒ์
๋๋ค. ๊ฐ๋ น, r###""###"###์ ์ ํจํ์ง ์์ต๋๋ค.
์๋ ๋ฌธ๋ฒ์ ๋ด
์๋ค:
R -> 'r' S
S -> '"' B '"'
S -> '#' S '#'
B -> . B
B -> ฮต
Plain Text
๋ณต์ฌ
์ฌ๊ธฐ์ .๋ ์์์ ๋ฌธ์๋ฅผ ๋ํ๋ด๊ณ ฮต๋ ๋น ๋ฌธ์์ด์ ๋ํ๋
๋๋ค. ๋ฌธ์์ด r#""#"#์ ์๊ฐํด ๋ณด๋ฉด, ์ด ๋ฌธ์์ด์ ์ ํจํ raw string literal์ ์๋์ง๋ง ๋ค์๊ณผ ๊ฐ์ ์ ๋ ๊ณผ์ ์ ํตํด ์๊ธฐ ๋ฌธ๋ฒ์์๋ ํ์ฉ๋ฉ๋๋ค:
R : #""#"#
S : ""#"
S : "#
B : #
B : ฮต
Plain Text
๋ณต์ฌ
(์ฌ๊ธฐ์ T : U๋ ๊ท์น T๊ฐ ์ ์ฉ๋จ์ ์๋ฏธํ๊ณ U๋ ๋ฌธ์์ด์ ๋๋จธ์ง ๋ถ๋ถ์
๋๋ค.) ๊ทผ๋ณธ์ ์ผ๋ก raw string literal์ด context-sensitive ํ๋ฏ๋ก CFG๋ก ํํ ์์ ์ด๋ ค์์ด ๋ฐ์ํ๋ ๊ฒ์ด๋ฉฐ, ํนํ ํ์ํ context๋ hash์ ์ ์
๋๋ค.
Rust์ string literal์ด context-free ํ์ง ์์์ ์ฆ๋ช
ํ๊ธฐ ์ํด context-free language๊ฐ regular language์์ ๊ต์งํฉ์ ๋ํด ๋ซํ ์๋ค๋ ์ฌ์ค๊ณผ context-free language์ ๋ํ pumping lemma๋ฅผ ์ฌ์ฉํ ๊ฒ์
๋๋ค.
Regular language R = r#+""#*"#+๋ฅผ ์๊ฐํด ๋ด
์๋ค. Rust์ raw string literal์ด context-free ํ๋ฉด, raw string literal๊ณผ R์ ๊ต์งํฉ์ธ R' ์ญ์ context-free ํด์ผ ํฉ๋๋ค. ๋ฐ๋ผ์ raw string literal์ด context-free ํ์ง ์์์ ์ฆ๋ช
ํ๋ ค๋ฉด R'์ด context-free ํ์ง ์์์ ์ฆ๋ช
ํ๋ฉด ๋ฉ๋๋ค.
R'์ {r#^n""#^m"#^n | m < n}์
๋๋ค.
R'์ด context-free ํ๋ค๊ณ ๊ฐ์ ํฉ์๋ค. ๊ทธ๋ฌ๋ฉด R'์ pumping lemma๊ฐ ์ ์ฉ๋๋ pumping length p > 0๋ฅผ ๊ฐ์ง๋๋ค. R'์์ ๋ค์ ๋ฌธ์์ด s๋ฅผ ์๊ฐํด ๋ด
์๋ค:
r#^p""#^{p-1}"#^p
e.g. for p = 2: s = r##""#"##
์๋ ์กฐ๊ฑด์ ๋ง์กฑ์ํค๋๋ก s = uvwxy์ ๊ฐ์ด ๋ถํ ํ ์ ์์ต๋๋ค.
โข
|vx| โฅ 1
โข
|vwx| โค p
โข
uv^iwx^iy โ R' for all i โฅ 0
โข
R'์ ๋ชจ๋ ๋ฌธ์์ด์์ "์ r์ ์๋ ๊ณ ์ ๋ผ ์์ผ๋ฏ๋ก v์ x ๋ชจ๋ " ๋๋ r์ ํฌํจํ ์ ์์ต๋๋ค. ๋ฐ๋ผ์ v์ x๋ hash๋ง ํฌํจํฉ๋๋ค. ๊ฒฐ๊ณผ์ ์ผ๋ก, ์ธ ๊ฐ์ hash sequence ์ค v์ x๋ฅผ ํฉ์น ๊ฒ์ ๊ทธ์ค ๋ ๊ฐ๋ง pumping ํ ์ ์์ต๋๋ค. ๋ง์ฝ ์ค์ hash sequence๋ฅผ ์ ํํ๋ฉด pumping ์ ์ธ๋ถ sequence ์ค ํ๋๊ฐ ์ฆ๊ฐํ์ง ์์ ์ธ๋ถ sequence ๊ฐ์ ๋ถ๊ท ํ์ด ๋ฐ์ํฉ๋๋ค. ๋ฐ๋ผ์ ๋ ์ธ๋ถ hash sequence๋ฅผ ๋ชจ๋ pumping ํด์ผ ํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ด ๋ hash sequence ์ฌ์ด์๋ p + 2๊ฐ์ ๋ฌธ์๊ฐ ์กด์ฌํ๋ฉฐ, |vwx|๋ p๋ณด๋ค ์๊ฑฐ๋ ๊ฐ์์ผ ํฉ๋๋ค. ์ฌ๊ธฐ์ ๋ชจ์์ด ๋ฐ์ํ์ฌ R'์ด context-free ํ์ง ์์์ด ๋์ถ๋ฉ๋๋ค.
R'๊ฐ context-free ํ์ง ์์ผ๋ฏ๋ก Rust์ raw string literal ๋ํ context-free ํ์ง ์์ต๋๋ค.