llparse
Version:
Compile incremental parsers to C code
89 lines (72 loc) • 2.04 kB
text/typescript
import * as debugAPI from 'debug';
import * as frontend from 'llparse-frontend';
import source = frontend.source;
import * as cImpl from '../implementation/c';
import { HeaderBuilder } from './header-builder';
const debug = debugAPI('llparse:compiler');
export interface ICompilerOptions {
/**
* Debug method name
*
* The method must have following signature:
*
* ```c
* void debug(llparse_t* state, const char* p, const char* endp,
* const char* msg);
* ```
*
* Where `llparse_t` is a parser state type.
*/
readonly debug?: string;
/**
* What guard define to use in `#ifndef` in C headers.
*
* Default value: `prefix` argument
*/
readonly headerGuard?: string;
/** Optional frontend configuration */
readonly frontend?: frontend.IFrontendLazyOptions;
/** Optional C-backend configuration */
readonly c?: cImpl.ICPublicOptions;
}
export interface ICompilerResult {
/**
* Textual C code
*/
readonly c: string;
/**
* Textual C header file
*/
readonly header: string;
}
export class Compiler {
constructor(public readonly prefix: string,
public readonly options: ICompilerOptions) {
}
public compile(root: source.node.Node,
properties: ReadonlyArray<source.Property>): ICompilerResult {
debug('Combining implementations');
const container = new frontend.Container();
const c = new cImpl.CCompiler(container, Object.assign({
debug: this.options.debug,
}, this.options.c));
debug('Running frontend pass');
const f = new frontend.Frontend(this.prefix,
container.build(),
this.options.frontend);
const info = f.compile(root, properties);
debug('Building header');
const hb = new HeaderBuilder();
const header = hb.build({
headerGuard: this.options.headerGuard,
prefix: this.prefix,
properties,
spans: info.spans,
});
debug('Building C');
return {
header,
c: c.compile(info),
};
}
}