llparse
Version:
Compile incremental parsers to C code
74 lines (63 loc) • 2.36 kB
text/typescript
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('}');
}
}