jonadab has asked for the wisdom of the Perl Monks concerning the following question:
I'm working on a simple bilingual program (code below), and I'm looking for tips and pointers primarily in terms of how to better work with the other language's syntax. I can easily hide each language's code from the other, since Inform uses a different comment char (!) than Perl, but that really isn't good enough. What I have right now is enough (if I'm careful about the order I declare things in, and leave out the optional hardware short names and parents on the object headers) to let Perl print on startup the same things the Inform program would, but the minute I want to add an additional object that comes into play later (after the user types something), I'm stuck. I really need a way to declare objects in Inform syntax and have Perl store the strings away, tied somehow to the name of the object. At this point, maybe I should put in the code I have, so you can get an idea of the sort of syntax I need to deal with...
#ifdef Perl; " "; !"; sub Constant ($) {}; sub Headline ($) { $x=$_[0]; $x =~ s/\^/\n +/g; print $x; } sub Story ($) { print $_[0]; } #" #endif; Constant Story "Obfuscated Perl Competition"; Constant Headline "^An interactive adventure in source-code obscurity. +^"; #Include "Parser"; Constant Code "Just Another Inform Hacker ";!"; sub with (@) { return @_; } "who really !"; sub Object (@) { } "ought to !"; sub EmptyRoom {} sub Desk {} "know better !"; sub initial { print "\n$_[0]\n> "; } "than this. !"; sub description { print "\n$_[1]\n$_[0]\n"; } " !"; sub short_name {} sub has($) {}; Object EmptyRoom with description "The walls are white.", short_name "EMPTY ROOM", has light; Object Desk EmptyRoom with initial "This is the desk where you are supposed to be working on you +r entry for the Obfuscated Perl Competition. But your mind keeps slipping back to that text adventure you were working on before...", short_name "Desk", has static; #Include "VerbLib"; [ Initialise; location = EmptyRoom; ]; global win +msg "You write an entry that compiles in both Perl and Inform. ";!"; #Include "Grammar"; [ FinishSub; deadflag=2; print_ret winmsg, " "; ]; Verb 'write' 'entry' -> Finish; Verb 'win' -> Finish; Verb 'finish' -> Finish; end; "; $debug=0; push @grammar, [['quit'], 'Quit']; push @grammar, [['write', 'entry'], 'Finish']; push @grammar, [['win'], 'Finish']; # I could do more, but I do not have the gumption to reproduce # the entire Inform standard library grammar here. Besides, # my parser can't handle most of it, and the Perl object model # is not up to the more advanced stuff. (Inform is very OO.) %verb = ( Quit => sub { exit 0; }, Finish => sub { print "You write an entry that compiles in both Perl and Inform.\ +n\n *** You Have Won ***\n\n"; exit 0; }, # I don't have the gumption to reproduce the entire Inform verb lib +rary here, either. ); sub gramerr { my ($tok,$gram) = @_; if ($tok>$besterr) { $besterr=$tok; $bestgram=$gram; } } while (<STDIN>) { @token=split/\s+/,$_; $besterr=0; foreach $g (@grammar) { last if ($besterr==999); if ($debug>1) { print "Considering grammar line: @$g: "; } @gramline = @$g; $gramtoken= @{gramline[0]}; $gramverb = @gramline[1]; $mismatch=0; $t=0; while ($t<scalar @$gramtoken and $mismatch==0 and $besterr<999) { if ($debug>2) { print " [token $t: $token[$t] vs $$gramtoken[$ +t]]"; } if ((not defined $token[$t]) or ($token[$t] !~ $$gramtoken[$t])) + { gramerr($t+1, $g); $mismatch++; if ($debug>2) {print "mismatch\n" +;}} if (not $mismatch) { if ($debug>2) { print "matches so far\n";} if ($t+1==scalar@$gramtoken) { $bestgram=$g; $besterr=999; if ($debug>2) { print "matches fully\n"; }}} $t++; }} if ($besterr==999) { $g=$bestgram; @gramline = @$g; $gramtoken= @{gramline[0]}; $gramverb = @gramline[1]; if ($debug) { print "Calling routine for $gramverb\n"; } &{$verb{$gramverb}}; } else { # This is horrifically weak, but this is an exercise in # merging two computer languages, not in natural language # parsing, and anyway I'm not a genius like Graham Nelson. if ($besterr<2) { print "What do you mean by $token[0]"; } else { print "What do you want to"; $g=$bestgram; @gramline = @$g; $gramtoken= @{gramline[0]}; $gramverb = @gramline[1]; foreach (0..($besterr-1)) { print " " . $token[$_]; } } print "?\n> "; } }
So, how can I better deal with syntax like that? Is there something more advanced I can do with templates, that will let me capture the bits that follow and create a nested hash structure, something like $obj{objectname}{propertyname}=$propertyvalue ? Each object can have numerous properties, but if I can just store the short_name and description that will be a good start.
I think all I need is a shove in the right direction. Pointers? Advice? Comments?
sub H{$_=shift;while($_){$c=0;while(s/^2//){$c++;}s/^4//;$ v.=(' ','|','_',"\n",'\\','/')[$c]}$v}sub A{$_=shift;while ($_){$d=hex chop;for(1..4){$pl.=($d%2)?4:2;$d>>=1}}$pl}$H= "16f6da116f6db14b4b0906c4f324";print H(A($H)) # -- jonadab
|
---|
Replies are listed 'Best First'. | |
---|---|
Re: Pointers on working with another language's syntax
by CountZero (Bishop) on Feb 17, 2003 at 19:58 UTC | |
by Koschei (Monk) on Feb 18, 2003 at 10:56 UTC | |
by jonadab (Parson) on Feb 18, 2003 at 13:30 UTC | |
by tall_man (Parson) on Feb 18, 2003 at 15:45 UTC | |
by jonadab (Parson) on Feb 18, 2003 at 13:15 UTC | |
Re: Pointers on working with another language's syntax
by jonadab (Parson) on Feb 17, 2003 at 14:19 UTC |