in reply to Parsing SExpressions (lisp)

As I said yesterday at the CB I would rather use regexes to transform an S-expr into a Perl M-expr and eval it. Like that delegating most of the parsing to Perl's interpreter.

You need to know that LISP syntax treats command code and data code equally as lists!

So it's very likely that you'll need to "execute" the code sooner or later, just static parsing is not enough.

As an example, these brute force regexes ...

my $data=do {local $/;<DATA>}; $data=~s/\(\s*(\w+)(\W)/$1\($2/gs; # s-expr -> m-expr functions $data=~s/\)(?=[\s\w]+)/),/g; # comma after functions $data=~s/\s([\w"\\]+)(?=[\s)])/$1,/g; # comma separated args print $data;
__DATA__ (global short rounds_completed 0) (script static unit player (unit (list_get (players) 0))) (script static void music_ambercladremix (sound_looping_start "sound\moooseguy\sound_looping\ambercladremix" none 1) ) (script dormant death_cutscene (enable_hud_help_flash false) (show_hud_help_text false) (sleep 30) (camera_set death7 100) (sleep 50) (camera_set death8 110) (cinematic_set_title gameover) (sleep 150) (fade_out 0 0 0 30) (sleep 50) (cinematic_stop) (wake credits_cutscene) )

prints

global(short,rounds_completed,0,), script(static,unit,player, unit( list_get( players(),0,))), script(static,void,music_ambercladremix, sound_looping_start( "sound\moooseguy\sound_looping\ambercladremix", none,1,), ), script(dormant,death_cutscene, enable_hud_help_flash(false,), show_hud_help_text(false,), sleep(30,), camera_set(death7,100,), sleep(50,), camera_set(death8,110,), cinematic_set_title(gameover,), sleep(150,), fade_out(0,0,0,30,), sleep(50,), cinematic_stop(), wake(credits_cutscene,), ),

Now simply defining these routines as perl subs in a dedicated package should be sufficient to eval the code, much like a DSL (domain specific language).

Be aware that additional leading underscores _ and \U for uppercasing in the substitution would avoid any possible conflicts with Perl's built-in function names.

And you should read the perldocs for AUTOLOAD about catching and treating undefined function names. Barewords in LISP are much like in Perl internally just functions.

UPDATE
I think I was wrong about the latter, Perl wouldn't always catch barewords like death7 in AUTOLOAD, so better append () or prepend & to make it clear.
&death7; death6(); sub AUTOLOAD { print "undefined sub $AUTOLOAD was called\n"; }

Cheers Rolf