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


In reply to Re: Parsing SExpressions (lisp) by LanX
in thread Parsing SExpressions (lisp) by Dwood

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.