UNPKG

clarity-pattern-parser

Version:

Parsing Library for Typescript and Javascript.

166 lines (131 loc) 4.18 kB
import { Node } from "../ast/Node"; import { Cursor } from "./Cursor"; import { execPattern } from "./execPattern"; import { ParseResult } from "./ParseResult"; import { Pattern } from "./Pattern"; import { testPattern } from "./testPattern"; let idIndex = 0; export class TakeUntil implements Pattern { private _id: string; private _type: string; private _name: string; private _parent: Pattern | null; private _children: Pattern[]; private _startedOnIndex: number; private _terminatingPattern: Pattern; private _tokens: string[]; get id(): string { return this._id; } get type(): string { return this._type; } get name(): string { return this._name; } get children(): Pattern[] { return this._children; } get parent(): Pattern | null { return this._parent; } set parent(pattern: Pattern | null) { this._parent = pattern; } get startedOnIndex(): number { return this._startedOnIndex; } constructor(name: string, terminatingPattern: Pattern) { this._id = String(idIndex++); this._type = "take-until"; this._name = name; this._parent = null; this._terminatingPattern = terminatingPattern; this._children = [this._terminatingPattern]; this._tokens = []; this._startedOnIndex = 0; } parse(cursor: Cursor): Node | null { let cursorIndex = cursor.index; let foundMatch = false; this._startedOnIndex = cursor.index; let terminatingResult = this._terminatingPattern.parse(cursor); cursor.resolveError(); if (terminatingResult == null) { foundMatch = true; cursor.moveTo(cursorIndex); cursorIndex += 1; cursor.hasNext() && cursor.next(); } while (true) { terminatingResult = this._terminatingPattern.parse(cursor); cursor.resolveError(); if (terminatingResult == null) { cursor.moveTo(cursorIndex); cursorIndex += 1; if (cursor.hasNext()) { cursor.next(); } else { break; } } else { break; } } if (foundMatch) { cursor.moveTo(cursorIndex - 1); const value = cursor.getChars(this.startedOnIndex, cursorIndex - 1); const node = Node.createValueNode(this._type, this._name, value); cursor.recordMatch(this, node); return node; } else { cursor.moveTo(this.startedOnIndex); cursor.recordErrorAt(this._startedOnIndex, this._startedOnIndex, this); return null; } } exec(text: string, record?: boolean | undefined): ParseResult { return execPattern(this, text, record); } test(text: string, record?: boolean | undefined): boolean { return testPattern(this, text, record); } clone(name = this.name): Pattern { const clone = new TakeUntil(name, this._terminatingPattern); clone._id = this._id; return clone; } getTokens() { return this._tokens; } getTokensAfter(_childReference: Pattern): string[] { return []; } getNextTokens(): string[] { if (this.parent == null) { return []; } return this.parent.getTokensAfter(this); } getPatterns(): Pattern[] { return [this]; } getPatternsAfter(_childReference: Pattern): Pattern[] { return []; } getNextPatterns(): Pattern[] { if (this.parent == null) { return []; } return this.parent.getPatternsAfter(this); } find(_predicate: (p: Pattern) => boolean): Pattern | null { return null; } setTokens(tokens: string[]) { this._tokens = tokens; } isEqual(pattern: Pattern): boolean { return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index])); } }