Skip to content

Commit 6299d1d

Browse files
committed
Indent tracking
1 parent 5e75ab0 commit 6299d1d

File tree

3 files changed

+64
-0
lines changed

3 files changed

+64
-0
lines changed

dm-lezer/src/context.js

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { ContextTracker } from "@lezer/lr";
2+
import { dedent, indent } from "./parser.terms.js";
3+
4+
class IndentLevel {
5+
constructor(parent, depth) {
6+
this.parent = parent;
7+
this.depth = depth;
8+
this.hash =
9+
(parent ? (parent.hash + parent.hash) << 8 : 0) + depth + (depth << 4);
10+
}
11+
}
12+
13+
export const ctx = new ContextTracker({
14+
start: { indent: new IndentLevel(null, 0) },
15+
shift(context, term, stack, input) {
16+
if (term === indent)
17+
return {
18+
...context,
19+
indent: new IndentLevel(context, stack.pos - input.pos),
20+
};
21+
if (term === dedent) return { ...context, indent: context.parent };
22+
return context;
23+
},
24+
hash: (context) => context.hash,
25+
});

dm-lezer/src/dm.grammar

+7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
@context ctx from "./context"
2+
@external tokens indentation from "./tokens.js" {
3+
indent
4+
dedent
5+
blankLineStart
6+
}
7+
18
@top File {
29
(
310
preprocessor |

dm-lezer/src/tokens.js

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { ExternalTokenizer } from "@lezer/lr";
2+
import { blankLineStart, dedent, indent } from "./parser.terms";
3+
4+
const newline = "\n".charCodeAt(0),
5+
space = " ".charCodeAt(0),
6+
tab = "\t".charCodeAt(0),
7+
hash = "#".charCodeAt(0),
8+
slash = "/".charCodeAt(0),
9+
star = "*".charCodeAt(0);
10+
11+
export const indentation = new ExternalTokenizer((input, stack) => {
12+
let prev = input.peek(-1);
13+
if (prev !== -1 && prev !== newline) return;
14+
let spaces = 0;
15+
while (input.next === space || input.next === tab) {
16+
input.advance();
17+
spaces++;
18+
}
19+
if (
20+
input.next === newline ||
21+
input.next === hash ||
22+
(input.next === slash &&
23+
(input.peek(1) === slash || input.peek(1) === star))
24+
) {
25+
if (stack.canShift(blankLineStart))
26+
input.acceptToken(blankLineStart, -spaces);
27+
} else if (spaces > stack.context.indent.depth) {
28+
input.acceptToken(indent);
29+
} else if (spaces < stack.context.indent.depth) {
30+
input.acceptToken(dedent, -spaces);
31+
}
32+
});

0 commit comments

Comments
 (0)