PEG.js ์์ฑ ํ์๋ ํ์ฌ ์์น(์ค ๋ฐ ์ด)๋ฅผ ์ถ์ ํ์ง ์์ต๋๋ค. ์ด ๊ธฐ๋ฅ์ด ๊ฝค ์ ์ฉํ ๊ฒ ๊ฐ์์ ์ถ๊ฐํ๊ณ ์ถ์ต๋๋ค.
ํ ๊ฐ์ง ๋ฐฉ๋ฒ์ ์ผ์น ๊ฒฐ๊ณผ๋ก ๋ฐํ๋๋ ๊ฐ ๊ฐ์ฒด์ line
๋ฐ column
์์ฑ์ ์ถ๊ฐํ๋ ๊ฒ์
๋๋ค.
start = "a" b:"b" { return [b.line, b.column]; } // Returns [1, 2] on the input "ab".
๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ํ์ฌ ๊ท์น์ ์์ ์์น๋ฅผ ์ฐธ์กฐํ์ฌ action/predicates ๋ด์์ ํน๋ณํ line
๋ฐ column
๋ณ์๋ฅผ ์ฌ์ฉํ ์ ์๋๋ก ํ๋ ๊ฒ์
๋๋ค.
start = "a" "b" { return [line, column]; } // Returns [1, 1] on the input "ab".
์ฒซ ๋ฒ์งธ ๋ฐฉ๋ฒ์ด ๋ ์ ์ฐํ์ง๋ง ์ค์ ๋ก๋ ์ด๋ฌํ ์ ์ฐ์ฑ์ด ํ์ํ์ง ์์ ์ ์์ต๋๋ค. ์ด๋ค ๋ฐฉ์์ผ๋ก ๊ตฌํํ ์ง๋ ์์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
๋ ๊ฐ์ง ๋ฐฉ๋ฒ ๋ชจ๋ ์ฑ๋ฅ์ ์ ํ์ํต๋๋ค. ์์น ์ถ์ ์ด ํ์ํ์ง ์์ ๊ฒฝ์ฐ ์ด๋ฅผ ๋ฐฉ์งํ๋ ค๋ฉด ํ์๋ฅผ ์์ฑํ ๋ truthy ๊ฐ์ด ์๋ trackPosition
์ต์
์ด PEG.buildParser
์ ์ ๋ฌ๋ ๊ฒฝ์ฐ์๋ง ์ถ์ ์ ํ์ฑํํด์ผ ํฉ๋๋ค.
๋ ์ต์ ๋ชจ๋ ํ๋ฅญํ ๊ฒ์ ๋๋ค. ๋ด ํ์์ ๋ฐ๋ผ ๋จ์ํ ์ , ์ด์ด ๊ด์ฐฎ์ ๊ฒ์ ๋๋ค.
๋๋ ๋ํ ์ด๊ฒ์ ๋ํ ํด๊ฒฐ์ฑ ์ ์ฐพ๊ณ ์์ต๋๋ค. ํ์ฌ ๋๋ computeErrorPosition()์ ๊ธฐ๋ฐ์ผ๋ก ๋น ๋ฅด๊ฒ ๋ฌด์ธ๊ฐ๋ฅผ ํดํนํ์ง๋ง ๋ช ๊ฐ์ง ๊ผฌ์์ด ์์ต๋๋ค.
ํ๋ฉด์ ์ผ๋ก๋ ์ฒซ ๋ฒ์งธ ์ ๊ทผ ๋ฐฉ์์ด ๋ ๋ฒ์งธ ๋ฐฉ์๋ณด๋ค ๋ ์ง๊ด์ ์ผ๋ก ๋ณด์ ๋๋ค.
๋๋ ์ฒซ ๋ฒ์งธ ์ ๊ทผ ๋ฐฉ์๋ ๋ ์ข์ํฉ๋๋ค.
๊ฐ๋ฅํ ํจ์จ์ฑ ์ค ํ๋๋ name.position์ ํจ์๋ก ์ฌ์ฉํ์ฌ ๋๋ฆฌ๊ฒ ๊ณ์ฐํ ์ ์๋๋ก ํ๋ ๊ฒ์ ๋๋ค. ๊ทธ๋ฌ๋ฉด ํ๊ณผ ์ด์ 2๊ฐ ํญ๋ชฉ ๋ฐฐ์ด์ ๋ฐํํ ์ ์์ต๋๋ค. ๋ชจ๋ ๋จ์ผ ํญ๋ชฉ์ ์์น๋ฅผ โโ๊ณ์ฐํ๊ณ ์ถ์ง ์์ ์ฌ๋๋ค์ ์ํ ์์ด๋์ด์ ๋๋ค.
๋์ด์ผ ๋ณด๋ฉด ์์ ๋ฐ ๋ ๋ฌธ์ ์์น๋ฅผ ์ ๊ณตํ ๋ค์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ์์น๋ฅผ ํ/์ด๋ก ๋ณํํ๋ ๋์ฐ๋ฏธ ํจ์๋ฅผ ์ ๊ณตํ๋ ๊ฒ์ด ๋ ๋์ ๊ฒ ๊ฐ์ต๋๋ค. ์ผ๋ฐ์ ์ธ ๊ฒฝ์ฐ์๋ ์ค๋ฅ๊ฐ ์๋ ํ ์ค/์ด์ด ํ์ํ์ง ์์ผ๋ฉฐ ์ผ๋จ ์ค๋ฅ์ ๋๋ฌํ๋ฉด ์ผ๋ฐ์ ์ผ๋ก ํ ๋ฒ๋ง ํ์ํฉ๋๋ค.
์ ๋ ํ์ฌ startPos0
๋ฐ pos
๋ณ์๋ฅผ ๋จ์ฉํ์ฌ ํดํน ๋ฐฉ์์ผ๋ก ์ด ์์
์ ์ํํ๊ณ ์์ต๋๋ค. ์ด๋ ํดํน์ฒ๋ผ ๋๊ปด์ง์ง๋ง ์ง๊ธ์ ์๋ํฉ๋๋ค.
๊ณต์ ์์ ์ด ์์ ๋๊น์ง ์ด ํจ์( computeErrorPosition
์ ๋๋ต์ ์ธ ์ฌ๋ณธ)๋ฅผ ๋ฌธ๋ฒ ๋งจ ์์ ํฌํจํ๊ฒ ์ต๋๋ค. ์ ์ด๋ ๊ทธ๊ฒ์ ๋์๊ฒ _current_ ์์น๋ฅผ ์ค ๊ฒ์
๋๋ค(๊ฐ๋ณ ๋
ธ๋์ ์์น๋ ์๋์ง๋ง):
function computeCurrentPos() {
/*
* The first idea was to use |String.split| to break the input up to the
* error position along newlines and derive the line and column from
* there. However IE's |split| implementation is so broken that it was
* enough to prevent it.
*/
var line = 1;
var column = 1;
var seenCR = false;
for (var i = 0; i < pos; i++) {
var ch = input.charAt(i);
if (ch === '\n') {
if (!seenCR) { line++; }
column = 1;
seenCR = false;
} else if (ch === '\r' | ch === '\u2028' || ch === '\u2029') {
line++;
column = 1;
seenCR = true;
} else {
column++;
seenCR = false;
}
}
return { line: line, column: column, pos: pos };
}
์ด ๋ฌธ์ ๋ ์ผ๋ จ์ ์ปค๋ฐ ์ผ๋ก ์์ ๋์์ต๋๋ค.
์ด์ trackLineAndColumn
์ต์
์ PEG.buildParser
ํจ์์ ์ ๋ฌํ ์ ์์ต๋๋ค.
var parser = PEG.buildParser(myGrammar, { trackLineAndColumn: true});
trackLineAndColumn
๋ฅผ true
๋ก ์ค์ ํ๋ฉด ๋ ๊ฐ์ ์๋ก์ด ๋ณ์๊ฐ ์ก์
๊ณผ ์ ์ด์ ํ์๋ฉ๋๋ค โ line
๋ฐ column
. ์กฐ์น์ ๊ฒฝ์ฐ ์ด๋ฌํ ๋ณ์๋ ์กฐ์น ํํ์์ ์์ ์์น๋ฅผ ๋ํ๋ด๋ ๋ฐ๋ฉด ์ ์ด์์๋ ํ์ฌ ์์น๋ฅผ ๋ํ๋
๋๋ค. ์ฝ๊ฐ ๋ค๋ฅธ ๋์์ ์์ ์ฌ์ฉ์ ์ํด ์ ๋ฐ๋ฉ๋๋ค.
ํ ๋ฐ ์ด ์ถ์ ์ ์ฑ๋ฅ์ ์ ํ์ํค๊ธฐ ๋๋ฌธ์ ์ ํ ์ฌํญ์ ๋๋ค(ํ์๊ฐ ์ฝ โโ3-4๋ฐฐ ๋๋ ค์ง). ๋๋ ์ด๊ฒ์ ๋ฏธ๋์ ์ด๋ ์ ๋ ์ต์ ํํ ์ ์์ ๊ฒ์ ๋๋ค(๋๋ ๊ทธ๊ฒ์ ๋จผ์ ์๋์ํค๋ ค๊ณ ๋ ธ๋ ฅํ์ต๋๋ค).
๋ฌธ์ ์ค๋ช
์์ ์ด ๋ฌธ์ ์ ๋ํ ๋ค๋ฅธ ์ ๊ทผ ๋ฐฉ์์ ์ธ๊ธํ์ต๋๋ค. line
๋ฐ column
์์ฑ์ ๊ฐ ์ผ์น ๊ฒฐ๊ณผ์ ์ถ๊ฐํ๋ ๊ฒ์
๋๋ค. ์ด ์๋ฃจ์
์ด ์ฌ์ฉ์์๊ฒ ๋ ๊นจ๋ํ๊ณ ์ ํธ๋์์ง๋ง ๋ฌธ์์ด, ์ซ์ ๋๋ ๋ถ์ธ(์ข
์ข
์ผ์น ๊ฒฐ๊ณผ๋ก ๋ฐํ๋จ)๊ณผ ๊ฐ์ ๊ธฐ๋ณธ ๊ฐ์ ๋ํ ์์ฑ์ ์ค์ ํ ์ ์๋ค๋ ๊ฒ์ ๊นจ๋ฌ์์ต๋๋ค. ๋ํ ๊ฐ์ฒด(์: String
, Number
๋๋ Boolean
)์ ์ธ์คํด์ค๋ฅผ ๋ฐํํ๋ ๊ฒ์ด ๊ฐ๋ฅํ ํด๊ฒฐ ๋ฐฉ๋ฒ์ด์ง๋ง ์ฌ์ฉ์๊ฐ ๋ง๋ ํ์์ ๋ฏธ๋ฌํ ๋ฒ๊ทธ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค. ์ด ๋ํผ๋ ํ๋ฆฌ๋ฏธํฐ๋ธ์ ์ฝ๊ฐ ๋ค๋ฅด๊ฒ ๋์ํฉ๋๋ค. ๊ทธ๋์ ๋์ ์ ์์ ์คํํ๊ธฐ๋ก ๊ฒฐ์ ํ์ต๋๋ค.
์ด ๊ธฐ๋ฅ์ ์ง์ํ๋๋ก ์จ๋ผ์ธ ํ ์คํธ ํ์ด์ง๊ฐ ์ ๋ฐ์ดํธ๋ฉ๋๊น?
@paulftw ์จ๋ผ์ธ ํธ์ง๊ธฐ๋ ํญ์ ์ต์ ์์ ๋ฒ์ ์ PEG.js(ํ์ฌ 0.6.2)๋ฅผ ์ฌ์ฉํฉ๋๋ค. PEG.js 0.7.0(์ด ๊ธฐ๋ฅ์ด ํฌํจ๋จ)์ ๋ฆด๋ฆฌ์คํ๋ฉด ์ ๋ฐ์ดํธํ๊ฒ ์ต๋๋ค. ์์์น ๋ชปํ ์ผ์ด ์ผ์ด๋์ง ์๋ ํ 4์ ํ๋ฐ๊ธฐ์ ์ผ์ด๋ ๊ฒ์ด๋ค.
์น ์ฌ์ดํธ ์์ค ์ฝ๋๋ GitHub ์์ ์ฌ์ฉํ ์ ์์ผ๋ฏ๋ก ์กฐ๊ธํดํ๋ฉด ์ง์ ์คํํ๊ณ ์์ ํ ์ ์์ต๋๋ค.
๋ชจ๋ ํ๊ณผ ์ด์ 1๋ถํฐ ์์ํ์ง๋ง JS ๋ฐฐ์ด๊ณผ ๊ฑฐ์ ๋ชจ๋ ์ต์ ์ธ์ด ๋ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ 0 ๊ธฐ๋ฐ ์ธ๋ฑ์ฑ์ ์ฌ์ฉํ๋ค๋ ๊ฒ์ ๋ฐฉ๊ธ ๊นจ๋ฌ์์ต๋๋ค.
๊ทธ ๋์์ธ ๊ฒฐ์ ์ ๋๋๋ฆด ๊ธฐํ๊ฐ ์์ต๋๊น?
@paulftw ํ๊ณผ ์ด์ 0 ๊ธฐ๋ฐ์ผ๋ก ๋ณด๊ณ ํ๋ ํ์ ์์ฑ๊ธฐ์ ์๋ฅผ ๋ค์ด ์ฃผ์๊ฒ ์ต๋๊น?
๋ด ๊ฒฐ์ ๋ค์ ์๋ ์์ด๋์ด๋ ์ด๋ฌํ ์ซ์๊ฐ ์ฌ์ฉ์์๊ฒ ํ์๋ ๊ฐ๋ฅ์ฑ์ด ๊ฐ์ฅ ๋๊ธฐ ๋๋ฌธ์(์ค๋ฅ ๋ฉ์์ง, ๋
ธ๋ ์์น ๋ฑ) 1 ๊ธฐ๋ฐ ์ธ๋ฑ์ฑ์ด 0 ๊ธฐ๋ฐ ์ธ๋ฑ์ฑ๋ณด๋ค ๋ ํฉ๋ฆฌ์ ์ด๋ผ๋ ๊ฒ์
๋๋ค. ๊ธฐ๊ณ ์ฒ๋ฆฌ์ ๊ฒฝ์ฐ offset
๋ณ์๊ฐ ๊ฐ์ฅ ์์ฃผ ์ฌ์ฉ๋๋ฉฐ 0๋ถํฐ ์์ํฉ๋๋ค.
๊ทธ ๋์์ธ ๊ฒฐ์ ์ ๋๋๋ฆด ๊ธฐํ๊ฐ ์์ต๋๊น?
๋ค, ํ์ ์ด ๋์ ๋ค๋ฉด :-)
์ ๋ Ace ํธ์ง๊ธฐ์์ ํ
์คํธ๋ฅผ ๊ฐ์กฐ ํ์ํ๊ธฐ ์ํด peg.js๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์์ฐ์ค๋ฝ๊ฒ ์์ด์ค ๋ผ์ธ ๋ฒํธ๋ 0๋ถํฐ ์์ํฉ๋๋ค.
๊ทธ๋ฌ๋ Bison์ ์์น๋ 1 ๊ธฐ๋ฐ์
๋๋ค.
http://git.savannah.gnu.org/cgit/bison.git/tree/src/location.c#n73
์ด๊ฒ์ด ์ฌ์ค์ด๋ผ๋ฉด ๋๋ ๋ ผ์์ ๊ทธ๋ง๋ฌ์ผ ํ๋ค.
์ด๋ค ์๋ฅผ ๋ณด๊ณ ์ถ์์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
์ง๊ธ์ ๋ค์ ์ฝ๋๋ฅผ ์ฌ์ฉํ์ฌ ๊ธฐํธ ์ด๋ฆ์ ์ฐพ์ต๋๋ค.
ํฌํ์
= "" { return new Position(์ค - 1, ์ด - 1); }
์์ง
= ์์:์บกํฐ ์ด๋ฆ:IDENT ๋:์บกํฐ S* { return new Symbol(name, new Range(start, end)); }
@paulftw ์ด ๋ฌธ์ ๋ฅผ ๋ณ๋์ ๋ฌธ์ ๋ก ๋๋ด์ต๋๋ค. ๋๋ ์ฌ์ฉ์๊ฐ 0.7.0์ ์ฑํํ๊ณ ๋๋ฆฌ ์ฌ์ฉ๋๋ ๊ฒ์ด ๋ฌด์์ธ์ง ๊ฒฐ์ ํ ๋๊น์ง ๊ธฐ๋ค๋ฆด ๊ฒ์ ๋๋ค.
์ด๊ฒ์ด ์ค๋ซ๋์ ํ์๋์๋ค๋ ๊ฒ์ ์๊ณ ์์ง๋ง ์ด๋ป๊ฒ ์ด๊ฒ์ ์๋์ํฌ ์ ์์ต๋๊น? ๋๋ ์ด๊ฒ์ ์์ฃผ ๋ฉ์ฒญํ๋ค. "trackLineAndColumn': true" ํ๋๊ทธ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฌธ๋ฒ์ ์ปดํ์ผํ์ง๋ง ๋ ธ๋์๋ ์ฌ์ ํ ํ๊ณผ ์ด์ด ํฌํจ๋์ด ์์ง ์์ต๋๋ค. ๋ ๋ฌด์์ด ํ์ํฉ๋๊น?
๋น์ ์ ๋ค์์ ์ธ๊ธ, ๋๋ ๊ทธ๊ฒ์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ชจ๋ฅด๋ ์ด๋๊ฐ์ ๋ฌธ์ํ๋์ด ์์ต๋๊น?
trackLineAndColumn์ true๋ก ์ค์ ํ๋ฉด ๋ ๊ฐ์ ์๋ก์ด ๋ณ์๊ฐ action๊ณผ predicate์ ํ์๋ฉ๋๋ค(line๊ณผ column). ์กฐ์น์ ๊ฒฝ์ฐ ์ด๋ฌํ ๋ณ์๋ ์กฐ์น ํํ์์ ์์ ์์น๋ฅผ ๋ํ๋ด๋ ๋ฐ๋ฉด ์ ์ด์์๋ ํ์ฌ ์์น๋ฅผ ๋ํ๋ ๋๋ค. ์ฝ๊ฐ ๋ค๋ฅธ ๋์์ ์์ ์ฌ์ฉ์ ์ํด ์ ๋ฐ๋ฉ๋๋ค.
@tomitreskak ์ด ๊ธฐ๋ฅ์ ๋ถ๋ช
ํ ๊ณผ๊ฑฐ์ ๋ช ๋ฒ ๋ณ๊ฒฝ๋์์ต๋๋ค. ์์ธํ ๋ด์ฉ์ ๋ณ๊ฒฝ ๋ก๊ทธ๋ฅผ ์ดํด๋ณด์ญ์์ค. tl;dr์ ๋ฌธ๋ฒ์์ location()
ํจ์๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค๋ ๊ฒ์
๋๋ค.
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
@tomitreskak ์ด ๊ธฐ๋ฅ์ ๋ถ๋ช ํ ๊ณผ๊ฑฐ์ ๋ช ๋ฒ ๋ณ๊ฒฝ๋์์ต๋๋ค. ์์ธํ ๋ด์ฉ์ ๋ณ๊ฒฝ ๋ก๊ทธ๋ฅผ ์ดํด๋ณด์ญ์์ค. tl;dr์ ๋ฌธ๋ฒ์์
location()
ํจ์๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค๋ ๊ฒ์ ๋๋ค.