The Kollos code
Table of contents
* [About Kollos](#about-kollos)
* [Kollos object](#kollos-object)
* [Kollos Lua interpreter](#kollos-lua-interpreter)
* [Kollos registry objects](#kollos-registry-objects)
* [Kollos recognizer registry object](#kollos-recognizer-registry-object)
* [Kollos semantics](#kollos-semantics)
* [VM operations](#vm-operations)
* [VM debug operation](#vm-debug-operation)
* [VM no-op operation](#vm-no-op-operation)
* [VM bail operation](#vm-bail-operation)
* [VM result operations](#vm-result-operations)
* [VM "result is undef" operation](#vm-result-is-undef-operation)
* [VM "result is token value" operation](#vm-result-is-token-value-operation)
* [VM "result is N of RHS" operation](#vm-result-is-n-of-rhs-operation)
* [VM "result is N of sequence" operation](#vm-result-is-n-of-sequence-operation)
* [VM operation: result is constant](#vm-operation-result-is-constant)
* [Operation of the values array](#operation-of-the-values-array)
* [VM "push undef" operation](#vm-push-undef-operation)
* [VM "push one" operation](#vm-push-one-operation)
* [Find current token literal](#find-current-token-literal)
* [VM "push values" operation](#vm-push-values-operation)
* [VM operation: push start location](#vm-operation-push-start-location)
* [VM operation: push length](#vm-operation-push-length)
* [VM operation: push G1 start location](#vm-operation-push-g1-start-location)
* [VM operation: push G1 length](#vm-operation-push-g1-length)
* [VM operation: push constant onto values array](#vm-operation-push-constant-onto-values-array)
* [VM operation: set the array blessing](#vm-operation-set-the-array-blessing)
* [VM operation: result is array](#vm-operation-result-is-array)
* [VM operation: callback](#vm-operation-callback)
* [Run the virtual machine](#run-the-virtual-machine)
* [Find and perform the VM operations](#find-and-perform-the-vm-operations)
* [VM-related utilities for use in the Perl code](#vm-related-utilities-for-use-in-the-perl-code)
* [Return operation key given its name](#return-operation-key-given-its-name)
* [Return operation name given its key](#return-operation-name-given-its-key)
* [Register a constant](#register-a-constant)
* [Register semantics for a token](#register-semantics-for-a-token)
* [Register semantics for a nulling symbol](#register-semantics-for-a-nulling-symbol)
* [Register semantics for a rule](#register-semantics-for-a-rule)
* [Return the top index of the stack](#return-the-top-index-of-the-stack)
* [Return the value of a stack entry](#return-the-value-of-a-stack-entry)
* [Set the value of a stack entry](#set-the-value-of-a-stack-entry)
* [The Kollos valuator](#the-kollos-valuator)
* [Initialize a valuator](#initialize-a-valuator)
* [Reset a valuator](#reset-a-valuator)
* [Libmarpa interface](#libmarpa-interface)
* [Standard template methods](#standard-template-methods)
* [The main Lua code file](#the-main-lua-code-file)
* [Preliminaries to the main code](#preliminaries-to-the-main-code)
* [The Kollos C code file](#the-kollos-c-code-file)
* [Stuff from okollos](#stuff-from-okollos)
* [`marpa_luaopen_kollos`](#marpa-luaopen-kollos)
* [Create a sandbox](#create-a-sandbox)
* [Preliminaries to the C library code](#preliminaries-to-the-c-library-code)
* [The Kollos C header file](#the-kollos-c-header-file)
* [Preliminaries to the C header file](#preliminaries-to-the-c-header-file)
* [Meta-coding utilities](#meta-coding-utilities)
* [Metacode execution sequence](#metacode-execution-sequence)
* [Dedent method](#dedent-method)
* [`c_safe_string` method](#c-safe-string-method)
* [Meta code argument processing](#meta-code-argument-processing)
bf2a558f14c663091120f585ef578ac9
This is the code for Kollos, the "middle layer" of Marpa.
Below it is Libmarpa, a library written in
the C language which contains the actual parse engine.
Above it is code in a higher level language -- at this point Perl.
This document is evolving. Most of the "middle layer" is still
in the Perl code or in the Perl XS, and not represented here.
This document only contains those portions converted to Lua or
to Lua-centeric C code.
The intent is that eventually
all the code in this file will be "pure"
Kollos -- no Perl knowledge.
That is not the case at the moment.
0588207666332b8ab79ee6ce927acf39
`ref_count` maintains a reference count that controls
the destruction of Kollos interpreters.
`warn` is for a warning callback -- it's not
currently used.
`buffer` is used by kollos internally, usually
for buffering symbol ID's in the libmarpa wrappers.
`buffer_capacity` is its current capacity.
The buffer strategy currently is to set its capacity to the
maximum symbol count of any of the grammars in the Kollos
interpreter.
```
-- miranda: section C function declarations
struct kollos_extraspace {
int ref_count;
int (*warn)(const char* format, ...);
Marpa_Symbol_ID *buffer;
size_t buffer_capacity;
};
```
1173d082650b8da97d45d0ceae562b13
A Kollos object is a Lua interpreter.
It keeps its own reference count, in its Lua registry.
`kollos_newstate()`,
the constructor, creates one reference
and gives its caller ownership.
When
the reference count falls to zero,
the interpreter (Kollos object) is destroyed.
```
8dc5321d52246096af3fce6bf7079ead
```
```
-- miranda: section+ lua interpreter management
static int default_warn(const char *format, ...)
{
va_list args;
va_start (args, format);
vfprintf (stderr, format, args);
va_end (args);
fputs("\n", stderr);
return 1;
}
```
`kollos_refinc()`
creates a new reference
to a Kollos interpreter,
and takes ownership of it.
```
d8a818172d3e6c6c60120195d23c8957
```
Give up ownership of a reference to a Kollos interpreter.
Deletes the interpreter if the reference count drops to zero.
```
624852863f01be8f2a031e9ad45fd5f1
```
Set the warning function of the Kollos interpreter.
```
758bbaadef7734c52c63f5c8a619b770
```
Write a warning message using Kollos's warning handler.
```
16a17165e2618fde2932b56b60feae54
```
5c2608a9792709eface89be5423234ac
A Kollos registry object is an object kept in its
registry.
These generated ID's which allow them to be identified
safely to non-Lua code.
They have increment and decrement methods.
These increment and decrement methods are intended only
for non-Lua code.
They make it possible
for the non-Lua code to be sure that the Lua
registry object exists for as long as they
require it.
Lua code should not use the reference counter.
Lua code
should simply copy the table object -- in Lua this
is a reference and Lua's GC will do the right thing.
`kollos_robrefinc()`
creates a new reference
to a Kollos registry object,
and takes ownership of it.
```
a29029d9e6a9b931e05c2cbfea26c949
```
Give up ownership of a reference to a Kollos registry object.
Deletes the interpreter if the reference count drops to zero.
```
097a87815361f731eb63264dc2c16c70
```
62bd3d6ba9532bf11e748f0471c2ecc4
Add a recce to the Kollos object, returning its
"lua_id".
The inner SLR C structure is passed in for now,
because it uses a lot of PERL/XS data structures.
```
-- miranda: section+ C function declarations
#define MT_NAME_RECCE "Marpa_recce"
int kollos_slr_new(lua_State* L, void* slr, int slg_ref);
-- miranda: section+ lua interpreter management
int kollos_slr_new(lua_State* L, void* slr, int slg_ref)
{
int lua_id;
const int base_of_stack = marpa_lua_gettop(L);
marpa_lua_checkstack(L, 20);
/* Lua stack: [] */
/* Create a table for this recce */
marpa_lua_newtable(L);
/* Lua stack: [ recce_table ] */
/* No lock held -- SLR must delete recce table in its */
/* destructor. */
/* Set the metatable for the recce table */
marpa_luaL_setmetatable(L, MT_NAME_RECCE);
/* Lua stack: [ recce_table ] */
c1fd400d0b5b5ace768706beb58858fa
```
5b9a9112f57b37f75fd55930c211df74
Initially, Marpa's semantics were performed using a VM (virtual machine)
of about two dozen
operations. I am converting them to Lua, one by one. Once they are in
Lua, the flexibility in defining operations becomes much greater than when
they were in C/XS. The set of operations which can be defined becomes
literally open-ended.
With Lua replacing C, the constraints which dictated the original design
of this VM are completely altered.
It remains an open question what becomes of this VM and its operation
set as Marpa evolves.
For example,
at the extreme end, every program in the old VM could be replaced with
one that is a single instruction long, with that single instruction
written entirely in Lua.
If this were done, there no longer would be a VM, in any real sense of the
word.
4ae16c025d4dc446cd1f3a6f1caf8f52
A return value of -1 indicates this should be the last VM operation.
A return value of 0 or greater indicates this is the last VM operation,
and that there is a Perl callback with the contents of the values array
as its arguments.
A return value of -2 or less indicates that the reading of VM operations
should continue.
Note the use of tails calls in the Lua code.
Maintainters should be aware that these are finicky.
In particular, while `return f(x)` is turned into a tail call,
`return (f(x))` is not.
2f313f5ac2063d40305558f28f692d57
Was used for development.
Perhaps I should delete this.
```
-- miranda: section VM operations
c4904e2f72cc7db901151f0779f32e68
```
44a4004e70e89025a1c728637ca1d67f
This is to be kept after development,
even if not used.
It may be useful in debugging.
```
-- miranda: section+ VM operations
9722a601245229d5e245e63bc47d98ff
```
e3f53a85136413a47ccd6a60af813a59
This is to used for development.
Its intended use is as a dummy argument,
which, if it is used by accident
as a VM operation,
fast fails with a clear message.
```
-- miranda: section+ VM operations
b2ddb036f551a285ac82152397e4ae2f
```
34aa84263d21d3e220f21ceec0d7a2c7
If an operation in the VM returns -1, it is a
"result operation".
The actual result is expected to be in the stack
at index `recce.this_step.result`.
The result operation is not required to be the
last operation in a sequence,
and
a sequence of operations does not have to contain
a result operation.
If there are
other operations after the result operation,
they will not be performed.
If a sequence ends without encountering a result
operation, an implicit "no-op" result operation
is assumed and, as usual,
the result is the value in the stack
at index `recce.this_step.result`.
32f82d9c075283bbb3cb4174a8c16470
Perhaps the simplest operation.
The result of the semantics is a Perl undef.
```
-- miranda: section+ VM operations
a7d39bbbdbcc273c2b940371356db93b
```
fe90344d864bba24a43f406f6d3af84d
The result of the semantics is the value of the
token at the current location.
It's assumed to be a MARPA_STEP_TOKEN step --
if not the value is an undef.
```
-- miranda: section+ VM operations
2aebdb72fa38eea8ae37f7d598f78107
```
3b34f3dc418a7f6e4b2205e6c5422596
```
-- miranda: section+ VM operations
function op_fn_result_is_n_of_rhs(recce, rhs_ix)
if recce.this_step.type ~= 'MARPA_STEP_RULE' then
return op_fn_result_is_undef(recce)
end
local stack = recce.lmw_v.stack
local result_ix = recce.this_step.result
repeat
if rhs_ix == 0 then break end
local fetch_ix = result_ix + rhs_ix
if fetch_ix > recce.this_step.arg_n then
stack[result_ix] = marpa.sv.undef()
break
end
stack[result_ix] = stack[fetch_ix]
until 1
return -1
end
```
cd80be994a4857cc082c703e5179040d
In `stack`,
set the result to the `item_ix`'th item of a sequence.
`stack` is a 0-based Perl AV.
Here "sequence" means a sequence in which the separators
have been kept.
For those with separators discarded,
the "N of RHS" operation should be used.
```
-- miranda: section+ VM operations
function op_fn_result_is_n_of_sequence(recce, item_ix)
if recce.this_step.type ~= 'MARPA_STEP_RULE' then
return op_fn_result_is_undef(recce)
end
local result_ix = recce.this_step.result
local fetch_ix = result_ix + item_ix * 2
if fetch_ix > recce.this_step.arg_n then
return op_fn_result_is_undef(recce)
end
local stack = recce.lmw_v.stack
if item_ix > 0 then
stack[result_ix] = stack[fetch_ix]
end
return -1
end
```
40e7018a85d565854fdb79cd9ef85870
Returns a constant result.
```
-- miranda: section+ VM operations
function op_fn_result_is_constant(recce, constant_ix)
local constants = recce:constants()
local constant = constants[constant_ix]
local stack = recce.lmw_v.stack
local result_ix = recce.this_step.result
stack[result_ix] = constant
if recce.trace_values > 0 and recce.this_step.type == 'MARPA_STEP_TOKEN' then
local top_of_queue = #recce.trace_values_queue
recce.trace_values_queue[top_of_queue+1] =
{ "valuator unknown step", recce.this_step.type, recce.token, constant}
-- io.stderr:write('valuator unknown step: ', inspect(recce))
end
return -1
end
```
213d43d4daa1b8176e29a5e16b995b06
The following operations add elements to the `values` array.
This is a special array which may eventually be the result of the
sequence of operations.
c97efefd1aeba097cce106af5310b8ac
Push an undef on the values array.
```
-- miranda: section+ VM operations
4688b5ed213f8f9d47db310042bfb0f7
```
3105ae29bd58291bc331b2d8337f713f
Push one of the RHS child values onto the values array.
```
-- miranda: section+ VM operations
61d74f60453e18a9914e711a2d635b5a
```
607f9d33c8519236b071d773a415bdc3
`current_token_literal` return the literal
equivalent of the current token.
It assumes that there *is* a current token,
that is,
it assumes that the caller has ensured that
`recce.this_step.type ~= 'MARPA_STEP_TOKEN'`.
```
-- miranda: section+ VM operations
function current_token_literal(recce)
if recce.token_is_literal == recce.this_step.value then
local start_es = recce.this_step.start_es_id
local end_es = recce.this_step.es_id
return recce:literal_of_es_span(start_es, end_es)
end
return recce.token_values[recce.this_step.value]
end
```
9eac4c7ab8443d2b081c4a567504ce44
Push the child values onto the `values` list.
If it is a token step, then
the token at the current location is pushed onto the `values` list.
If it is a nulling step, the nothing is pushed.
Otherwise the values of the RHS children are pushed.
`increment` is 2 for sequences where separators must be discarded,
1 otherwise.
```
-- miranda: section+ VM operations
845aaf32c7b6a13f850fb90fb7722a22
```
bd96c22212c42eeb154d27741a7c3907
The current start location in input location terms -- that is,
in terms of the input string.
```
-- miranda: section+ VM operations
function op_fn_push_start(recce, dummy, new_values)
local start_es = recce.this_step.start_es_id
local end_es = recce.this_step.es_id
local start, l = recce:span(start_es, end_es)
local next_ix = marpa.sv.top_index(new_values) + 1;
local _
new_values[next_ix], _ = recce:span(start_es, end_es)
return -2
end
```
9881048d9a6628ba3918cec5c11799a7
The length of the current step in input location terms --
that is, in terms of the input string
```
-- miranda: section+ VM operations
function op_fn_push_length(recce, dummy, new_values)
local start_es = recce.this_step.start_es_id
local end_es = recce.this_step.es_id
local next_ix = marpa.sv.top_index(new_values) + 1;
local _
_, new_values[next_ix] = recce:span(start_es, end_es)
return -2
end
```
5060000ef023dbe5de55262804395b4e
The current start location in G1 location terms -- that is,
in terms of G1 Earley sets.
```
-- miranda: section+ VM operations
function op_fn_push_g1_start(recce, dummy, new_values)
local next_ix = marpa.sv.top_index(new_values) + 1;
new_values[next_ix] = recce.this_step.start_es_id
return -2
end
```
a076ffdd247bf6503b3cefd8f3e7aa9a
The length of the current step in G1 terms --
that is, in terms of G1 Earley sets.
```
-- miranda: section+ VM operations
function op_fn_push_g1_length(recce, dummy, new_values)
local next_ix = marpa.sv.top_index(new_values) + 1;
new_values[next_ix] = (recce.this_step.es_id
- recce.this_step.start_es_id) + 1
return -2
end
```
20c9eb68722cd214070737fa5ca649a5
```
-- miranda: section+ VM operations
function op_fn_push_constant(recce, constant_ix, new_values)
local constants = recce:constants()
-- io.stderr:write('constants: ', inspect(constants), "\n")
-- io.stderr:write('constant_ix: ', constant_ix, "\n")
-- io.stderr:write('constants top ix: ', marpa.sv.top_index(constants), "\n")
bcd3517f0e80d9a9dfa779dedae3b4f1
```
24ea833cc539cfcdcd2eaa2cc836ac32
The blessing is registered in a constant, and this operation
lets the VM know its index. The index is cleared at the beginning
of every sequence of operations
```
-- miranda: section+ VM operations
function op_fn_bless(recce, blessing_ix)
recce.this_step.blessing_ix = blessing_ix
return -2
end
```
c9752cce1826bbf8bd52c0d93bc788b6
This operation tells the VM that the current `values` array
is the result of this sequence of operations.
```
-- miranda: section+ VM operations
function op_fn_result_is_array(recce, dummy, new_values)
local blessing_ix = recce.this_step.blessing_ix
if blessing_ix then
local constants = recce:constants()
local blessing = constants[blessing_ix]
marpa.sv.bless(new_values, blessing)
end
local stack = recce.lmw_v.stack
local result_ix = recce.this_step.result
stack[result_ix] = new_values
return -1
end
```
e38e80875d78f9d94f7aea75359401de
Tells the VM to create a callback to Perl, with
the `values` array as an argument.
The return value of 3 is a vestige of an earlier
implementation, which returned the size of the
`values` array.
```
-- miranda: section+ VM operations
function op_fn_callback(recce, dummy, new_values)
local step_type = recce.this_step.type
if step_type ~= 'MARPA_STEP_RULE'
and step_type ~= 'MARPA_STEP_NULLING_SYMBOL'
then
io.stderr:write(
'Internal error: callback for wrong step type ',
step_type
)
os.exit(false)
end
local blessing_ix = recce.this_step.blessing_ix
if blessing_ix then
local constants = recce:constants()
local blessing = constants[blessing_ix]
marpa.sv.bless(new_values, blessing)
end
return 3
end
```
73a6d1e740a3922624acc288aa423f48
```
-- miranda: section+ VM operations
function do_ops(recce, ops, new_values)
local op_ix = 1
while op_ix <= #ops do
local op_code = ops[op_ix]
if op_code == 0 then return -1 end
if op_code ~= op_lua then
end
-- io.stderr:write('op_code: ', inspect(op_code), '\\n')
-- io.stderr:write('op_lua: ', inspect(op_lua), '\\n')
local fn_key = ops[op_ix+1]
-- io.stderr:write('ops: ', inspect(ops), '\\n')
-- io.stderr:write('fn_key: ', inspect(fn_key), '\\n')
-- io.stderr:write('fn name: ', recce.op_fn_key[fn_key], '\\n')
local arg = ops[op_ix+2]
-- io.stderr:write('arg: ', inspect(arg), '\\n')
if recce.trace_values >= 3 then
local queue = recce.trace_values_queue
local tag = 'starting lua op'
queue[#queue+1] = {'starting op', recce.this_step.type, 'lua'}
queue[#queue+1] = {tag, recce.this_step.type, recce.op_fn_key[fn_key]}
-- io.stderr:write('starting op: ', inspect(recce))
end
local op_fn = recce[fn_key]
local result = op_fn(recce, arg, new_values)
if result >= -1 then return result end
op_ix = op_ix + 3
end
return -1
end
```
6140eb2bf9dee8f905549d49d3ea6377
Determine the appropriate VM operations for this
step, and perform them.
Return codes are
c774493032c8e76e2ac94bf262124d1c
The mnemonic for these codes is
that they represent the size of the list returned to Perl,
with "trace" and "do not return" being special cases.
```
-- miranda: section+ VM operations
function find_and_do_ops(recce)
recce.trace_values_queue = {}
while true do
local new_values = marpa.sv.av_new()
local ops = {}
recce:step()
if recce.this_step.type == 'MARPA_STEP_INACTIVE' then
return 0, new_values
end
if recce.this_step.type == 'MARPA_STEP_RULE' then
ops = recce.rule_semantics[recce.this_step.rule]
if not ops then
ops = recce.rule_semantics.default
end
goto DO_OPS
end
if recce.this_step.type == 'MARPA_STEP_TOKEN' then
ops = recce.token_semantics[recce.this_step.symbol]
if not ops then
ops = recce.token_semantics.default
end
goto DO_OPS
end
if recce.this_step.type == 'MARPA_STEP_NULLING_SYMBOL' then
ops = recce.nulling_semantics[recce.this_step.symbol]
if not ops then
ops = recce.nulling_semantics.default
end
goto DO_OPS
end
if true then return 1, new_values end
::DO_OPS::
if not ops then
error(string.format('No semantics defined for %s', recce.this_step.type))
end
local do_ops_result = do_ops(recce, ops, new_values)
local stack = recce.lmw_v.stack
-- truncate stack
local above_top = recce.this_step.result + 1
for i = above_top,#stack do stack[i] = nil end
if do_ops_result > 0 then
return 3, new_values
end
if #recce.trace_values_queue > 0 then return -1, new_values end
end
end
```
794c0d2d40add6139468882ae5dbcaf1
The following operations are used by the higher-level Perl code
to set and discover various Lua values.
0024e3157be76a7c016404cb7d408f19
```
-- miranda: section Utilities for Perl code
function get_op_fn_key_by_name(recce, op_name_sv)
local op_name = tostring(op_name_sv)
return recce.op_fn_key[op_name]
end
```
8a24df87bd9b12aa7ec6c4cddddbb11e
```
-- miranda: section+ Utilities for Perl code
function get_op_fn_name_by_key(recce, op_key_sv)
local op_key = op_key_sv + 0
return recce.op_fn_key[op_key]
end
```
ba87cf8544db8bb5e9bcdb3dd936c060
Register a constant, returning its key.
```
-- miranda: section+ Utilities for Perl code
function constant_register(recce, constant_sv)
local constants = recce:constants()
local next_constant_key = marpa.sv.top_index(constants) + 1
constants[next_constant_key] = constant_sv
return next_constant_key
end
```
f1c0d0d498b68bbd08dfdaf213f231ff
Register the semantic operations, `ops`, for the token
whose id is `id`.
```
-- miranda: section+ Utilities for Perl code
function token_register(...)
local args = {...}
local recce = args[1]
local id = args[2]+0
local ops = {}
for ix = 3, #args do
ops[#ops+1] = args[ix]+0
end
recce.token_semantics[id] = ops
end
```
51dda6c2d8175b580a563748f50efaa2
Register the semantic operations, `ops`, for the nulling symbol
whose id is `id`.
```
-- miranda: section+ Utilities for Perl code
function nulling_register(...)
local args = {...}
local recce = args[1]
local id = args[2]+0
local ops = {}
for ix = 3, #args do
ops[#ops+1] = args[ix]+0
end
recce.nulling_semantics[id] = ops
end
```
e1bc5b0da11d1f83680c5c20e585e76d
Register the semantic operations, `ops`, for the rule
whose id is `id`.
```
-- miranda: section+ Utilities for Perl code
function rule_register(...)
local args = {...}
local recce = args[1]
local id = args[2]+0
local ops = {}
for ix = 3, #args do
ops[#ops+1] = args[ix]+0
end
recce.rule_semantics[id] = ops
end
```
657ce8475e95a259230444aeea05d9c3
```
-- miranda: section+ Utilities for Perl code
function stack_top_index(recce)
return recce.this_step.result
end
```
f776cb87d6732a84fa565bcb393aefec
```
-- miranda: section+ Utilities for Perl code
function stack_get(recce, ix)
local stack = recce.lmw_v.stack
return stack[ix+0]
end
```
5d2cf9e4a56c7aa8cd3b2600a5bbc0c5
```
-- miranda: section+ Utilities for Perl code
function stack_set(recce, ix, v)
local stack = recce.lmw_v.stack
stack[ix+0] = v
end
```
93bd16199227703f4bb77f151470ab35
The "valuator" portion of Kollos produces the
value of a
Kollos parse.
f68f883f3bab97e21a4e28c792ff41fc
Called when a valuator is set up.
```
-- miranda: section value_init()
f1a520a8d23ecf3bd516d633f7984951
```
e0b664f8a57aa6845fb38fa50f79792b
A function to be called whenever a valuator is reset.
It should free all memory associated with the valuation.
```
8a57810aa29697569876565d51d713c5
```
d82f5d1e82b8649109f4a3e37a8da9ce
```
-- miranda: section+ diagnostics
function and_node_tag(recce, and_node_id)
local bocage = recce.lmw_b
local parent_or_node_id = bocage:_and_node_parent(and_node_id)
local origin = bocage:_or_node_origin(parent_or_node_id)
local origin_earleme = recce.lmw_g1r:earleme(origin)
fbf0166447d88a48663a332d8475fe32
`show_bocage` returns a string which describes the bocage.
12f729bd0c7fc024cc955558255bb027
```
7225cb31284d54300be9a4223acfa505
```
--[==[ miranda: exec libmarpa interface globals
3de7d2644a5cab9b69ff7dfbe97652ae
```
4420a578dbc938521d8b0b4bd168a386
Here are the meta-programmed wrappers --
This is Lua code which writes the C code based on
a "signature" for the wrapper
This meta-programming does not attempt to work for
all of the wrappers. It works only when
1. The number of arguments is fixed.
2. Their type is from a fixed list.
3. Converting the return value to int is a good thing to do.
4. Non-negative return values indicate success
5. Return values less than -1 indicate failure
6. Return values less than -1 set the error code
7. Return value of -1 is "soft" and returning nil is
the right thing to do
On those methods for which the wrapper requirements are "bent"
a little bit:
3acedea147ab7d66bcd548db53d81f7c
```
-- miranda: section standard libmarpa wrappers
--[==[ miranda: exec declare standard libmarpa wrappers
signatures = {
{"marpa_g_completion_symbol_activate", "Marpa_Symbol_ID", "sym_id", "int", "activate"},
{"marpa_g_error_clear"},
{"marpa_g_event_count"},
{"marpa_g_force_valued"},
{"marpa_g_has_cycle"},
{"marpa_g_highest_rule_id"},
{"marpa_g_highest_symbol_id"},
{"marpa_g_is_precomputed"},
{"marpa_g_nulled_symbol_activate", "Marpa_Symbol_ID", "sym_id", "int", "activate"},
{"marpa_g_prediction_symbol_activate", "Marpa_Symbol_ID", "sym_id", "int", "activate"},
{"marpa_g_rule_is_accessible", "Marpa_Rule_ID", "rule_id"},
{"marpa_g_rule_is_loop", "Marpa_Rule_ID", "rule_id"},
{"marpa_g_rule_is_nullable", "Marpa_Rule_ID", "rule_id"},
{"marpa_g_rule_is_nulling", "Marpa_Rule_ID", "rule_id"},
{"marpa_g_rule_is_productive", "Marpa_Rule_ID", "rule_id"},
{"marpa_g_rule_is_proper_separation", "Marpa_Rule_ID", "rule_id"},
{"marpa_g_rule_length", "Marpa_Rule_ID", "rule_id"},
{"marpa_g_rule_lhs", "Marpa_Rule_ID", "rule_id"},
{"marpa_g_rule_null_high", "Marpa_Rule_ID", "rule_id"},
{"marpa_g_rule_null_high_set", "Marpa_Rule_ID", "rule_id", "int", "flag"},
{"marpa_g_rule_rhs", "Marpa_Rule_ID", "rule_id", "int", "ix"},
{"marpa_g_sequence_min", "Marpa_Rule_ID", "rule_id"},
{"marpa_g_sequence_separator", "Marpa_Rule_ID", "rule_id"},
{"marpa_g_start_symbol"},
{"marpa_g_start_symbol_set", "Marpa_Symbol_ID", "id"},
{"marpa_g_symbol_is_accessible", "Marpa_Symbol_ID", "symbol_id"},
{"marpa_g_symbol_is_completion_event", "Marpa_Symbol_ID", "sym_id"},
{"marpa_g_symbol_is_completion_event_set", "Marpa_Symbol_ID", "sym_id", "int", "value"},
{"marpa_g_symbol_is_counted", "Marpa_Symbol_ID", "symbol_id"},
{"marpa_g_symbol_is_nullable", "Marpa_Symbol_ID", "symbol_id"},
{"marpa_g_symbol_is_nulled_event", "Marpa_Symbol_ID", "sym_id"},
{"marpa_g_symbol_is_nulled_event_set", "Marpa_Symbol_ID", "sym_id", "int", "value"},
{"marpa_g_symbol_is_nulling", "Marpa_Symbol_ID", "symbol_id"},
{"marpa_g_symbol_is_prediction_event", "Marpa_Symbol_ID", "sym_id"},
{"marpa_g_symbol_is_prediction_event_set", "Marpa_Symbol_ID", "sym_id", "int", "value"},
{"marpa_g_symbol_is_productive", "Marpa_Symbol_ID", "symbol_id"},
{"marpa_g_symbol_is_start", "Marpa_Symbol_ID", "symbol_id"},
{"marpa_g_symbol_is_terminal", "Marpa_Symbol_ID", "symbol_id"},
{"marpa_g_symbol_is_terminal_set", "Marpa_Symbol_ID", "symbol_id", "int", "boolean"},
{"marpa_g_symbol_is_valued", "Marpa_Symbol_ID", "symbol_id"},
{"marpa_g_symbol_is_valued_set", "Marpa_Symbol_ID", "symbol_id", "int", "boolean"},
{"marpa_g_symbol_new"},
{"marpa_g_zwa_new", "int", "default_value"},
{"marpa_g_zwa_place", "Marpa_Assertion_ID", "zwaid", "Marpa_Rule_ID", "xrl_id", "int", "rhs_ix"},
{"marpa_r_completion_symbol_activate", "Marpa_Symbol_ID", "sym_id", "int", "reactivate"},
{"marpa_r_alternative", "Marpa_Symbol_ID", "token", "int", "value", "int", "length"}, -- See above,
{"marpa_r_current_earleme"},
{"marpa_r_earleme_complete"}, -- See note above,
{"marpa_r_earleme", "Marpa_Earley_Set_ID", "ordinal"},
{"marpa_r_earley_item_warning_threshold"},
{"marpa_r_earley_item_warning_threshold_set", "int", "too_many_earley_items"},
{"marpa_r_earley_set_value", "Marpa_Earley_Set_ID", "ordinal"},
{"marpa_r_expected_symbol_event_set", "Marpa_Symbol_ID", "xsyid", "int", "value"},
{"marpa_r_furthest_earleme"},
{"marpa_r_is_exhausted"},
{"marpa_r_latest_earley_set"},
{"marpa_r_latest_earley_set_value_set", "int", "value"},
{"marpa_r_nulled_symbol_activate", "Marpa_Symbol_ID", "sym_id", "int", "reactivate"},
{"marpa_r_prediction_symbol_activate", "Marpa_Symbol_ID", "sym_id", "int", "reactivate"},
{"marpa_r_progress_report_finish"},
{"marpa_r_progress_report_start", "Marpa_Earley_Set_ID", "ordinal"},
{"marpa_r_start_input"},
{"marpa_r_terminal_is_expected", "Marpa_Symbol_ID", "xsyid"},
{"marpa_r_zwa_default", "Marpa_Assertion_ID", "zwaid"},
{"marpa_r_zwa_default_set", "Marpa_Assertion_ID", "zwaid", "int", "default_value"},
{"marpa_b_ambiguity_metric"},
{"marpa_b_is_null"},
{"marpa_o_ambiguity_metric"},
{"marpa_o_high_rank_only_set", "int", "flag"},
{"marpa_o_high_rank_only"},
{"marpa_o_is_null"},
{"marpa_o_rank"},
{"marpa_t_next"},
{"marpa_t_parse_count"},
{"_marpa_t_size" },
{"_marpa_t_nook_or_node", "Marpa_Nook_ID", "nook_id" },
{"_marpa_t_nook_choice", "Marpa_Nook_ID", "nook_id" },
{"_marpa_t_nook_parent", "Marpa_Nook_ID", "nook_id" },
{"_marpa_t_nook_is_cause", "Marpa_Nook_ID", "nook_id" },
{"_marpa_t_nook_cause_is_ready", "Marpa_Nook_ID", "nook_id" },
{"_marpa_t_nook_is_predecessor", "Marpa_Nook_ID", "nook_id" },
{"_marpa_t_nook_predecessor_is_ready", "Marpa_Nook_ID", "nook_id" },
{"marpa_v_valued_force"},
{"marpa_v_rule_is_valued_set", "Marpa_Rule_ID", "symbol_id", "int", "value"},
{"marpa_v_symbol_is_valued_set", "Marpa_Symbol_ID", "symbol_id", "int", "value"},
{"_marpa_v_nook"},
{"_marpa_v_trace", "int", "flag"},
{"_marpa_g_ahm_count"},
{"_marpa_g_ahm_irl", "Marpa_AHM_ID", "item_id"},
{"_marpa_g_ahm_position", "Marpa_AHM_ID", "item_id"},
{"_marpa_g_ahm_postdot", "Marpa_AHM_ID", "item_id"},
{"_marpa_g_irl_count"},
{"_marpa_g_irl_is_virtual_rhs", "Marpa_IRL_ID", "irl_id"},
{"_marpa_g_irl_length", "Marpa_IRL_ID", "irl_id"},
{"_marpa_g_irl_lhs", "Marpa_IRL_ID", "irl_id"},
{"_marpa_g_irl_rank", "Marpa_IRL_ID", "irl_id"},
{"_marpa_g_irl_rhs", "Marpa_IRL_ID", "irl_id", "int", "ix"},
{"_marpa_g_irl_semantic_equivalent", "Marpa_IRL_ID", "irl_id"},
{"_marpa_g_nsy_count"},
{"_marpa_g_nsy_is_lhs", "Marpa_NSY_ID", "nsy_id"},
{"_marpa_g_nsy_is_nulling", "Marpa_NSY_ID", "nsy_id"},
{"_marpa_g_nsy_is_semantic", "Marpa_NSY_ID", "nsy_id"},
{"_marpa_g_nsy_is_start", "Marpa_NSY_ID", "nsy_id"},
{"_marpa_g_nsy_lhs_xrl", "Marpa_NSY_ID", "nsy_id"},
{"_marpa_g_nsy_rank", "Marpa_NSY_ID", "nsy_id"},
{"_marpa_g_nsy_xrl_offset", "Marpa_NSY_ID", "nsy_id"},
{"_marpa_g_real_symbol_count", "Marpa_IRL_ID", "irl_id"},
{"_marpa_g_rule_is_keep_separation", "Marpa_Rule_ID", "rule_id"},
{"_marpa_g_rule_is_used", "Marpa_Rule_ID", "rule_id"},
{"_marpa_g_source_xrl", "Marpa_IRL_ID", "irl_id"},
{"_marpa_g_source_xsy", "Marpa_NSY_ID", "nsy_id"},
{"_marpa_g_virtual_end", "Marpa_IRL_ID", "irl_id"},
{"_marpa_g_virtual_start", "Marpa_IRL_ID", "irl_id"},
{"_marpa_g_xsy_nsy", "Marpa_Symbol_ID", "symid"},
{"_marpa_g_xsy_nulling_nsy", "Marpa_Symbol_ID", "symid"},
{"_marpa_r_earley_item_origin"},
{"_marpa_r_earley_item_trace", "Marpa_Earley_Item_ID", "item_id"},
{"_marpa_r_earley_set_size", "Marpa_Earley_Set_ID", "set_id"},
{"_marpa_r_earley_set_trace", "Marpa_Earley_Set_ID", "set_id"},
{"_marpa_r_first_completion_link_trace"},
{"_marpa_r_first_leo_link_trace"},
{"_marpa_r_first_postdot_item_trace"},
{"_marpa_r_first_token_link_trace"},
{"_marpa_r_is_use_leo"},
{"_marpa_r_is_use_leo_set", "int", "value"},
{"_marpa_r_leo_base_origin"},
{"_marpa_r_leo_base_state"},
{"_marpa_r_leo_predecessor_symbol"},
{"_marpa_r_next_completion_link_trace"},
{"_marpa_r_next_leo_link_trace"},
{"_marpa_r_next_postdot_item_trace"},
{"_marpa_r_next_token_link_trace"},
{"_marpa_r_postdot_item_symbol"},
{"_marpa_r_postdot_symbol_trace", "Marpa_Symbol_ID", "symid"},
{"_marpa_r_source_leo_transition_symbol"},
{"_marpa_r_source_middle"},
{"_marpa_r_source_predecessor_state"},
-- {"_marpa_r_source_token", "int", "*value_p"},
{"_marpa_r_trace_earley_set"},
{"_marpa_b_and_node_cause", "Marpa_And_Node_ID", "ordinal"},
{"_marpa_b_and_node_count"},
{"_marpa_b_and_node_middle", "Marpa_And_Node_ID", "and_node_id"},
{"_marpa_b_and_node_parent", "Marpa_And_Node_ID", "and_node_id"},
{"_marpa_b_and_node_predecessor", "Marpa_And_Node_ID", "ordinal"},
{"_marpa_b_and_node_symbol", "Marpa_And_Node_ID", "and_node_id"},
{"_marpa_b_or_node_and_count", "Marpa_Or_Node_ID", "or_node_id"},
{"_marpa_b_or_node_first_and", "Marpa_Or_Node_ID", "ordinal"},
{"_marpa_b_or_node_irl", "Marpa_Or_Node_ID", "ordinal"},
{"_marpa_b_or_node_is_semantic", "Marpa_Or_Node_ID", "or_node_id"},
{"_marpa_b_or_node_is_whole", "Marpa_Or_Node_ID", "or_node_id"},
{"_marpa_b_or_node_last_and", "Marpa_Or_Node_ID", "ordinal"},
{"_marpa_b_or_node_origin", "Marpa_Or_Node_ID", "ordinal"},
{"_marpa_b_or_node_position", "Marpa_Or_Node_ID", "ordinal"},
{"_marpa_b_or_node_set", "Marpa_Or_Node_ID", "ordinal"},
{"_marpa_b_top_or_node"},
{"_marpa_o_and_order_get", "Marpa_Or_Node_ID", "or_node_id", "int", "ix"},
{"_marpa_o_or_node_and_node_count", "Marpa_Or_Node_ID", "or_node_id"},
{"_marpa_o_or_node_and_node_id_by_ix", "Marpa_Or_Node_ID", "or_node_id", "int", "ix"},
}
local result = {}
for ix = 1,#signatures do
result[#result+1] = wrap_libmarpa_method(signatures[ix])
end
return table.concat(result)
-- end of exec
]==]
-- miranda: section register standard libmarpa wrappers
--[==[ miranda: exec register standard libmarpa wrappers
local result = {}
for ix = 1, #signatures do
local signature = signatures[ix]
local function_name = signature[1]
local unprefixed_name = function_name:gsub("^[_]?marpa_", "", 1)
local class_letter = unprefixed_name:gsub("_.*$", "", 1)
local class_name = libmarpa_class_name[class_letter]
local class_table_name = 'class_' .. class_name
-- for example: marpa_lua_getfield(L, kollos_table_stack_ix, "class_grammar")
result[#result+1] = string.format(" marpa_lua_getfield(L, kollos_table_stack_ix, %q);\n", class_table_name)
local wrapper_name = "wrap_" .. unprefixed_name;
-- for example: marpa_lua_pushcfunction(L, wrap_g_highest_rule_id)
result[#result+1] = string.format(" marpa_lua_pushcfunction(L, %s);\n", wrapper_name)
local classless_name = function_name:gsub("^[_]?marpa_*_", "")
local initial_underscore = function_name:match('^_') and '_' or ''
local field_name = initial_underscore .. classless_name
-- for example: marpa_lua_setfield(L, -2, "highest_rule_id")
result[#result+1] = string.format(" marpa_lua_setfield(L, -2, %q);\n", field_name)
result[#result+1] = string.format(" marpa_lua_pop(L, 1);\n", field_name)
end
return table.concat(result)
]==]
-- miranda: section create kollos class tables
--[==[ miranda: exec create kollos class tables
local result = {}
for class_letter, class in pairs(libmarpa_class_name) do
local class_table_name = 'class_' .. class
local functions_to_register = class .. '_methods'
result[#result+1] = string.format(" marpa_luaL_newlib(L, %s);\n", functions_to_register)
result[#result+1] = " marpa_lua_pushvalue(L, -1);\n"
result[#result+1] = ' marpa_lua_setfield(L, -2, "__index");\n'
result[#result+1] = string.format(" marpa_lua_setfield(L, kollos_table_stack_ix, %q);\n", class_table_name);
end
return table.concat(result)
]==]
05803539f778f51a5797abee9a2381f3
The standard constructors are generated indirectly, from a template.
This saves a lot of repetition, which makes for easier reading in the
long run.
In the short run, however, you may want first to look at the bocage
constructor.
It is specified directly, which can be easier for a first reading.
-- miranda: section object constructors
--[==[ miranda: exec object constructors
local result = {}
local template = [[
|static int
|wrap_!NAME!_new (lua_State * L)
|{
| const int !BASE_NAME!_stack_ix = 1;
| int !NAME!_stack_ix;
|
| if (0)
| printf ("%s %s %d\n", __PRETTY_FUNCTION__, __FILE__, __LINE__);
| if (1)
| {
| marpa_luaL_checktype(L, !BASE_NAME!_stack_ix, LUA_TTABLE);
| }
|
| marpa_lua_newtable(L);
| /* [ base_table, class_table ] */
| !NAME!_stack_ix = marpa_lua_gettop(L);
| marpa_lua_getglobal (L, "kollos");
| marpa_lua_getfield (L, -1, "class_!NAME!");
| marpa_lua_setmetatable (L, !NAME!_stack_ix);
| /* [ base_table, class_table ] */
|
| {
| !BASE_TYPE! *!BASE_NAME!_ud;
|
| !TYPE! *!NAME!_ud =
| (!TYPE! *) marpa_lua_newuserdata (L, sizeof (!TYPE!));
| /* [ base_table, class_table, class_ud ] */
| marpa_lua_rawgetp (L, LUA_REGISTRYINDEX, &kollos_!LETTER!_ud_mt_key);
| /* [ class_table, class_ud, class_ud_mt ] */
| marpa_lua_setmetatable (L, -2);
| /* [ class_table, class_ud ] */
|
| marpa_lua_setfield (L, !NAME!_stack_ix, "_libmarpa");
| marpa_lua_getfield (L, !BASE_NAME!_stack_ix, "_libmarpa_g");
| marpa_lua_setfield (L, !NAME!_stack_ix, "_libmarpa_g");
| marpa_lua_getfield (L, !BASE_NAME!_stack_ix, "_libmarpa");
| !BASE_NAME!_ud = (!BASE_TYPE! *) marpa_lua_touserdata (L, -1);
|
| *!NAME!_ud = marpa_!LETTER!_new (*!BASE_NAME!_ud);
| if (!*!NAME!_ud)
| {
| return libmarpa_error_handle (L, !NAME!_stack_ix, "marpa_!LETTER!_new()");
| }
| }
|
| if (0)
| printf ("%s %s %d\n", __PRETTY_FUNCTION__, __FILE__, __LINE__);
| marpa_lua_settop(L, !NAME!_stack_ix );
| /* [ base_table, class_table ] */
| return 1;
|}
]]
for class_ix = 1, (#libmarpa_class_sequence - 1) do
local class_letter = libmarpa_class_sequence[class_ix+1]
-- bocage constructor is special case
if class_letter == 'b' then goto NEXT_CLASS end
local class_name = libmarpa_class_name[class_letter]
local class_type = libmarpa_class_type[class_letter]
local base_class_letter = libmarpa_class_sequence[class_ix]
local base_class_name = libmarpa_class_name[base_class_letter]
local base_class_type = libmarpa_class_type[base_class_letter]
local this_piece =
pipe_dedent(template)
:gsub("!BASE_NAME!", base_class_name)
:gsub("!BASE_TYPE!", base_class_type)
:gsub("!BASE_LETTER!", base_class_letter)
:gsub("!NAME!", class_name)
:gsub("!TYPE!", class_type)
:gsub("!LETTER!", class_letter)
result[#result+1] = this_piece
::NEXT_CLASS::
end
return table.concat(result, "\n")
]==]
The bocage constructor takes an extra argument, so it's a special
case.
It's close to the standard constructor.
The standard constructors are generated indirectly, from a template.
The template saves repetition, but is harder on a first reading.
This bocage constructor is specified directly,
so you may find it easer to read it first.
696b99945883b9971354315357ca2369
```
The grammar constructor is a special case, because its argument is
a special "configuration" argument.
3413eeffa76ac9455e11d6f5a646fb9e
```
93c0c75a51511e500c0dae6c0c61b967
```
-- miranda: section main
-- miranda: insert legal preliminaries
-- miranda: insert luacheck declarations
-- miranda: insert enforce strict globals
-- miranda: insert VM operations
-- miranda: insert value_init()
-- miranda: insert valuation_reset()
-- miranda: insert diagnostics
-- miranda: insert Utilities for Perl code
1d4f7117746e39d7c6b8c5915a3e863b
```
aa24849b8a6c63acc96f8d05194f8699
Licensing, etc.
```
d330c928d8c9e4928e85c0b149b0a9a8
```
Luacheck declarations
```
b81c2f9eff64cac7580cbf7785a12c96
```
Set "strict" globals, using code taken from strict.lua.
```
77862327ef6c36b005fc7f61e69c0038
```
15a93b4b782f10f5b74aeaad0262d95d
```
-- miranda: section kollos_c
-- miranda: language c
-- miranda: insert preliminaries to the c library code
-- miranda: insert private error code declarations
-- miranda: insert define error codes
-- miranda: insert private event code declarations
-- miranda: insert define event codes
-- miranda: insert private step code declarations
-- miranda: insert define step codes
489d7af1fa46139c550a73c8f5841f88
```
2c97d996aac9a81338200d283c9c5ed9
```
852faf79d5428272f0ca848eb020ea4a
`dummyup_grammar` is not Lua C API.
This may be the basis of the actual constructor.
Takes ownership of a Libmarpa grammar reference,
so the caller must make sure that one is available.
fadf73388c7f2ffc61facf7c2642d7c4
`lca_grammar_rule_new` wraps the Libmarpa method `marpa_g_rule_new()`.
If the rule is 7 symbols or fewer, I put it on the stack. As an old
kernel driver programmer, I was trained to avoid putting even small
arrays on the stack, but one of this size should be safe on anything
like close to a modern architecture.
Perhaps I will eventually limit Libmarpa's
rule RHS to 7 symbols, 7 because I can encode dot position in 3 bit.
fcee9ea8d686a3f22de960fd1f240f8b
`lca_grammar_sequence_new` wraps the Libmarpa method `marpa_g_sequence_new()`.
If the rule is 7 symbols or fewer, I put it on the stack. As an old
kernel driver programmer, I was trained to avoid putting even small
arrays on the stack, but one of this size should be safe on anything
like close to a modern architecture.
Perhaps I will eventually limit Libmarpa's
rule RHS to 7 symbols, 7 because I can encode dot position in 3 bit.
e2f782eb1bb5589b535333df5537102a
```
e7ce018cd89a2db0dc4f39d0f359d06e
```
-- miranda: section define marpa_luaopen_kollos method
static int marpa_luaopen_kollos(lua_State *L)
{
/* Create the main kollos object */
const int kollos_table_stack_ix = marpa_lua_gettop(L) + 1;
2a6626558b179ebdad868ca2fde485c5
```
16cba468890abcd47d29061aeec334e5
Given a Lua state,
create a table, which can be used
as a "sandbox" for protect the global environment
from user code.
The table is named `sandbox` and itself *is*
kept in the global environment.
This code only creates the sandbox, it does not
set it as an environment -- it is assumed that
that will be done later,
after to-be-sandboxed Lua code is loaded,
but before it is executed.
Not Lua-callable, but leaves the stack as before.
```
-- miranda: section create sandbox table
{
const int base_of_stack = marpa_lua_gettop(L);
marpa_lua_newtable (L);
/* sandbox.__index = _G */
marpa_lua_pushglobaltable(L);
marpa_lua_setfield(L, -2, "__index");
4b591ba429f741af6923045aeec1867a
```
b6a8e743190e3cf38308b3e90f52b6c8
```
-- miranda: section preliminaries to the c library code
/*
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
** [ MIT license: http://www.opensource.org/licenses/mit-license.php ]
*/
bd950df5e94c26ae1756ced394737fc4
```
b2f928f420e95c15fbf6fdb822fc81cc
```
-- miranda: section kollos_h
-- miranda: language c
-- miranda: insert preliminary comments of the c header file
63307eac5875bc8ac69a0b2da5e32644
```
e6637690337bd22bf481dd86522a6199
```
-- miranda: section preliminary comments of the c header file
15bec93404073dd1e5ce3a24f9ac1ebd
```
afb8dc824e40eceee466a48c546d8150
a4bbb4894824af0a448684b010503cfd
```
-- miranda: sequence-exec argument processing
-- miranda: sequence-exec metacode utilities
-- miranda: sequence-exec libmarpa interface globals
-- miranda: sequence-exec declare standard libmarpa wrappers
-- miranda: sequence-exec register standard libmarpa wrappers
-- miranda: sequence-exec create kollos class tables
-- miranda: sequence-exec object userdata gc methods
```
96ba0007a41bc64e7333f4d2864d0998
A pipe symbol is used when inlining code to separate the code's indentation
from the indentation used to display the code in this document.
The `pipe_dedent` method removes the display indentation.
```
--[==[ miranda: exec metacode utilities
function pipe_dedent(code)
return code:gsub('\n *|', '\n'):gsub('^ *|', '', 1)
end
]==]
```
c7a29b68db380940ce1706b6a063c975
```
--[==[ miranda: exec metacode utilities
local function c_safe_string (s)
s = string.gsub(s, '"', '\\034')
s = string.gsub(s, '\\', '\\092')
return '"' .. s .. '"'
end
]==]
```
6a09f6e14230a185214506388e39c699
The arguments show where to find the files containing event
and error codes.
```
-- assumes that, when called, out_file to set to output file
--[==[ miranda: exec argument processing
local error_file
local event_file
d20aee9d3482a5dcae0c0a8e232d8e3c
```