diff options
Diffstat (limited to '')
-rw-r--r-- | llparse-builder/src/span.ts | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/llparse-builder/src/span.ts b/llparse-builder/src/span.ts new file mode 100644 index 0000000..99cafb0 --- /dev/null +++ b/llparse-builder/src/span.ts @@ -0,0 +1,57 @@ +import * as assert from 'assert'; + +import { Span as SpanCallback } from './code'; +import { Node, SpanEnd, SpanStart } from './node'; + +/** + * Spans are used for notifying parser user about matched data. Each byte after + * span start will be sent to the span callback until span end is called. + */ +export class Span { + private readonly startCache: Map<Node, SpanStart> = new Map(); + private readonly endCache: Map<Node, SpanEnd> = new Map(); + + /** + * @param callback External callback, must be `code.span(...)` result. + */ + constructor(public readonly callback: SpanCallback) { + } + + /** + * Create `SpanStart` that indicates the start of the span. + * + * @param otherwise Optional convenience value. Same as calling + * `span.start().otherwise(...)` + */ + public start(otherwise?: Node) { + if (otherwise !== undefined && this.startCache.has(otherwise)) { + return this.startCache.get(otherwise)!; + } + + const res = new SpanStart(this); + if (otherwise !== undefined) { + res.otherwise(otherwise); + this.startCache.set(otherwise, res); + } + return res; + } + + /** + * Create `SpanEnd` that indicates the end of the span. + * + * @param otherwise Optional convenience value. Same as calling + * `span.end().otherwise(...)` + */ + public end(otherwise?: Node) { + if (otherwise !== undefined && this.endCache.has(otherwise)) { + return this.endCache.get(otherwise)!; + } + + const res = new SpanEnd(this); + if (otherwise !== undefined) { + res.otherwise(otherwise); + this.endCache.set(otherwise, res); + } + return res; + } +} |