๋ณ์๋ก ๊ท์น์ ๋งค๊ฐ๋ณ์ํํ ์ ์๋ค๋ฉด ์ข์ ๊ฒ์ ๋๋ค.
= '\"' parse_contents '\"' ->
/ '\'' parse_contents('\'') '\'' ->
/ '+' parse_contents('+') '+' -> /* sure why not :) */
parse_contents(terminator='\"')
= ('\\' terminator / !terminator .)+ -> return stuff
์ด๊ฒ์ด ์๋นํ ์์ ์์ ์ ์ ์ฝํ๊ฑฐ๋ ํ์ฌ ๋ถ๊ฐ๋ฅํ ๊ฒ์ ๊ฐ๋ฅํ๊ฒ ๋ง๋๋ ํน์ ์ฌ์ฉ ์ฌ๋ก๊ฐ ์์ต๋๊น?
์์ค์ด ์ธ์๋ก ์ ๋ฌ๋ ๊ท์น์ ํธ์ถํ์ฌ ๋ค์ฌ์ฐ๊ธฐ ์์ค์ ํจ์ฌ ์ฝ๊ฒ ๊ตฌ๋ฌธ ๋ถ์ํ ์ ์์ต๋๋ค.
๋ํ ์์ํ DRY ๋
ผ๋ฆฌ์์ "์ด ๋ฌธ์๋ก ๊ตฌ๋ถ๋ ์ด์ค์ผ์ดํ ์ํ์ค์ ๊ฐ์ ํญ๋ชฉ"๊ณผ ๊ฐ์ ์์
์ ์ํํ ๋ ๊ท์น(๋ฐ ํด๋น ์์
!)์ ์ธ ๋ฒ ์ํํ๋ ๊ฒ๋ณด๋ค delimited('\'', '\\')
์ ๊ฐ์ ๊ฒ์ ํธ์ถํ๋ ๊ฒ์ด ์ข์ต๋๋ค. .
๋๋ ๋ ๋ช ํํ์ด์ผ ํ๋ค. "ํน์ "์ผ๋ก "๋๋ X ์ธ์ด์ ๋ฌธ๋ฒ์ ๋ํด ์์ ํ๊ณ ์์๊ณ ๊ฑฐ๊ธฐ์๋ ํ๋๋ก ๊ฒฐํฉ๋ ์ ์๋ 5๊ฐ์ง ๊ท์น์ด ์์ต๋๋ค. ์ฌ๊ธฐ ๊ทธ๊ฒ๋ค์ด ์์ต๋๋ค:"์ ๊ฐ์ ๊ฒ์ ์ฐพ๊ณ ์์์ต๋๋ค. ์ฆ, ์ ๋ ์ค์ ์ธ๊ณ๋ฅผ ๋ณด๊ณ ์ถ์์ต๋๋ค. ์ฌ์ฉ ์ฌ๋ก ๋ฐ ์ค์ ์ฝ๋. ์ด๋ฅผ ํตํด ์ด ๊ธฐ๋ฅ์ด ์ด๋ค ๊ฒฝ์ฐ์ ์ผ๋ง๋ ๋ง์ ์ฌ๋๋ค์๊ฒ ์ ์ฉํ ์ง ๋ ์ ํ๋จํ ์ ์์ต๋๋ค.
์ด ๊ธฐ๋ฅ ์์ฒด์ ๋ฐ๋ํ๋ฏ๋ก ์ด๊ฒ์ ๋ฐ์๋ค์ด์ง ๋ง์ญ์์ค. ๋๋ ์ผ๋ฐ์ ์ผ๋ก ๋ณต์ก์ฑ๊ณผ ๊ตฌํ ๋น์ฉ ๋๋ฌธ์ ์์์ ์ธ์ด ๋๋ ๊ฐ๋ฐ์์๊ฒ๋ง ์ ์ฉํ ๊ธฐ๋ฅ์ ๊ตฌํํ๊ณ ์ถ์ง ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ด ๊ฒฝ์ฐ ๋น์ฉ์ด ์๋์ ์ผ๋ก ๋์ต๋๋ค.
์๋ฐ์คํฌ๋ฆฝํธ์ฉ ํ์๋ฅผ ์์ฑํ๊ธฐ๋ง ํ๋ฉด string = delimited_by('\'') / delimited_by('\"')
๋ฅผ ๊ฐ์ง ์ ์๊ณ ๋์ค์ regexp = delimited_by('/')
๋ฅผ ๊ฐ์ง ์ ์์ต๋๋ค.
์ต๊ทผ์ ๋๋ ๋ด ์์ ์ ์ธ์ด์ ๋ํ ํ์๋ฅผ ์์ฑํ๊ณ ์์ต๋๋ค. ๋๋ ํ์ด์ฌ์ ์ํด ์์ฑํ PEG ํ๋ ์์ํฌ์ ๋ค์๊ณผ ๊ฐ์ ๊ฒ์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
LeftAssociative(op, subrule): l:subrule rest:(op subrule)* -> a_recursive_function_that_reverses_rest_and_makes_bintrees(l, op, subrule)
๊ทธ๋ฆฌ๊ณ ๋ค์๊ณผ ๊ฐ์ด ์ธ ์ ์์ต๋๋ค.
...
exp_mult = LeftAssociative(/[\*\/%]/, exp_paren)
exp_add = LeftAssociative(/[\+-]/, exp_mult)
C++๋งํผ ๋ง์ ์ฐ์ ์์ ์์ค(๋ชจ๋ ์ฐ์ฐ์์ ๋ช ๊ฐ์ง ์ถ๊ฐ)์ด ์์ผ๋ฏ๋ก in์ด ์ผ๋ง๋ ์ ์ฉํ์ง ์์ํด ๋ณด๊ฒ ์ต๋๋ค. ์์ง ๊ตฌ๋ฌธ ๋ถ์์ด ๋๋์ง ์์์ง๋ง ์ด๋ฏธ 12๋ฒ์ด๋ ์ฌ์ฉํ๊ณ ์์ต๋๋ค.
'๊ฐ์ ธ์ค๊ธฐ' ๊ธฐ๋ฅ๊ณผ ๊ฒฐํฉํ๋ฉด ์ข์ ๊ฒ์ ๋๋ค.
require(CommaSeparatedList.pegjs)
require(StringLiteral.pegjs)
require(IntegerLiteral.pegjs)
...
Function
= name:FuncName "(" args:CommaSeparatedList(Literal) ")"
Hash
= "{" props:CommaSeparatedList(Prop) "}"
Prop
= Key ":" Literal
Literal =
StringLiteral / IntegerLiteral
(์ด๊ฒ์ OP์ ์์ฒญ๋ณด๋ค ์กฐ๊ธ ๋ ๋ณต์กํ์ง๋ง ์์ ์ ์ค๋ ๋๋ฅผ ์ ๋นํํ๊ธฐ์๋ ๋๋ฌด ๊ฐ๊น์ ๋ณด์์ต๋๋ค.)
์ ๋ PEG.js์ ๋์์ผ๋ก R5RS Scheme ํ์๋ฅผ ๋ง๋ค๊ณ ์์ต๋๋ค. ์ปจํ ์คํธ ์ธ์ ๊ตฌ๋ฌธ ๋ถ์์ด ํ์ํ ์ ์ฌ ์ธ์ฉ์ ์ ์ธํ๊ณ ๋ ๋ชจ๋ ๊ฒ์ด ์ฅ๋ฐ๋น์ ๋๋ค. ๋ง์ ์์ ์ด์ํ ์ฌํ ์ฒ๋ฆฌ๋ฅผ ํผํ๋ฉด์ ํ ํ๋ฆฟ์์ ์ฆ์ ๊ท์น ์์ฑ์ ์ํด ๊ท์น์ ๋งค๊ฐ๋ณ์ํํ ์ ์์ผ๋ฉด ์ ์ฉํ ๊ฒ์ ๋๋ค. ์๋ฅผ ๋ค์ด, ๋จ์ํ๋ ์ค์ธ์ฉ ๋ฌธ๋ฒ์ ๋ค์๊ณผ ๊ฐ์ ์ ์์ต๋๋ค.
quasiquotation = qq[1]
qq[n] = "`" qq_template[n]
qq_template[0] = expression
qq_template[n] = simple_datum / list_qq_template[n] / unquotation[n]
list_qq_template[n] = "(" qq_template[n]* ")" / qq[n+1]
unquotation[n] = "," qq_template[n-1]
์ด ๊ธฐ๋ฅ์ ๋๊ตฌ์ ์ถ๊ฐํ๋ ๋ฐ ๊ด์ฌ์ด ์๋ค๋ฉด ์ด ๊ธฐ๋ฅ์ ๊ฐ๋ฐ์ ๊ธฐ์ฌํ๊ณ ์ถ์ต๋๋ค.
์ด๊ฒ์ ํ๋ ์ฃผ๋ ์ด์ ๋ ๋ฌธ๋งฅ์ ๋ฏผ๊ฐํ ๋ฌธ๋ฒ์ โโ์ง์ํ๊ธฐ ์ํ ๊ฒ์ ๋๋ค. ์ ๊ฐ ํ๋ฆฌ์ง ์๋๋ค๋ฉด ๊ฐ์ฅ ์ธ๊ธฐ ์๋ ์ธ์ด๋ (C์ ํ์ด์ฌ์ ๋ฌธ๋งฅ์ ํน์ ํ ๊ฒ๋ค์ด ์๋ค๋ ๊ฒ์ ํ์คํ ์๋๋ค). Trevor Jim์ ๋ฐ๋ฅด๋ฉด Haskell๋ ์ปจํ ์คํธ๊ฐ ์์ผ๋ฉฐ ๋๋ถ๋ถ์ ์ธ์ด๊ฐ ๋ค์๊ณผ ๊ฐ์ด ์์ ๋กญ์ง ์๋ค๊ณ ์ฃผ์ฅํฉ๋๋ค.
http://trevorjim.com/haskell-is-not-context-free/
http://trevorjim.com/how-to-prove-that-a-programming-language-is-context-free/
(PEG์ ๊ฐ์ด) ์ญ์ถ์ ํ ์ ์๋ ํ์์์ ์ธ๋ถ ์ํ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ์ํํ๋ฉฐ ์ด ํ์์์ ๋ณผ ์ ์๋ ๊ฒ๊ณผ ๊ฐ์ ๋ฌธ์ ๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
{ var countCs = 0;
}
start = ((x/y) ws*)* { return countCs }
x = "ab" c "d"
y = "a" bc "e"
c = "c" { countCs++; }
bc = "bc" { countCs++; }
ws = " " / "\n"
์๋ 1์ ์ ๋ต ๋์ 2๋ฅผ ๋ฐํํฉ๋๋ค. ์ด์ ๊ฐ์ ๋ฌธ์ ๋ ์ถ๋ก ํ๊ธฐ ์ด๋ ค์ธ ์ ์๊ณ , ์ฐพ๊ธฐ ์ด๋ ค์ด ๊ตํํ ๋ฒ๊ทธ๋ฅผ ์์ฑํ ์ ์์ผ๋ฉฐ, ๋ฐ๊ฒฌ๋๋ฉด ์ฐ์ํ๊ฒ ํด๊ฒฐํ๋ ๊ฒ์ ํจ์ฌ ๋ ์ด๋ ค์ธ ์ ์์ต๋๋ค. . PEG์์ ๋ฐํ๋ ๋ฐ์ดํฐ์ ์ฌํ ์ฒ๋ฆฌ๋ฅผ ์ํํ์ง ์๊ณ ์ด ์์ ์ ์ํํ๋ ๋ฐฉ๋ฒ์กฐ์ฐจ ๋ช ํํ์ง ์์ต๋๋ค. ์ด๋ป๊ฒ ๋ ํ์ ์์ฒด์ ์นด์ดํธ๊ฐ ํ์ํ ๊ฒฝ์ฐ ๋จ์ํ ์ด์ด ์ข์ง ์์ต๋๋ค.
ํ์ฌ (์ํํ๊ฒ) ์ธ๋ถ ์ํ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์ปจํ ์คํธ์ ๋ฏผ๊ฐํ ๋ฌธ๋ฒ์ โโ๊ตฌ๋ฌธ ๋ถ์ํ๋ ์ ์ผํ ๋ฐฉ๋ฒ์ ๋๋ค. ๋งค๊ฐ๋ณ์ํ๋ ๊ท์น์ ์ฌ์ฉํ๋ฉด ํ์๋ ์ ํจํ์ง ์์ ์ํ์ ์ํ ์์ด ์ด๊ฒ์ ๊ตฌ๋ฌธ ๋ถ์ํ ์ ์์ต๋๋ค.
start = countCs:((x<0>/y<0>) ws*)* { return countCs.reduce(function(a,b){return a+b[0];}, 0); }
x<count> = "ab" theCount:c<count> "d" { return theCount; }
y<count> = "a" theCount:bc<count> "e" { return theCount; }
c<count> = "c" { return count++; }
bc<count> = "bc" { return count++; }
ws = " " / "\n"
David, ๋น์ ์ ์ค์ ์ํฉ์ ๋ํด ๋ฌผ์๊ณ ํ์ด์ฌ์ ๊ณต๋ฐฑ ๋ค์ฌ์ฐ๊ธฐ ๊ตฌ๋ฌธ์ ๋ถ๋ช ํ ์ฌ๊ธฐ์ ์์ ๋๋ค. Lima(๋ด๊ฐ PEG๋ก ๋ง๋ค๊ณ ์๋ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด)์์ ์ ์ฌํ ๊ณต๋ฐฑ ๋ค์ฌ์ฐ๊ธฐ ๊ตฌ๋ฌธ์ ์ํํ๊ณ ์ถ์ต๋๋ค. ํ์ง๋ง ์ค์๋ก ๋ชจ๋ ๊ฒ์ ์ง์ฅ์ผ๋ก ๋ชฐ์๋ฃ๋ ์๋ชป๋ ์ํ๋ฅผ ๋ง๋ค ์ ์์ ๋ ๊ทธ๋ฐ ๊ฒ์ ๊ตฌํํ๊ณ ์ถ์ง ์์ต๋๋ค. C์ x* y(x x y ๋๋ y๊ฐ x ํ์ ๊ฐ์ ๋ํ ํฌ์ธํฐ๋ก ์ ์๋จ)์ ๊ฐ์ด ์ปจํ ์คํธ๊ฐ ํ์ํ ๊ตฌ๋ฌธ ๋ถ์ ๊ตฌ์กฐ์ ์ด๋ฆ์ ์ง์ ํ ์ ์์ต๋๋ค.
๊ตฌ๋ฌธ ๋ถ์์ด ๊ฐ๋ฅํ ์ปจํ ์คํธ์ ๋ฏผ๊ฐํ ๋ฌธ๋ฒ์ ๊ฒฝ์ฐ ์ด๋ฏธ ๋งค๊ฐ๋ณ์ํ๋ ๊ท์น๊ณผ ์ผ์นํ๋ ํ์ ํํ์์์ ๋ฐํ๋ ์ ๋ณด๋ฅผ ๋ฐ๋์ ์ ๋ฌํด์ผ ํฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ๊ตฌ๋ฌธ ๋ถ์๊ธฐ๊ฐ ์ปจํ ์คํธ๋ฅผ ์ค์ ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค. ๋ค์์ ๋งค๊ฐ๋ณ์ํ๋ ๊ตฌ๋ฌธ ๋ถ์์ ์ฌ์ฉํ ์ ์๊ณ ์ด์ ์ ์ผ์นํ ํํ์์ ๋ ์ด๋ธ์ (๋ณ์๋ก) ์ก์ธ์คํ ์ ์๋ ๊ฒฝ์ฐ์๋ง ์๋ํ๋ Lima์ ๋ํด ๊ณ ๋ ค ์ค์ธ ๋ฌธ์์ด ์ ํ์ ์ค์ ์์ ๋๋ค.
literalStringWithExplicitLength = "string[" n:number ":" characters<n> "]"
number = n:[0-9]* {return parseInt(n.join(''));}
characters<n> = c:. { // base case
if(n>0) return null; // don't match base case unless n is 0
else return c;
}
/ c:. cs:characters<n-1> {
ret c+cs
}
์ด๊ฒ์ string[10:abcdefghij] ์ ๊ฐ์ ๋ฌธ์์ด์ ๊ตฌ๋ฌธ ๋ถ์ํ ์ ์์ต๋๋ค. ์๋ ๊ทธ๋๋ก์ ๋ฉ์ง ์์ PEG.js๋ก๋ ๊ทธ๋ ๊ฒ ํ ์ ์์ต๋๋ค. ๋น์ ์ ๋ค์๊ณผ ๊ฐ์ ๋์ฐํ ์ผ์ํ์ต๋๋ค.
{ var literalStringLengthLeft=undefined;
}
literalStringWithExplicitLength = "string[" n:specialNumber ":" characters "]"
specialNumber = n:number {
literalStringLengthLeft = n;
return n;
}
number = n:[0-9]* {return parseInt(n.join(''));}
characters = c:character cs:characters? {
return c + cs
}
character = c:. {
if(literalStringLengthLeft > 0) {
literalStringLengthLeft--;
return c;
} else {
literalStringLengthLeft = undefined;
return null; // doesn't match
}
}
๋ง์ ํ๋กํ ์ฝ์๋ ์ด๋ฌํ ์ข ๋ฅ์ ๊ตฌ๋ฌธ ๋ถ์์ด ํ์ํฉ๋๋ค. ์๋ฅผ ๋ค์ด IPv4 ํจํท์๋ ์ ์ฒด ๊ธธ์ด๋ฅผ ์ค๋ช ํ๋ ํ๋๊ฐ ์์ต๋๋ค. ๋๋จธ์ง ํจํท์ ์ ์ ํ๊ฒ ๊ตฌ๋ฌธ ๋ถ์ํ๋ ค๋ฉด ํด๋น ์ปจํ ์คํธ๊ฐ ํ์ํฉ๋๋ค. IPv6, UDP ๋ฐ ๊ธฐํ ํจํท ๊ธฐ๋ฐ ํ๋กํ ์ฝ๋ ๋ง์ฐฌ๊ฐ์ง์ ๋๋ค. TCP๋ฅผ ์ฌ์ฉํ๋ ๋๋ถ๋ถ์ ํ๋กํ ์ฝ์ ๋์ผํ ๊ฐ๋ ์ ๋ฌธ์ ์คํธ๋ฆผ์ ์ฌ์ฉํ์ฌ ์์ ํ ๋ณ๊ฐ์ ์ฌ๋ฌ ๊ฐ์ฒด๋ฅผ ์ ์กํ ์ ์์ด์ผ ํ๊ธฐ ๋๋ฌธ์ ์ด์ ๊ฐ์ ๊ฒ์ด ํ์ํฉ๋๋ค.
์ด์จ๋ , ๋๋ ์ด๊ฒ์ด ์ข์ ๊ธฐ๋ฅ์ผ ๋ฟ๋ง ์๋๋ผ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ์ผ ๋ฟ๋ง ์๋๋ผ ๋ง์ ํ์(ํ์ฌ๋ก์๋ PEG.js ํฌํจ ).
Pegasus (๋๋ถ๋ถ์ ๊ตฌ๋ฌธ์ peg.js์ ๊ณต์ ํ๋ ํ๋ก์ ํธ)๋ ์ํ ์ฌ์ ์ ๋ณ๊ฒฝํ ์ ์๋ ๊ธฐ๋ฅ์ด ์ ๊ณต๋๋ #STATE{}
ํํ์์ ์ฌ์ฉํ์ฌ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํฉ๋๋ค. ์ด ์ํ ์ฌ์ ์ ๊ท์น์ด ์ญ์ถ์ ๋ ๋ ์ญ์ถ์ ๋ฉ๋๋ค. ์ด๋ฅผ ํตํด ์ค์ํ ๊ณต๋ฐฑ ๊ตฌ๋ฌธ ๋ถ์์ ์ง์ํ ์ ์์ต๋๋ค(์์ธํ ๋ด์ฉ ์ ์ค์ํ ๊ณต๋ฐฑ์ ๋ํ Wiki ํญ๋ชฉ ์ฐธ์กฐ).
๋ํ ๊ตฌ๋ฌธ ๋ถ์ ์ปค์์ ํจ๊ป ์ํ๋ฅผ ์ญ์ถ์ ํ์ฌ ์ํ ์ ์ฅ ๊ท์น์ ๋ํด์๋ ๋ฉ๋ชจ์ด์ ์ด์ ์ ์ํํ ์ ์์ต๋๋ค.
Peg.js๋ ๊ฐ์ ์์ ์ ์ฝ๊ฒ ์ํํ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
๊ท์น์ด ์ญ์ถ์ ํ ๋ Pegasus๋ ์ญ์ถ์ ์ํ๋ฅผ ์ด๋ป๊ฒ ๊ด๋ฆฌํฉ๋๊น? ๋ณ๊ฒฝ๋ ์ ์ฒด ํ๋ก๊ทธ๋จ ์ํ์ ์ค๋ ์ท์ ์ ์งํ๊ณ ๋๋๋ฆด ์ ์๋ค๊ณ ์์ํ ์ ์์ง๋ง ๋น์ฉ์ด ๋ง์ด ๋ญ๋๋ค. ๋ณ๊ฒฝ๋ ๋ณ์๋ง ์ค๋ ์ท์ผ๋ก ์ ์งํ๋ ๊ฒ์ ์์ํ ์ ์์ง๋ง, ์ฌ์ฉ์๊ฐ ์ด๋ฅผ ์ง์ ํด์ผ ํ์๋ฅผ ์์ฑํ๋ ๋ฐ ๋ณต์ก์ฑ์ด ์ถ๊ฐ๋๊ฑฐ๋ ํ์๊ฐ ์ผ๋ถ ์ฝ๋์์ ๋ณ๊ฒฝ๋ ๋ชจ๋ ์ํ๋ฅผ ์ด๋ป๊ฒ๋ ํ์ ํด์ผ ํฉ๋๋ค. ์ด๋ค ์ค ์ด๋ ๊ฒ๋ ์ด์์ ์ด์ง ์์๋ฐ ํ๊ฐ์์ค๋ ์ด๋ป๊ฒ ํฉ๋๊น?
์ด๋ก ์ ์ผ๋ก ํ์๋ A. ์์ ์ด ํด๋ก์ ์ ๋๊ธฐ ์ค์ด๊ณ ํ์๊ฐ ์์ ํ ์๋ฃ๋ ํ์๋ง ์คํ๋๊ณ B. ํ์๊ฐ ์๋ฃ๋ ํ์ ์คํ๋๊ธฐ ๋๋ฌธ์ ๊ท์น ์ผ์น๋ฅผ ์ทจ์ํ ์ ์๋ ๊ฒฝ์ฐ ํ์๋ ์๋ชป ์คํ๋ ์์ ์ ํผํ ์ ์์ต๋๋ค. ์๋ง๋ ๊ทธ ๊ณํ์ด ํ๊ฐ์์ค์์ ์ํ๋ ์ํ ์ญ์ถ์ ๋ณด๋ค ๋ ์ต์ ์ผ ๊ฒ์ ๋๋ค.
๋ํ ๋ฌดํจ ์ํ์ ๋ฌธ์ ๋ฅผ ์์ ํ๋ ๊ฒ์ ์ค์ ๋ก ๋งค์ฐ ์ข์ง๋ง string[10:abcdefghij]์ ๊ฐ์ ๋ฌธ์์ด ๋ฆฌํฐ๋ด๊ณผ ๊ด๋ จํ์ฌ ์ ๊ธฐํ ํํ์ฑ ๋ฌธ์ ๋ ํด๊ฒฐ๋์ง ์์ง๋ง ์๋ ๋ฐฉ์์ ํ์คํ ๊ด์ฌ์ด ์์ต๋๋ค.
์ ์ฒด ํ๋ก๊ทธ๋จ์ ์ํ๋ฅผ ์ญ์ถ์ ํ์ง ์์ต๋๋ค. ๋ถ๋ณ์ ์ํ ์ฌ์ ์ ์ ์งํฉ๋๋ค. ์ปค์์ ํจ๊ป ํ์ฌ ์ํ ์ฌ์ ์ ์ ์ฅํ๊ณ ์ปค์๊ฐ ์ญ์ถ์ ๋ ๋๋ง๋ค ์ํ ์ฌ์ ๋ ํจ๊ป ์ญ์ถ์ ๋ฉ๋๋ค. ๋์
๋๋ฆฌ๋ #STATE{}
์ก์
์ด์ธ์ ์ด๋ ๊ณณ์์๋ ๋ณ๊ฒฝํ ์ ์์ผ๋ฉฐ ๊ฐ ์ํ๊ฐ ๋ณ๊ฒฝ๋๊ธฐ ์ง์ ์ ๋ณต์ฌ๋ฉ๋๋ค.
์ปค์๋ฅผ ์ด๋ํ ๋๋ง๋ค ์ถ๊ฐ ๋ณ์๋ฅผ ์ค์ ํ๋ฉด ์ฑ๋ฅ์ด ์ฝ๊ฐ ์ ํ๋์ง๋ง ์ํ ์ ์ฅ ๊ท์น์ ๋ฉ๋ชจํ๋ ๊ธฐ๋ฅ๋ณด๋ค ํจ์ฌ ์ค์ํฉ๋๋ค. ๋ํ ์ํ ์ฌ์ ์ ๋ถ๋ณ ํน์ฑ์ผ๋ก ์ธํด ๋ณ๊ฒฝ๋ ๋๊น์ง ๊ณต์ ํ ์ ์๊ธฐ ๋๋ฌธ์ ์ด๋ก ์ธํด ์๋ง์ ๋ฉ๋ชจ๋ฆฌ ํ ๋น์ด ๋ฐ์ํ์ง ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ํ์์ ์ํ๊ฐ ์์ผ๋ฉด ๋จ์ผ(๋น) ์ํ ์ฌ์ ์ด๋ผ๋ ํ๋์ ํ ๋น๋ง ์์ ๊ฒ์ ๋๋ค.
JavaScript์๋ (๋ด๊ฐ ์๋ ํ) ๊ฐ์ฒด๋ฅผ ๋ณ๊ฒฝํ ์ ์๋๋ก ๋ง๋๋ ๊ธฐ๋ฅ์ด ์์ง๋ง ๋๋ถ๋ถ์ ์์ ๊ธฐ๋ฅ์ด์์ต๋๋ค. Peg.js๋ ๊ฐ #STATE{}
์ฝ๋ ๋ธ๋ก์ ์ฒ๋ฆฌํ๊ธฐ ์ ์ ์ํ ์ฌ์ ์ ๋ณต์ฌํ๊ณ ์ปค์๊ฐ ์ญ์ถ์ ๋ ๋๋ง๋ค ์ญ์ถ์ ํ๋ฉด ๋ฉ๋๋ค.
์, ๊ทธ๋์ ์ฌ์ฉ์๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ด๋ค ์ํ๋ฅผ ๋ณ๊ฒฝํ๋์ง ์ง์ ํด์ผ ํฉ๋๋ค. ๊ฝค ๊ด์ฐฎ์๋ฐ. ๊ทธ๋ฌ๋ ์ฌ์ ํ ๋งค๊ฐ๋ณ์ํ๊ฐ ์ํํ๋ ๊ฒ๊ณผ ๋์ผํ ์ด์ ์ ์ค์ ๋ก ๋ค๋ฃจ์ง๋ ์๋๋ค๊ณ ์๊ฐํฉ๋๋ค. ๋ค๋ฅธ ๊ฒ๋ค์ ๊ทธ ์์ฒด๋ก ์ ์ฉํ ๊ฒ ๊ฐ์ต๋๋ค.
๋ฐฉ๊ธ env
๋ณ์๋ฅผ ์ฌ์ฉํ์ฌ ์ก์ธ์คํ ์ ์๋ ํ๊ฒฝ์ ์ ๊ณตํ๋ ํฌํฌ๋ฅผ ์์ฑํ์ต๋๋ค. https://github.com/tebbi/pegjs
์ด๋ ์์์ ์ ์ํ #STATE{}
๊ฐ์ฒด์ ๋์ผํฉ๋๋ค.
ํ์ฑ โโ๊ธฐ๋ฅ์ด ๋จ์์์ ๋๋ง๋ค ๋ณต์๋๋ (ํจํค์ง-) ์ ์ญ ๋ณ์๋ฅผ ์ฌ์ฉํ๋ ๋น ๋ฅธ ํดํน์
๋๋ค. env
์ ๋ณต์ฌ๋ Object.create()๋ก ์ํ๋ฉ๋๋ค.
๋ค์์ Python์์ ๊ณต๋ฐฑ์ผ๋ก ์ ์๋ ๋ธ๋ก์ ๊ตฌ๋ฌธ ๋ถ์ํ๋ ๋ฐ ์ฌ์ฉํ๋ ๋ฌธ๋ฒ์ ์์ ๋๋ค.
{
env.indLevel = -1
}
block =
empty
ind:ws* &{
if (ind.length <= env.indLevel) return false;
env.indLevel = ind.length;
return true;
}
first:statement? rest:indStatement*
{
if (first) rest.unshift(first);
return rest;
}
indStatement =
"\n" empty ind:ws* &{ return env.indLevel === ind.length; }
stm:statement
{return stm; }
statement =
id:identifier ws* ":" ws* "\n"
bl:block { return [id, bl]; }
/ identifier
identifier = s:[a-z]* { return s.join(""); }
empty = (ws* "\n")*
ws = [ \t\r]
๋ค์์ ๊ฒฐ๊ณผ ๊ตฌ๋ฌธ ๋ถ์๊ธฐ์ ๋ํ ์ ๋ ฅ ์์ ๋๋ค.
b:
c
d:
e
f
g
PEG.js๊ฐ ๊ท์น์ ๋ํด ์ด๋ค ์ข ๋ฅ์ ๋งค๊ฐ๋ณ์๋ ์ง์ํ์ง ์๋๋ค๋ ์ธ์์ ๋ฐ์์ต๋๋ค. ์ด๋ ๋๋ผ์ด ์ผ์ ๋๋ค. ์ด ๊ธฐ๋ฅ์ ์ ์๊ฒ ๋งค์ฐ ์ค์ํฉ๋๋ค.
๋ด๊ฐ ํ์ํ ๊ฒ์ OP์ ์์ฒญ๋ณด๋ค ๊ฐ๋จํฉ๋๋ค. OP๋ ๋งค๊ฐ๋ณ์์ ๋ฐ๋ผ ๋ฌธ๋ฒ ์์ฒด๋ฅผ ์์ ํ๊ธฐ๋ฅผ ์ํ์ง๋ง ์ต์ํ ์ ์๋ฅผ ๊ท์น์ ์ ๋ฌํ๋ฉด ๋ฉ๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก ๋ค์๊ณผ ๊ฐ์ LLLPG ๊ท์น์ ๋ฒ์ญํ๊ณ ์ถ์ต๋๋ค(์ฌ๊ธฐ์ PrefixExpr
๋ -x
์ ๊ฐ์ ์ ๋์ด ํํ์ ๋๋ ์๋ณ์...)์ ๊ฐ์ ์ฐ์ ์์๊ฐ ๋์ ํํ์์
๋๋ค.
@[LL(1)]
rule Expr(context::Precedence)::LNode @{
{prec::Precedence;}
e:PrefixExpr(context)
greedy
( // Infix operator
&{context.CanParse(prec=InfixPrecedenceOf(LT($LI)))}
t:(NormalOp|BQString|Dot|Assignment)
rhs:Expr(prec)
{ ... }
| // Method_calls(with arguments), indexers[with indexes], generic!arguments
&{context.CanParse(P.Primary)}
e=FinishPrimaryExpr(e)
| // Suffix operator
...
)*
{return e;}
};
// Helper rule that parses one of the syntactically special primary expressions
@[private] rule FinishPrimaryExpr(e::LNode)::LNode @{
( // call(function)
"(" list:ExprList(ref endMarker) ")"
{ ... }
| // ! operator (generic #of)
"!" ...
| // Indexer / square brackets
{var args = (new VList!LNode { e });}
"[" args=ExprList(args) "]"
{ ... }
)
{return e;}
};
๋ด ์ธ์ด ์๋ 25๊ฐ์ ์ฐ์ ์์ ์์ค์ด ์์ผ๋ฉฐ ์ด๋ฌํ ๊ท์น์ ์ฌ์ฉํ์ฌ ๊ฑฐ์ ๋ชจ๋ ํญ๋ชฉ์ ๋จ์ผ ๊ท์น์ผ๋ก ์ฒ๋ฆฌํ๋๋ก ์ถ์ํ์ต๋๋ค( Precedence
๋ ์ด์์). ๊ฒ๋ค๊ฐ ๋ด ์ธ์ด์๋ ๋ฌดํํ ์์ ์ฐ์ฐ์(๊ธฐ๋ณธ์ ์ผ๋ก ๋ชจ๋ ๊ตฌ๋์ ์ํ์ค)๊ฐ ์์ผ๋ฉฐ ์ฐ์ฐ์์ ์ฐ์ ์์๋ ๊ตฌ๋ฌธ ๋ถ์๋ ํ์ ๊ฒฐ์ ๋ฉ๋๋ค. 25๊ฐ์ง ์ข
๋ฅ์ ์ฐ์ฐ์ ๊ฐ๊ฐ์ ๋ํด ๋ณ๋์ ๊ท์น์ ์ฌ์ฉํ์ฌ ์ผ๋ฐ์ ์ธ ๋ฐฉ์์ผ๋ก ์ธ์ด๋ฅผ ๊ตฌ๋ฌธ ๋ถ์ํ๋ ๊ฒ์ _๊ธฐ์ ์ ์ผ๋ก_ ๊ฐ๋ฅํ์ง๋ง ๊ทธ๋ ๊ฒ ํ๋ ๊ฒ์ ๋์ฐํ ๋ฐฉ๋ฒ์ด ๋ ๊ฒ์
๋๋ค.
๋ํ ์ฌ๊ธฐ์์ ๋ด๋ถ ๊ท์น FinishPrimaryExpr
์ด ๋๋ฌ์ธ๋ ๊ท์น์์ ์ ๋ฌ๋ ๋งค๊ฐ๋ณ์๋ฅผ ํตํฉํ๋ ๊ตฌ๋ฌธ ํธ๋ฆฌ๋ฅผ ๊ตฌ์ฑํ๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
๊ทธ๋์ ... ๋งค๊ฐ๋ณ์๋ฅผ PEG.js ๊ท์น์ ์ ๋ฌํ ๋ฐฉ๋ฒ์ด ์์ต๋๊น?
+1! ์ ๊ฒฝ์ฐ์๋ ์ผ๋ถ ๊ตฌ๋ถ ๊ธฐํธ๋ฅผ ์ ์ญ์ ์ผ๋ก ๊ตฌ์ฑํ ์ ์๋ ๊ตฌ๋ฌธ์ ๋ํ ํ์๋ฅผ ์์ฑํ๊ณ ์ถ์ต๋๋ค. ์ด ๊ฒฝ์ฐ ๊ตฌ๋ถ ๊ธฐํธ ๋ฆฌํฐ๋ด์ ์ ์ด์ ๊ฒฐํฉ๋ ๋ชจ๋ ๊ฒ๊ณผ ์ผ์นํ๋ ํํ์์ผ๋ก ๊ต์ฒดํ์ฌ ์ด๋ฅผ ๋ฌ์ฑํ ์ ์์ง๋ง ๋ชจ๋ ์ผ์น๊ฐ ๋จ์ํ ๋ณ์๋ก ๋์ฒด๋ ์ ์๋ค๋ฉด ํจ์ฌ ๋ ์ฐ์ํ๊ณ ํจ์จ์ ์ ๋๋ค.
+1, ๊ฐ๊น์ด ์ฅ๋์ ์ด๊ฒ์ด ๊ตฌํ๋๋ ๊ฒ์ ๋ณผ ๊ธฐํ๊ฐ ์์ต๋๊น?
๋ ๋ค๋ฅธ ์ฌ์ฉ ์ฌ๋ก. ์ด๊ฒ์ javascript.pegjs
์์์์ ๊ฐ์ ธ์จ ๊ฒ์
๋๋ค.
(...)
RelationalExpression
= head:ShiftExpression
tail:(__ RelationalOperator __ ShiftExpression)*
{ return buildBinaryExpression(head, tail); }
RelationalOperator
= "<="
/ ">="
/ $("<" !"<")
/ $(">" !">")
/ $InstanceofToken
/ $InToken
RelationalExpressionNoIn
= head:ShiftExpression
tail:(__ RelationalOperatorNoIn __ ShiftExpression)*
{ return buildBinaryExpression(head, tail); }
RelationalOperatorNoIn
= "<="
/ ">="
/ $("<" !"<")
/ $(">" !">")
/ $InstanceofToken
(...)
(...)
/ ForToken __
"(" __
init:(ExpressionNoIn __)? ";" __
test:(Expression __)? ";" __
update:(Expression __)?
")" __
body:Statement
(...)
(...)
์ด๋ฌํ ๋ชจ๋ ...NoIn
๊ท์น(๊ทธ๋ฆฌ๊ณ ๋ง์ ๊ท์น์ด ์์)์ ๋จ์ํ for in
๋ฌธ ๋๋ฌธ์ ํ์ํฉ๋๋ค. ์ด๊ฒ์ ๋ํ ํจ์ฌ ๋ ๋์ ์ ๊ทผ ๋ฐฉ์์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
(...)
RelationalExpression<allowIn>
= head:ShiftExpression
tail:(__ RelationalOperator<allowIn> __ ShiftExpression)*
{ return buildBinaryExpression(head, tail); }
RelationalOperator<allowIn>
= "<="
/ ">="
/ $("<" !"<")
/ $(">" !">")
/ $InstanceofToken
/ &{ return allowIn; } InToken
{return "in";}
(...)
(...)
/ ForToken __
"(" __
init:(Expression<false> __)? ";" __
test:(Expression<true> __)? ";" __
update:(Expression<true> __)?
")" __
body:Statement
(...)
(...)
์ด๊ฒ์ ์๋ฅผ ๋ค์ด JavaScript ๋ฌธ๋ฒ์ด ์ง์ ๋๋ ๋ฐฉ์๊ณผ ๋งค์ฐ ์ ์ฌํฉ๋๋ค. https://tc39.github.io/ecma262/#prod -IterationStatement ( ~In
์ฐธ๊ณ )
ํ์ฌ ๊ฐ๋ฐ ์ค์ธ ์ธ์ด์๋ ๋ค์๊ณผ ๊ฐ์ ์ ํํ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. ํน์ ์ง์ ์์๋ง ์ผ๋ถ ๊ท์น์ ๋นํ์ฑํ/ํ์ฑํํ๊ณ ์ถ์ต๋๋ค. JavaScript ๋ฌธ๋ฒ์ ๋ํด ํ๋ ๊ฒ์ฒ๋ผ ์ํฅ์ ๋ฐ๋ ๋ชจ๋ ๊ท์น์ ๋ณต์ ํ๋ ๊ฒ์ ์ผ๊ฐ๊ณ ์ถ์ต๋๋ค.
๊ท์น์ ๋ณต์ ํ์ง ์๊ณ ์ด๋ฅผ ๋ฌ์ฑํ ์ ์๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ด ์์ต๋๊น?
+1, ๊ฐ๊น์ด ์ฅ๋์ ์ด๊ฒ์ด ๊ตฌํ๋๋ ๊ฒ์ ๋ณผ ๊ธฐํ๊ฐ ์์ต๋๊น?
์ด ๋ฌธ์ ์๋ ๋ง์ผ์คํค์ด ํ ๋น๋์ด ์์ต๋๋ค(1.0.0 ์ดํ). PEG.js์ ํ์ฌ ๋ฒ์ ์ 0.10.0์ ๋๋ค. ๋ถ๋ช ํ ํฌ์คํธ 1.0.0 ๋ฌธ์ ๋ ๋ก๋๋งต ์ ๋ฐ๋ผ 0.11.0 ๋ฆด๋ฆฌ์ค ํ ์ด๋ ์์ ์์ ๋ฐ์ํ 1.0.0 ๋ฆด๋ฆฌ์ค ์ดํ์ ์ฒ๋ฆฌ๋ฉ๋๋ค.
์ด๊ฒ์ ๊ทํ์ ์ง๋ฌธ์ ๋ตํด์ผ ํฉ๋๋ค. ์ ์ฒด ํ๋ก์ธ์ค๋ฅผ ๊ฐ์ํํ๋ ๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ์ 0.11.0 ๋ฐ 1.0.0 ์ ๋์์ผ๋ก ํ๋ ๋ฌธ์ ๋ฅผ ์ง์ํ๋ ๊ฒ์ ๋๋ค.
๊ท์น์ ๋ณต์ ํ์ง ์๊ณ ์ด๋ฅผ ๋ฌ์ฑํ ์ ์๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ด ์์ต๋๊น?
๊ฐ๋ฅํ ๋ฐฉ๋ฒ์ ์ํ๋ฅผ ์๋์ผ๋ก ์ถ์ ํ ๋ค์ ์๋ฏธ๋ก ์ ์ ์ด๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋๋ค. ๊ทธ๋ฌ๋ ์ด ์ ๊ทผ ๋ฐฉ์์ ์ญ์ถ์ ์ ๋ฌธ์ ๊ฐ ์์ผ๋ฏ๋ก ๊ถ์ฅํ์ง ์์ต๋๋ค(์ฆ, ๊ท์น ๋ณต์ ์ ์๋ ์ํ ์ถ์ ์ค ํ๋๋ฅผ ์ ํํ ๋ ๋ณต์ ๋ฅผ ์ ํํฉ๋๋ค).
ํ์์ ์ ๋ฌํ ์ ์๋ ๋ ๊ฐ์ง ์ ํ์ ์ธ์๊ฐ ์์ต๋๋ค.
leftAssociative(element, separator)
, escapedString(quote)
๋ฐ withPosition(parser)
๊ฐ ์ข์ ์์
๋๋ค.์ธ์๊ฐ ํ์์ธ์ง ๊ฐ์ธ์ง๋ฅผ ์ด๋ป๊ฒ๋ ํ์ํ๋ ๋ฐฉ๋ฒ์ด ์์ด์ผ ํฉ๋๋ค. ์ฌ๋ฐ๋ฅธ ์ ๊ทผ ๋ฐฉ์์ ์์๋ด๋ ค๊ณ ํ์ ๋ ์ปจํ ์คํธ์ ์ ์ญ ๋ณ์๋ฅผ ์ฌ์ฉํ๊ฒ ๋์๊ณ ์ด๋ ๋ถ๋ช ํ ๋ง๋ค๋ฅธ ๊ณจ๋ชฉ์ด์์ต๋๋ค. ๋๊ตฌ๋ ์ง ๊ทธ๊ฒ์ ๋ํ ์์ด๋์ด๊ฐ ์์ต๋๊น?
๋งคํฌ๋ก ๋ ์ด๋ป์ต๋๊น?
์ฃผ์ด์ง:
Add <Expression, Add>
= left:Expression _ '+' _ right:Add
{ return { type: 'add', left, right } }
/ Expression
์ธ์ :
= Add <MyExpression, MyAdd>
MyExpression
= [0-9]+
๊ทธ ๋ค์์:
= left:MyExpression _ '+' _ right:MyAdd
{ return { type: 'add', left, right } }
/ MyExpression
MyExpression
= [0-9]+
์ด๋ฅผ ํตํด ์ํฅ์ :smirk์์ ๊ท์น์ ์์ฑํ ์ ์์ต๋๋ค.
๋์ํฉ๋๋ค. ๊ฐ๋ฐ์๊ฐ ์ด ๊ธฐ๋ฅ์ ์ถ๊ฐํ๋ ๊ฒ์ด ์ข์ต๋๋ค. :)
์ ๊ฐ ์์ฑํ๊ณ ์๋ ์ ๋ฐ์ดํธ๋ JavaScript ๋ฌธ๋ฒ์ ์ด ๊ธฐ๋ฅ์ด ์ ๋ง ํ์ํฉ๋๋ค. ๊ทธ๋์ ์ด๊ฒ์ ์ ์์๋ฆฌ์คํธ์ ์์ต๋๋ค. ๊ทธ๊ฒ์ ํด๋ณด๊ณ ๊ทธ๊ฒ์ด ์ด๋ป๊ฒ ์๋ํ๋์ง ๋ณผ ๊ฒ์ ๋๋ค.
@samvv ๋๋ ์ด๊ฒ์ ๋งค์ฐ ๋ค๋ฅธ ๊ฒฝ๋ก์์ ๋ณด์๊ณ ์์ง ์ ์ฒด ์ค๋ ๋๋ฅผ ์ฝ์ง ์์์ต๋๋ค.
๊ทธ๋ฌ๋ ์ฌ๊ธฐ์์ ์ธ๊ธํ #572์์ ๋งค๊ฐ๋ณ์ํ๋ ๊ท์น์ ์๋ฎฌ๋ ์ด์
ํ ์ ์๋ ๊ธฐ์ ์ ๋ณด์ฌ์ฃผ๊ณ ์์ต๋๋ค.
์ฆ, ๋ณธ์ง์ ์ผ๋ก ํจ์ ๋ฅผ ์ค๊ฐ ๊ตฌ๋ฌธ ๋ถ์ ๊ฒฐ๊ณผ๋ก ๋ฐํํฉ๋๋ค.
๊ทธ "์์์"๋ ๊ฒฐ์ฝ ๋ด ๋ฐ๋ช ํ์ด ์๋๋ฉฐ ์๋ง๋ ๋น์ ์ ๋ชฉ์ ์ ๋ค์ ํฌ๋ฐํ ๊ฒ ๊ฐ์ต๋๋ค. ๊ทธ๋ฌ๋ ๊ทธ๊ฒ์ ๋น์ ์ ์ํ ํด๊ฒฐ ๋ฐฉ๋ฒ์ผ ์ ์์ต๋๋ค. "ํฌ์คํธ v1.0"๊น์ง... :)
@meisl Cool, ํ ๊ฐ์ฌํฉ๋๋ค! ์๊ฐ์ด ๋๋ฉด ์๋ํด ๋ณด๊ฒ ์ต๋๋ค.
@samvv ์ค, ์... ์ ๊ฐ ์ข ์ค์ํ ๊ฒ์ ๊ฐ๊ณผํ ๊ฒ ๊ฐ์ต๋๋ค.
๋ด๊ฐ ์ ์ํ ๊ฒ์ ์ ์ ์๋ง ๋์์ด๋๋ ๋ฐ๋ฉด ํ์๋ OP์ ์ค์ ๋ฌธ์ ์
๋๋ค ...
๊ทธ ์ฃ์กํฉ๋๋ค.
๊ทธ๋ฌ๋ ํ์์ ๊ฒฝ์ฐ ์๋ ํด๊ฒฐ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ "์์กด ๊ฒฐ์ " ๋ถ๋ถ์ ํจ์๋ฅผ ๋ฐํํ๋ ๊ฒ๊ณผ ์๋ฌด ๊ด๋ จ์ด ์์ต๋๋ค...
https://pegjs.org/online ์์ ์๋ํด ๋ณผ ์ ์๋ ์์ ๋ฅผ ์ถ๊ฐํ๊ณ ์์ต๋๋ค.
๊ธฐ๋ณธ ์์ด๋์ด๋ ํ์ฌ "ํฐ๋ฏธ๋ค์ดํฐ"๋ฅผ ๊ธฐ์ตํ๊ธฐ ์ํด ์ ์ญ ์ํ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์
๋๋ค. ๊ทธ๊ฒ์ ํ์คํ ํดํน์ด๋ฉฐ ๋ฐ๋ณต์ ์
๋๋ค.
ํ์ง๋ง: |
๋ ๋ค๋ฅธ ๊ตฌ๋ถ ๊ธฐํธ๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ str
์ ํ๋์ ๋์์ ์ถ๊ฐํ๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
/ (t:'|' {term = t}) c:conts t:.&{ return isT(t) } { return c }
๊ทธ๊ฒ์ ๋ฐ๋ก ๊ทธ ํ๋ ์ ๋ฌธ์์์ ๋ค๋ฅธ ๊ฒ๋ค๊ณผ ๋ค๋ฆ
๋๋ค |
{
var term;
function isT(ch) { return ch === term }
function isE(ch) { return ch === '\\' }
}
start = str*
str
= (t:'\"' {term = t}) c:conts t:.&{ return isT(t) } { return c }
/ (t:'\'' {term = t}) c:conts t:.&{ return isT(t) } { return c }
conts
= c:(
'\\' t:.&{ return isT(t) || isE(t) } { return t }
/ t:.!{ return isT(t) } { return t }
)*
{ return c.join('') }
... ์ ๋ ฅ์
"abc"
-> ["abc"]
"a\"bc"
-> ["a\"bc"]
"a\\bc"
-> ["a\bc"]
"a\\b\"c"'a\\b\''
-> ["a\b\"c", "a\b'c"]
์ถ์ : ๊ทธ๊ฑด ์ ๋ง ์์ผ๋ก ์ฐ๊ณ ์ถ์ ๊ฒ์ด ์๋๋๋ค. ์ ๋ ์๋๋ค. ํ์ง๋ง ์ด๋ด, ๊ทธ๊ฒ์ด ๋น์ ์ ์ํด ์์ฑ ๋ ๊ฒ์ด๋ผ๊ณ ์์ํด๋ณด์ญ์์ค... ์ ์๊ฐ์๋ ์์น์ ์ผ๋ก ๊ทธ๋ ๊ฒ ์๊ฐ ํฉ๋๋ค .
@ceymard - 10๋ ์ด ์ง๋ ๊ฑธ ์์ง๋ง #36๊ณผ ์ด๋ป๊ฒ ๋ค๋ฅธ์ง ๊ถ๊ธํฉ๋๋ค.
์ฐ์ ๊ธฐ์ตํ๋๋ฐ ์๊ฐ์ด ์ข ๊ฑธ๋ ธ๋ค์. 10 ๋ !
์ด PR์์ ๊ท์น์ ์ธ์๋ฅผ ์ทจํ๊ณ ๋งค๊ฐ๋ณ์ํ๋ ์ ์์ต๋๋ค. ์ด๊ฒ์ ์ ์ฌํ์ง๋ง ๋ค๋ฅธ ๊ท์น์ ๋ฐ๋ณต์ ํผํ๊ธฐ ์ํด ๋ฌธ๋ฒ ์์ฒด์์ ์ฌ์ฉํ๊ธฐ ์ํ ๊ฒ์ ๋๋ค.
#36์์ ๊ท์น์ ๋ฌธ๋ฒ ์์ฒด์ ์ธ๋ถ์ ์ง์ ๋ฉ๋๋ค. ๋ฐ๋ผ์ ๋ฌธ๋ฒ ์์ฒด๊ฐ ๋งค๊ฐ๋ณ์ํ๋ฉ๋๋ค.
๋ฌธ๋ฒ ์์ฒด๊ฐ ๊ท์น์ด๊ณ ๋ฐ๋ผ์ ๋์ผํ ๋ฌธ์ ๋ผ๊ณ ์ฃผ์ฅํ ์ ์์ง๋ง ๋ฒ์๊ฐ ๋ค๋ฅด๋ค๊ณ ์๊ฐํฉ๋๋ค. #36์ ์๋ง๋ ์ฝ๊ฐ์ API ๋ณ๊ฒฝ์ ์๋ฏธํ์ง๋ง ์ด PR์ ๊ทธ๋ ์ง ์๊ธฐ ๋๋ฌธ์ ๊ทธ๋ ์ง ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
๋ฐ๋ผ์ C++ ์ฉ์ด๋ฅผ ๋งค์ฐ ์๋ชป๋ ๋ฐฉ์์ผ๋ก ๋จ์ฉํ๊ธฐ ์ํด ์ ์๋ ํ ํ๋ฆฟ ์ ์ ์ด๊ณ ํ์๋ ์์ฑ์ ํธ์ถ์ ๋๊น?
๋๋ ์ด ๋น์ ๊ฐ ์ด๋ ์ ๋ ํจ๊ณผ๊ฐ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ๊ทธ๋ ์ต๋๋ค.
์๊ฐ๋ด์ ์ค๋ช ํด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค
10๋ ํ์๋ ๋ ๋ค๋ฅธ ์ง๋ฌธ์ด ์์ ๊ฒ์ ๋๋ค. 2020๋ ์ ๋ณด๋ด์ธ์
๋ด ํ์ ์ ์์ ์ค๋ณต์ ์ ๊ฑฐํ๋ ๋ฐ ์ ๋ง ์ ์ฉํ ๊ฒ์ ๋๋ค. ๋๋ ์๋์ ์ผ๋ก ๋งค์ฐ ํธ์ํ ๋ง์ถค ๋ฌธ๋ฒ์ ๊ฐ์ง๊ณ ์์ผ๋ฉฐ ์ฝ๊ฐ ๋ค๋ฅธ ์ปจํ ์คํธ์์ ์ผ๋ถ ๊ท์น์ ์ ์ฉํด์ผ ํฉ๋๋ค.
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
์๊ฐ๋ด์ ์ค๋ช ํด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค
10๋ ํ์๋ ๋ ๋ค๋ฅธ ์ง๋ฌธ์ด ์์ ๊ฒ์ ๋๋ค. 2020๋ ์ ๋ณด๋ด์ธ์