Skip to content

Commit

Permalink
Indent tracking
Browse files Browse the repository at this point in the history
  • Loading branch information
alexkar598 committed Jul 7, 2024
1 parent 5e75ab0 commit 6299d1d
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 0 deletions.
25 changes: 25 additions & 0 deletions dm-lezer/src/context.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { ContextTracker } from "@lezer/lr";
import { dedent, indent } from "./parser.terms.js";

class IndentLevel {
constructor(parent, depth) {
this.parent = parent;
this.depth = depth;
this.hash =
(parent ? (parent.hash + parent.hash) << 8 : 0) + depth + (depth << 4);
}
}

export const ctx = new ContextTracker({
start: { indent: new IndentLevel(null, 0) },
shift(context, term, stack, input) {
if (term === indent)
return {
...context,
indent: new IndentLevel(context, stack.pos - input.pos),
};
if (term === dedent) return { ...context, indent: context.parent };
return context;
},
hash: (context) => context.hash,
});
7 changes: 7 additions & 0 deletions dm-lezer/src/dm.grammar
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
@context ctx from "./context"
@external tokens indentation from "./tokens.js" {
indent
dedent
blankLineStart
}

@top File {
(
preprocessor |
Expand Down
32 changes: 32 additions & 0 deletions dm-lezer/src/tokens.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { ExternalTokenizer } from "@lezer/lr";
import { blankLineStart, dedent, indent } from "./parser.terms";

const newline = "\n".charCodeAt(0),
space = " ".charCodeAt(0),
tab = "\t".charCodeAt(0),
hash = "#".charCodeAt(0),
slash = "/".charCodeAt(0),
star = "*".charCodeAt(0);

export const indentation = new ExternalTokenizer((input, stack) => {
let prev = input.peek(-1);
if (prev !== -1 && prev !== newline) return;
let spaces = 0;
while (input.next === space || input.next === tab) {
input.advance();
spaces++;
}
if (
input.next === newline ||
input.next === hash ||
(input.next === slash &&
(input.peek(1) === slash || input.peek(1) === star))
) {
if (stack.canShift(blankLineStart))
input.acceptToken(blankLineStart, -spaces);
} else if (spaces > stack.context.indent.depth) {
input.acceptToken(indent);
} else if (spaces < stack.context.indent.depth) {
input.acceptToken(dedent, -spaces);
}
});

0 comments on commit 6299d1d

Please sign in to comment.