diff options
Diffstat (limited to 'llparse/src/compiler/header-builder.ts')
-rw-r--r-- | llparse/src/compiler/header-builder.ts | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/llparse/src/compiler/header-builder.ts b/llparse/src/compiler/header-builder.ts new file mode 100644 index 0000000..9f5bee7 --- /dev/null +++ b/llparse/src/compiler/header-builder.ts @@ -0,0 +1,80 @@ +import * as frontend from 'llparse-frontend'; +import source = frontend.source; + +export interface IHeaderBuilderOptions { + readonly prefix: string; + readonly headerGuard?: string; + readonly properties: ReadonlyArray<source.Property>; + readonly spans: ReadonlyArray<frontend.SpanField>; +} + +export class HeaderBuilder { + public build(options: IHeaderBuilderOptions): string { + let res = ''; + const PREFIX = options.prefix.toUpperCase().replace(/[^a-z]/gi, '_'); + const DEFINE = options.headerGuard === undefined ? + `INCLUDE_${PREFIX}_H_` : options.headerGuard; + + res += `#ifndef ${DEFINE}\n`; + res += `#define ${DEFINE}\n`; + res += '#ifdef __cplusplus\n'; + res += 'extern "C" {\n'; + res += '#endif\n'; + res += '\n'; + + res += '#include <stdint.h>\n'; + res += '\n'; + + // Structure + res += `typedef struct ${options.prefix}_s ${options.prefix}_t;\n`; + res += `struct ${options.prefix}_s {\n`; + res += ' int32_t _index;\n'; + + for (const [ index, field ] of options.spans.entries()) { + res += ` void* _span_pos${index};\n`; + if (field.callbacks.length > 1) { + res += ` void* _span_cb${index};\n`; + } + } + + res += ' int32_t error;\n'; + res += ' const char* reason;\n'; + res += ' const char* error_pos;\n'; + res += ' void* data;\n'; + res += ' void* _current;\n'; + + for (const prop of options.properties) { + let ty: string; + if (prop.ty === 'i8') { + ty = 'uint8_t'; + } else if (prop.ty === 'i16') { + ty = 'uint16_t'; + } else if (prop.ty === 'i32') { + ty = 'uint32_t'; + } else if (prop.ty === 'i64') { + ty = 'uint64_t'; + } else if (prop.ty === 'ptr') { + ty = 'void*'; + } else { + throw new Error( + `Unknown state property type: "${prop.ty}"`); + } + res += ` ${ty} ${prop.name};\n`; + } + res += '};\n'; + + res += '\n'; + + res += `int ${options.prefix}_init(${options.prefix}_t* s);\n`; + res += `int ${options.prefix}_execute(${options.prefix}_t* s, ` + + 'const char* p, const char* endp);\n'; + + res += '\n'; + res += '#ifdef __cplusplus\n'; + res += '} /* extern "C" *\/\n'; + res += '#endif\n'; + res += `#endif /* ${DEFINE} *\/\n`; + + return res; + } +} |