llparse
Version:
Compile incremental parsers to C code
56 lines (41 loc) • 1.54 kB
text/typescript
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};`);
}
}