lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]



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!)
);
}