UNPKG

llparse

Version:

Compile incremental parsers to C code

56 lines (41 loc) 1.54 kB
import * as frontend from 'llparse-frontend'; import { STATE_ERROR } from '../constants'; import { Node } from './base'; export class SpanEnd extends Node<frontend.node.SpanEnd> { public doBuild(out: string[]): void { out.push('const unsigned char* start;'); out.push('int err;'); out.push(''); const ctx = this.compilation; const field = this.ref.field; const posField = ctx.spanPosField(field.index); // Load start position out.push(`start = ${posField};`); // ...and reset out.push(`${posField} = NULL;`); // Invoke callback const callback = ctx.buildCode(ctx.unwrapCode(this.ref.callback)); out.push(`err = ${callback}(${ctx.stateArg()}, start, ${ctx.posArg()});`); out.push('if (err != 0) {'); const tmp: string[] = []; this.buildError(tmp, 'err'); ctx.indent(out, tmp, ' '); out.push('}'); const otherwise = this.ref.otherwise!; this.tailTo(out, otherwise); } private buildError(out: string[], code: string) { const ctx = this.compilation; out.push(`${ctx.errorField()} = ${code};`); const otherwise = this.ref.otherwise!; let resumePos = ctx.posArg(); if (!otherwise.noAdvance) { resumePos = `(${resumePos} + 1)`; } out.push(`${ctx.errorPosField()} = (const char*) ${resumePos};`); const resumptionTarget = ctx.unwrapNode(otherwise.node).build(ctx); out.push(`${ctx.currentField()} = ` + `(void*) (intptr_t) ${resumptionTarget};`); out.push(`return ${STATE_ERROR};`); } }