External Declarations
DaeDaLus supports an interface for declaring parsers and types whose implementations are provided by the code generation backend (currently C++). This is useful when integrating DaeDaLus-generated code with host-language libraries or when certain operations cannot be expressed in DaeDaLus itself.
External Primitives
A declaration with a type signature but no body declares an external primitive:
def SetSpecial (x : uint 8) : {}
def GetSpecial : uint 8
This tells DaeDaLus that these parsers exist with the given types, but their implementations must be provided by the code generation backend. External primitives may not use implicit parameters.
When generating C++, the code generator emits an extern declaration
for each external primitive. The user must provide a corresponding
implementation. For a parser returning type T with parameters
p1, ..., pN, the C++ signature is:
DDL::ParserResult parser_Name(
DDL::ParserState& state,
T* result, DDL::Input* newInput,
DDL::Input currentInput, P1 p1, ..., PN pN);
The function should return DDL::ParserResult::Ok on success (setting
*result and *newInput), DDL::ParserResult::Failure on parse
failure, or DDL::ParserResult::Exception for unrecoverable errors.
Reference-typed arguments (arrays, maps, streams, etc.) are passed as owned values. This means that on failure the external function is responsible for deallocating them. On success, ownership of the arguments is considered transferred and the caller will not free them.
Here is a complete example:
// Implementation of: def GetSpecial : uint 8
DDL::ParserResult parser_GetSpecial(
DDL::ParserStateUser<DDL::Input, State>& state,
DDL::UInt<8>* result, DDL::Input* newInput,
DDL::Input currentInput) {
*result = DDL::UInt<8>(state.getUserState().get());
*newInput = currentInput;
return DDL::ParserResult::Ok;
}
External Module Imports
When importing a module, the extern keyword indicates that the
code generator should not produce type definitions for that module:
import extern MyTypes
This is useful when compiling multiple parser specifications separately
that share common type definitions. Without extern, each compiled
specification would generate its own copy of the shared types, leading
to duplicate definitions. With import extern, one specification
generates the type definitions and the others simply reference them
without generating them again.