diff --git a/src/index.ts b/src/index.ts index c9fe663..5f65eeb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,11 +8,49 @@ export function char(c: string): CodePoint { return c.codePointAt(0) as CodePoint; } +// Whitespace +export const NEW_LINE: CodePoint = char('\n'); +export const CARRIAGE_RETURN: CodePoint = char('\r'); +export const SPACE: CodePoint = char(' '); +export const TAB: CodePoint = char('\t'); + +// Digit Boundaries +export const DIGIT_0: CodePoint = char('0'); +export const DIGIT_9: CodePoint = char('9'); + +export const DOT: CodePoint = char('.'); + +// Hex Boundaries +export const LOWERCASE_a: CodePoint = char('a'); +export const UPPERCASE_A: CodePoint = char('A'); +export const LOWERCASE_f: CodePoint = char('f'); +export const UPPERCASE_F: CodePoint = char('F'); +export const LOWERCASE_z: CodePoint = char('z'); +export const UPPERCASE_Z: CodePoint = char('Z'); + + +export function isBetween(a: CodePoint, x: CodePoint, b: CodePoint): boolean { + return a <= x && x <= b; +} + +export function isDigit(x: CodePoint): boolean { + return isBetween(DIGIT_0, x, DIGIT_9); +} + +export function isAlphanumeric(x: CodePoint): boolean { + return isDigit(x) || isBetween(LOWERCASE_a, x, LOWERCASE_z) || isBetween(LOWERCASE_z, x, UPPERCASE_Z); +} + export type CodePointRef = { char: CodePoint, offset: StringIndex, }; +export type CodePointSpan = { + start: CodePointIndex, + end: CodePointIndex, +} + // === Source Text === export class SourceText { readonly source: string; @@ -147,6 +185,10 @@ export class SourceText { return { index, line, column }; } + getSpan(span: CodePointSpan): Span { + return { start: this.getLocation(span.start), end: this.getLocation(span.end) }; + } + // Creates a SourceRegion from a Span. makeRegion(span: Span): SourceRegion { // Basic validation @@ -202,6 +244,10 @@ export function span(start: SourceLocation, end: SourceLocation): Span { return { start, end }; } +export function rawSpan(start: CodePointIndex, end: CodePointIndex): CodePointSpan { + return { start, end }; +} + export class SourceRegion { constructor( public readonly source: SourceText, @@ -238,11 +284,11 @@ export class SourceRegion { } toString(): string { - return this.source.sliceByCp(this.span.start.index, this.span.end.index); + return this.stringOf(this.span); } stringOf(span: Span): string { - return this.subRegion(span).toString(); + return this.source.sliceByCp(span.start.index, span.end.index); } // Returns a Span for the given line (1-based index). @@ -292,24 +338,6 @@ export type SourceLocation = { column: number; // 1-based } -// Whitespace -export const NEW_LINE: CodePoint = char('\n'); -export const CARRIAGE_RETURN: CodePoint = char('\r'); -export const SPACE: CodePoint = char(' '); -export const TAB: CodePoint = char('\t'); - -// Digit Boundaries -export const DIGIT_0: CodePoint = char('0'); -export const DIGIT_9: CodePoint = char('9'); - -export const DOT: CodePoint = char('.'); - -// Hex Boundaries -export const LOWERCASE_a: CodePoint = char('a'); -export const UPPERCASE_A: CodePoint = char('A'); -export const LOWERCASE_f: CodePoint = char('f'); -export const UPPERCASE_F: CodePoint = char('F'); - // === Rendering Utilities === export type LineView = {