diff --git a/src/index.ts b/src/index.ts index d99eb10..21fc37e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -74,11 +74,28 @@ export class SourceText { return this.source.slice(startOff, endOff); } - // Converts a linear Code Point Index into SourceLocation - // getLocation(index: CodePointIndex): SourceLocation { - // // TODO: can be implemented either by a linear or binary search. - // return (0 as any); - // } + // Converts a linear Code Point Index into a SourceLocation (line, column, index). + getLocation(index: CodePointIndex): SourceLocation { + // Does binary search. + let low = 0; + let high = this.lineStarts.length - 1; + let line = 1; + + while (low <= high) { + const mid = Math.floor((low + high) / 2); + if (this.lineStarts[mid] <= index) { + line = mid + 1; + low = mid + 1; + } else { + high = mid - 1; + } + } + + const lineStartIndex = this.lineStarts[line - 1]; + const column = index - lineStartIndex + 1; + + return { index, line, column }; + } // Returns the full text of a specific line (1-based index) getLineText(line: number): string { @@ -114,6 +131,19 @@ export function sourceText(s: string): SourceText { return new SourceText(s); } +export class SourceRegion { + // TODO + readonly sourceText: SourceText; + readonly span: Span; + + constructor(sourceText: SourceText, span: Span) { + this.sourceText = sourceText; + // TODO: What about span validation? + this.span = span; + } +} + + export type Span = { start: SourceLocation; end: SourceLocation;