Skip to content

Commit

Permalink
improve performance (#207)
Browse files Browse the repository at this point in the history
* improve performance

* Create serious-hairs-sparkle.md
  • Loading branch information
ota-meshi authored Jun 26, 2024
1 parent d590e7f commit 7104688
Show file tree
Hide file tree
Showing 14 changed files with 229 additions and 116 deletions.
5 changes: 5 additions & 0 deletions .changeset/serious-hairs-sparkle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"toml-eslint-parser": minor
---

improve performance
57 changes: 26 additions & 31 deletions src/tokenizer/code-point-iterator.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,16 @@
import { CodePoint } from "./code-point";

type Position = {
offset: number;
line: number;
column: number;
};
import { Locations } from "./locs";

export class CodePointIterator {
public readonly text: string;

private readonly locs = new Locations();

private lastCodePoint: number = CodePoint.NULL;

public start: Position = {
offset: -1,
line: 1,
column: -1,
};
public start = -1;

public end: Position = {
offset: 0,
line: 1,
column: 0,
};
public end = 0;

/**
* Initialize this char iterator.
Expand All @@ -38,38 +27,44 @@ export class CodePointIterator {
return (this.lastCodePoint = this.moveAt(this.end));
}

public getStartLoc(): { line: number; column: number } {
return this.getLocFromIndex(this.start);
}

public getEndLoc(): { line: number; column: number } {
return this.getLocFromIndex(this.end);
}

public getLocFromIndex(index: number): { line: number; column: number } {
return this.locs.getLocFromIndex(index);
}

public eat(cp: number): boolean {
if (this.text.codePointAt(this.end.offset) === cp) {
if (this.text.codePointAt(this.end) === cp) {
this.next();
return true;
}
return false;
}

public moveAt(pos: Position): number {
this.start.offset = this.end.offset = pos.offset;
this.start.line = this.end.line = pos.line;
this.start.column = this.end.column = pos.column;
public moveAt(offset: number): number {
this.start = this.end = offset;

const cp = this.text.codePointAt(this.start.offset) ?? CodePoint.EOF;
const cp = this.text.codePointAt(this.start) ?? CodePoint.EOF;
if (cp === CodePoint.EOF) {
this.end = this.start;
return cp;
}
const shift = cp >= 0x10000 ? 2 : 1;
this.end.offset += shift;
this.end += shift;
if (cp === CodePoint.LINE_FEED) {
this.end.line += 1;
this.end.column = 0;
this.locs.addOffset(this.end);
} else if (cp === CodePoint.CARRIAGE_RETURN) {
if (this.text.codePointAt(this.end.offset) === CodePoint.LINE_FEED) {
this.end.offset++;
this.end.line += 1;
this.end.column = 0;
if (this.text.codePointAt(this.end) === CodePoint.LINE_FEED) {
this.end++;
this.locs.addOffset(this.end);
}
return CodePoint.LINE_FEED;
} else {
this.end.column += shift;
}

return cp;
Expand Down
50 changes: 50 additions & 0 deletions src/tokenizer/locs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* Find the last index of the array that is less than or equal to the value.
*/
function sortedLastIndex(array: number[], value: number): number {
let low = 0;
let high = array.length;

while (low < high) {
const mid = (low + high) >>> 1;
const val = array[mid];
if (val === value) return mid + 1;
if (val < value) {
low = mid + 1;
} else {
high = mid;
}
}

return low;
}

type Location = { line: number; column: number };

/**
* A class for getting lines and columns location.
*/
export class Locations {
private readonly offsets: number[] = [];

public addOffset(offset: number): void {
// Check for dupe offset
for (let i = this.offsets.length - 1; i >= 0; i--) {
const element = this.offsets[i];
if (element === offset) return;
if (element < offset) break;
}
this.offsets.push(offset);
}

/**
* Calculate the location of the given index.
* @param index The index to calculate their location.
* @returns The location of the index.
*/
public getLocFromIndex(offset: number): Location {
const line = sortedLastIndex(this.offsets, offset) + 1;
const column = offset - (line === 1 ? 0 : this.offsets[line - 2]);
return { line, column };
}
}
Loading

0 comments on commit 7104688

Please sign in to comment.