Pegjs: ๋งค๊ฐœ๋ณ€์ˆ˜ํ™” ๊ฐ€๋Šฅํ•œ ๊ทœ์น™ ๊ตฌํ˜„

์— ๋งŒ๋“  2011๋…„ 08์›” 25์ผ  ยท  29์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: pegjs/pegjs

๋ณ€์ˆ˜๋กœ ๊ทœ์น™์„ ๋งค๊ฐœ๋ณ€์ˆ˜ํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

   = '\"' parse_contents '\"' ->
   / '\'' parse_contents('\'') '\'' ->
   / '+' parse_contents('+') '+' -> /* sure why not :) */

parse_contents(terminator='\"')
    = ('\\' terminator / !terminator .)+ -> return stuff

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

์‹œ๊ฐ„๋‚ด์„œ ์„ค๋ช…ํ•ด์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค

10๋…„ ํ›„์—๋Š” ๋˜ ๋‹ค๋ฅธ ์งˆ๋ฌธ์ด ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. 2020๋…„ ์ž˜ ๋ณด๋‚ด์„ธ์š”

๋ชจ๋“  29 ๋Œ“๊ธ€

์ด๊ฒƒ์ด ์ƒ๋‹นํ•œ ์–‘์˜ ์ž‘์—…์„ ์ ˆ์•ฝํ•˜๊ฑฐ๋‚˜ ํ˜„์žฌ ๋ถˆ๊ฐ€๋Šฅํ•œ ๊ฒƒ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ํŠน์ • ์‚ฌ์šฉ ์‚ฌ๋ก€๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

์ˆ˜์ค€์ด ์ธ์ˆ˜๋กœ ์ „๋‹ฌ๋œ ๊ทœ์น™์„ ํ˜ธ์ถœํ•˜์—ฌ ๋“ค์—ฌ์“ฐ๊ธฐ ์ˆ˜์ค€์„ ํ›จ์”ฌ ์‰ฝ๊ฒŒ ๊ตฌ๋ฌธ ๋ถ„์„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ ์ˆœ์ˆ˜ํ•œ 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 ์„ ๋Œ€์ƒ์œผ๋กœ ํ•˜๋Š” ๋ฌธ์ œ๋ฅผ ์ง€์›ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทœ์น™์„ ๋ณต์ œํ•˜์ง€ ์•Š๊ณ  ์ด๋ฅผ ๋‹ฌ์„ฑํ•  ์ˆ˜ ์žˆ๋Š” ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๊นŒ?

๊ฐ€๋Šฅํ•œ ๋ฐฉ๋ฒ•์€ ์ƒํƒœ๋ฅผ ์ˆ˜๋™์œผ๋กœ ์ถ”์ ํ•œ ๋‹ค์Œ ์˜๋ฏธ๋ก ์  ์ˆ ์–ด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด ์ ‘๊ทผ ๋ฐฉ์‹์€ ์—ญ์ถ”์ ์— ๋ฌธ์ œ๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ ๊ถŒ์žฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค(์ฆ‰, ๊ทœ์น™ ๋ณต์ œ์™€ ์ˆ˜๋™ ์ƒํƒœ ์ถ”์  ์ค‘ ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•  ๋•Œ ๋ณต์ œ๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค).

ํŒŒ์„œ์— ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋Š” ๋‘ ๊ฐ€์ง€ ์œ ํ˜•์˜ ์ธ์ˆ˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ๊ฐ€์น˜. Python, Nim ๋ฐ Haskell(๋ฐ ๋‹ค๋ฅธ ๋ฐฉ์‹์˜ Scheme)๊ณผ ๊ฐ™์€ ์–ธ์–ด์˜ ๋ฌธ๋ฒ•์€ ํŠธ๋ฆฌ ๋‚ด๋ถ€ ํ‘œํ˜„์‹์˜ "๊นŠ์ด"์— ๋”ฐ๋ผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ์˜ฌ๋ฐ”๋ฅธ ๋ฌธ๋ฒ•์„ ์ž‘์„ฑํ•˜๋ ค๋ฉด ์ด ์ปจํ…์ŠคํŠธ๋ฅผ ์–ด๋–ป๊ฒŒ๋“  ํ†ต๊ณผํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  2. ํŒŒ์„œ. 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๋…„ ์ž˜ ๋ณด๋‚ด์„ธ์š”

๋‚ด ํŒŒ์„œ ์ •์˜์˜ ์ค‘๋ณต์„ ์ œ๊ฑฐํ•˜๋Š” ๋ฐ ์ •๋ง ์œ ์šฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‚˜๋Š” ์˜๋„์ ์œผ๋กœ ๋งค์šฐ ํŽธ์•ˆํ•œ ๋งž์ถค ๋ฌธ๋ฒ•์„ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฉฐ ์•ฝ๊ฐ„ ๋‹ค๋ฅธ ์ปจํ…์ŠคํŠธ์—์„œ ์ผ๋ถ€ ๊ทœ์น™์„ ์ ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰

๊ด€๋ จ ๋ฌธ์ œ

mreinstein picture mreinstein  ยท  12์ฝ”๋ฉ˜ํŠธ

emmenko picture emmenko  ยท  15์ฝ”๋ฉ˜ํŠธ

audinue picture audinue  ยท  13์ฝ”๋ฉ˜ํŠธ

mattkanwisher picture mattkanwisher  ยท  5์ฝ”๋ฉ˜ํŠธ

futagoza picture futagoza  ยท  13์ฝ”๋ฉ˜ํŠธ