[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: introducing luaSuper
- From: Asko Kauppi <askok@...>
- Date: Fri, 2 Nov 2007 23:15:40 +0200
The work on luaSuper is approaching release, and I would like to
share some of it here, although "code complete" stage is still a few
days away, hopefully no more.
The concept is making 'luas' command a syntax modifiable version of
the 'lua' interpreter. This is how it goes:
luas -s select demo.lua # loads demo.lua with syntax mods from
'luas_select.so'
or, one can make demo.lua load the syntax mods automatically, by
having the following shebang line:
#!/.../luas -s select
Some differentiation of luaSuper to regular token filtering, and
MetaLua:
- made in C++ (about 2500 lines, 4 .cpp files)
- parsing speed should be similar to regular Lua parser, _even_ when
the syntax is modified
- multiple syntax mods are usable
- different source files can use each their own set of syntax mods
Performance and ease of making syntax modifications have been the
design goals. As a sample, below is what it takes to make a "select"
syntax mod, build by:
g++ -bundle luas_select.cpp -o luas_select.so
I will hopefully get the code ready during next week. It'd be
motivating to get some feedback, ideas, questions already now.
-asko
/*
* SELECT token filter Copyright 2006-07 Asko Kauppi
*
* Simplifies the 'select' usage a bit, making it look less like a
function
*
* #... -> select('#',...) = number of values in ...
* ...[n] -> (select(n,...)) = value #n of ...
*
* 'select(n,...)' is still used explicitly when wanting all values
from 'n' onwards.
*
* License: MIT/Lua5 (see LICENSE)
*/
#include "plugin.hpp"
/*
* Called by luaSuper parser, for "#..."
*/
static bool CATCH1( PluginParser& p )
{
p.replace( 0,2, "select", "(", "\"#\"", ",", "...", ")" );
return true;
}
/*
* Called by luaSuper parser, for "...[exp]"
*/
static bool CATCH2( PluginParser& p )
{
p.replace( 0,2, "(", "select", "(" );
p.replace( -1,1, ",", "...", ")", ")" );
return true;
}
/*
* Override normal syntax:
*
* ["exp"]= { opt(unop),
* alt{ "nil", "false", "true", "<number>", "<string>",
"...",
* { "{", opt(fieldlist), "}" },
* { "function", funcbody },
* prefixexp },
* opt( binop, exp ) }
* -->
* ["exp"]= { opt( ent( opt(unop),
* alt{ { "#", "..." },
* { "...", opt{ "[", exp,
"]" } },
* opt(binop,exp) ),
* original }
*
* Note: Not repeating the original syntax makes us play nice with
potential
* other plugins. We would otherwise let the original path be
considered
* first, but "..." within it would make a match, avoiding "...
[exp]"
* extension to work. Alas, we need to be first.
*
* Other plugins may further extend the 'exp' syntax, appending
* or prepending their modifications, without troubling us or the
* original syntax (unless, of course, the syntaxes themselves
do clash).
*/
void syntax_select( PluginSyntax& syntax ) {
// Note: use 'syntax["exp"]' to get the _current_ syntax, using
'ref()'
// would make a loop! However, for "...[exp]" we can use
'ref()'
// since it's within an 'alt' case. Ref allows our syntax
to be
// recursively applied, and further changes to 'exp' to
apply also
// within our syntax.
const EntBase *unop= ref("unop");
const EntBase *binop= ref("binop");
const EntBase *exp= ref("exp");
syntax["exp"]= opt( ent( opt(unop),
alt( "#", ent( "...", CATCH1 ),
"...", ent( "[", exp, "]",
CATCH2 ) ),
opt(binop,exp)
),
syntax["exp"] // earlier exp ('ref' would
make a loop!)
);
}