#!/usr/bin/perl # Compiler of The Graphomaton to Pascal # (c) 2006 Martin Mares use strict; use warnings; my $var_decl = 0; my %vars = ( "vv" => undef, "s" => undef, "p" => undef ); my $h = <>; my ($deg) = $h =~ /^#deg\s+(\d+)\s*$/ or die "Missing #deg"; print "program graphomaton;\n"; while (<>) { s/{[^{}]*}//g; /[{}]/ && die "Multi-line comments not supported"; /^\s*$/ && next; if (/^var\s+/) { print "const\tdeg = $deg;\n"; print "type\tpvertex = ^vertex;\n"; print "\tvertex = record\n"; print "\t\ts: array [1..deg] of pvertex;\n"; print "\t\tp: array [1..deg] of 1..deg;\n"; print "\t\tstop: boolean;\n"; s/^var//; $var_decl = 1; } if (/^begin/) { $var_decl || die "No variables declared"; $var_decl = 0; print "\tend;\n\n"; print "procedure init(vv: pvertex);\nbegin\n"; print "\twith vv^ do begin\n"; foreach my $v (sort keys %vars) { print "\t\t$v := $vars{$v};\n" if defined $vars{$v}; } print "\tend;\n"; print "end;\n\n"; print "procedure dump(vv: pvertex);\nbegin\n"; print "\twith vv^ do begin\n"; foreach my $v (sort keys %vars) { if (defined $vars{$v}) { print "\t\twrite(' $v=', $v);\n"; } } print "\tend;\n"; print "end;\n\n"; print "procedure run(vv: pvertex);\nbegin\nwith vv^ do begin\n"; print "\tstop := false;\n"; next; } elsif (/^end\./) { print "end;\nend;\n"; next; } elsif (/^\w/) { die "Unknown top-level construct"; } if ($var_decl) { my ($vars, $type, $init) = /^\s+(.*):([^=]+)(=.*)?;\s*$/ or die "Incomprehensible declaration: $_"; if (defined $init) { $init =~ /^=\s*(\d+)\s*$/ or die "Nasty initializer: $init"; $init = $1; } $type =~ s/^\s+//; $type =~ s/\s+$//; $type =~ /^\d+\.\.\d+$/ or die "Barbaric type: $type"; foreach my $v (split(/,/, $vars)) { $v =~ s/^\s+//; $v =~ s/\s+$//; $v =~ tr/A-Z/a-z/; !exists $vars{$v} or die "Duplicate variable: $v"; $vars{$v} = $init; if ($v eq "x") { defined($init) && die "Input must not have an explicit initializer"; } elsif (!defined $init) { $init = 0; } # Defaulting initializer to 0 print "\t\t$v: $type;"; print " { = $init }" if defined $init; print "\n"; } } else { sub maybevar($) { my $v = shift @_; $v =~ tr/A-Z/a-z/; return $v; } s/(\w+)/maybevar($1)/ge; s/]\./]^./g; s/\bstop\b/stop := true/g; print; } } print "\n"; open RT, "runtime" or die "Cannot open runtime"; while () { print; } close RT;