///|
/// PEG.js version this port follows.
pub let version : String = "0.11.0"
///|
pub using @runtime {
type Value,
type ActionContext,
type ActionFn,
type InitFn,
type Location,
type Pos,
type Expectation,
type SyntaxError,
type Tracer,
type TraceEvent,
}
///|
pub using @vm {type Parser}
///|
pub using @compiler {
type Session,
type Options,
type Optimize,
type Output,
type GrammarError,
type CompilerError,
}
///|
/// A plugin: may inspect and modify the session (parser, passes, opcodes,
/// backend, reporters) and the options before compilation (`plugin.use`).
pub type Plugin[T] = (Session[T], Options[T]) -> Unit raise
///|
/// A session with the standard grammar parser and passes, including the
/// `generateMoonBit` source generation pass.
pub fn[T] new_session() -> Session[T] {
let session = Session::new(parser=(input, options) => {
@parser.parse(
input,
reserved_words?=options.reserved_words,
extract_comments=options.extract_comments,
filename?=options.filename,
)
})
session.passes.generate.push({
name: "generateMoonBit",
run: @codegen.generate_moonbit,
})
session
}
///|
/// Generates a parser from a PEG.js grammar (`peg.generate`).
///
/// Code blocks in the grammar are implemented in MoonBit through `actions`
/// (keyed by the block's code text, see `@vm.lookup_binding`) and
/// `initializer`. Raises `SyntaxError` for invalid grammar syntax,
/// `GrammarError` / `CompilerError` for semantic errors and
/// `@vm.UnboundCode` for code blocks without an implementation.
pub fn[T] generate(
grammar : String,
options? : Options[T] = Options::new(),
plugins? : Array[Plugin[T]] = [],
) -> Parser[T] raise {
let session : Session[T] = new_session()
for plugin in plugins {
plugin(session, options)
}
let ast = session.parse(grammar, options.parser)
match @compiler.compile(ast, session, options) {
Parser(parser) => parser
Source(_) =>
raise @compiler.CompilerError(
"generate() returns a parser; use output=Parser (source generation is not available through generate)",
)
}
}
///|
/// Generates the MoonBit source of a parser for `grammar`, whose code blocks
/// contain MoonBit code (see the `codegen` package for the conventions).
///
/// Labels may not be MoonBit keywords unless `options.parser.reserved_words`
/// says otherwise. Raises like `generate`.
pub fn[T] generate_source(
grammar : String,
options? : Options[T] = Options::new(),
plugins? : Array[Plugin[T]] = [],
) -> String raise {
let options = options.copy()
options.output = Source
if options.parser.reserved_words is None {
options.parser.reserved_words = Some(@codegen.reserved_words())
}
let session : Session[T] = new_session()
for plugin in plugins {
plugin(session, options)
}
let ast = session.parse(grammar, options.parser)
match @compiler.compile(ast, session, options) {
Source(code) => code
Parser(_) =>
raise @compiler.CompilerError("generate_source() requires output=Source")
}
}