UNPKG

llparse

Version:

Compile incremental parsers to C code

74 lines (63 loc) 2.36 kB
import * as frontend from 'llparse-frontend'; import { SEQUENCE_COMPLETE, SEQUENCE_MISMATCH, SEQUENCE_PAUSE, } from '../constants'; import { Transform } from '../transform'; import { Compilation } from '../compilation'; type TransformWrap = Transform<frontend.transform.Transform>; export class MatchSequence { constructor(private readonly transform: TransformWrap) { } public static buildGlobals(out: string[]): void { out.push('enum llparse_match_status_e {'); out.push(` ${SEQUENCE_COMPLETE},`); out.push(` ${SEQUENCE_PAUSE},`); out.push(` ${SEQUENCE_MISMATCH}`); out.push('};'); out.push('typedef enum llparse_match_status_e llparse_match_status_t;'); out.push(''); out.push('struct llparse_match_s {'); out.push(' llparse_match_status_t status;'); out.push(' const unsigned char* current;'); out.push('};'); out.push('typedef struct llparse_match_s llparse_match_t;'); } public getName(): string { return `llparse__match_sequence_${this.transform.ref.name}`; } public build(ctx: Compilation, out: string[]): void { out.push(`static llparse_match_t ${this.getName()}(`); out.push(` ${ctx.prefix}_t* s, const unsigned char* p,`); out.push(' const unsigned char* endp,'); out.push(' const unsigned char* seq, uint32_t seq_len) {'); // Vars out.push(' uint32_t index;'); out.push(' llparse_match_t res;'); out.push(''); // Body out.push(' index = s->_index;'); out.push(' for (; p != endp; p++) {'); out.push(' unsigned char current;'); out.push(''); out.push(` current = ${this.transform.build(ctx, '*p')};`); out.push(' if (current == seq[index]) {'); out.push(' if (++index == seq_len) {'); out.push(` res.status = ${SEQUENCE_COMPLETE};`); out.push(' goto reset;'); out.push(' }'); out.push(' } else {'); out.push(` res.status = ${SEQUENCE_MISMATCH};`); out.push(' goto reset;'); out.push(' }'); out.push(' }'); out.push(' s->_index = index;'); out.push(` res.status = ${SEQUENCE_PAUSE};`); out.push(' res.current = p;'); out.push(' return res;'); out.push('reset:'); out.push(' s->_index = 0;'); out.push(' res.current = p;'); out.push(' return res;'); out.push('}'); } }