PEG не может разобрать отступ.
Но peg.js банка.
Я провел быстрый и грязный эксперимент (вдохновленный комментарием Айры Бакстер о мошенничестве) и написал простой токенизатор.
Для более полного решения (полный анализатор), пожалуйста, посмотрите этот вопрос: Разобрать уровень отступа с PEG.js
/* Initializations */
{
function start(first, tail) {
var done = [first[1]];
for (var i = 0; i < tail.length; i++) {
done = done.concat(tail[i][1][0])
done.push(tail[i][1][1]);
}
return done;
}
var depths = [0];
function indent(s) {
var depth = s.length;
if (depth == depths[0]) return [];
if (depth > depths[0]) {
depths.unshift(depth);
return ["INDENT"];
}
var dents = [];
while (depth < depths[0]) {
depths.shift();
dents.push("DEDENT");
}
if (depth != depths[0]) dents.push("BADDENT");
return dents;
}
}
/* The real grammar */
start = first:line tail:(newline line)* newline? { return start(first, tail) }
line = depth:indent s:text { return [depth, s] }
indent = s:" "* { return indent(s) }
text = c:[^\n]* { return c.join("") }
newline = "\n" {}
depths
- это стек отступов. indent () возвращает массив маркеров отступа, а start () разворачивает массив, чтобы синтаксический анализатор вел себя как поток.
peg.js выдает для текста:
alpha
beta
gamma
delta
epsilon
zeta
eta
theta
iota
эти результаты:
[
"alpha",
"INDENT",
"beta",
"gamma",
"INDENT",
"delta",
"DEDENT",
"DEDENT",
"epsilon",
"INDENT",
"zeta",
"DEDENT",
"BADDENT",
"eta",
"theta",
"INDENT",
"iota",
"DEDENT",
"",
""
]
Этот токенизатор даже ловит плохие отступы.