Программист-прагматик. Путь от подмастерья к мастеру
Шрифт:
Ответ: Ответ к данному упражнению составлен на языке Perl.
my @consts;
my $name = <>;
die "Invalid format – missing name" unless defined($name);
chomp $name;
# Read in the rest of the file
while (<>) {
chomp;
s/"\s*//; s/\s*$//;
die "Invalid line: $_" unless /"(\w+)$/;
push @consts, $_;
}
# Now generate the file
open(HDR, ">$name.h") or die "Can't open $name.h: $!";
open(SRC, ">$name.c") or die "Can't open $name.c: $!";
my $uc_name = uc($name);
print HDR "/* File generated automatically – do not edit */\n";
print HDR "extern const char *$ {ucjiame)_name[];";
print HDR "typedef enum {\n"; print HDR join",\n", @consts;
print HDR "\n) $uc_name;\n\n";
print SRC "* File generated automatically – do not edit */\n";
print SRC "const char *$ {uc name}_name[] = {\n \"";
print SRC join "\",\n \"", @consts;
print SRC "\"\n};\n";
close(SRC);
close(HDR);
Используя
etest.c etest.h: etest.inc enumerated.pl
perl enumerated.pl etest.inc
Ответ: Вот ответ, написанный на языке Perl.
my $dir = shift or die "Missing directory" ,
for my Sfile (glob(u$dir/*.pr)) {
open(IP, "$file") or die "Opening $file: $!";
undef $/; # Turn off input record separator -
my Scontent = <IP>; # read whole file as one string.
close(IP);
if (Scontent Гrusestrict/m) {
rename Sfile, "$file.bak" or die "Renaming $file: $!"; open(OP, ">$file") or die "Creating $file: $!";
# Put 'use strict' on first line that
# doesn't start #
Scontent =" sr(V.#)/\nuse strict;\n\n/m',
print OP Scontent; close(OP);
print "Updated $file\n";
)
else {
print "Sfile already strict\n":
)
}
Ответ: Решение реализовано
my lang = shift or die "Missing language";
$lang .= "_cg.pm";
require <$lang> or die "Couldn't load $lang";
# Read and parse the file
my $name;
while (<>) {
chomp;
if (/^ \s*$/) {CG::blankLine;)
elsif ((/^ \#(.*)/) {CG::comment($1);}
elsif ((/^M\s*(.+)/) {CG::startMsg($1); $name = $1;}
elsif ((/^E/) {CG::endMsg($name);}
elsif (/^F\s*(\w+)\s+(\w+)$/) {CG::simpleType($1,$2);}
elsif (/^F\s*(\w+)\s+(\w+)\[(\d+)\]$/) {CG::arrayType $1,$2,$3);}
else {
die "Invalid line: $ ";
}
}
Написание языковой серверной части не составит труда: создайте модуль, который реализует шесть точек входа. Вот генератор текста на языке С:
#!/usr/bin/perl – w
package CG;
use strict;
# Code generator for 'C' (see cg_base.pl)
sub blankLine {print "\n"; }
sub comment {print "/*$_[0] */\n"; }
sub startMsg {print "typedef struct {\n"; }
sub endMsg {print "} $_[0];\n\n"; }
sub arrayType {
my ($name, $type, $size) = @_;
print " $type $name\[$size];\n":
}
sub simpleType{) {
my ($name, $type) = @_;
print " $type $пате;\п";
}
1;
А вот генератор текста на языке Pascal:
#!/usr/bin/perl – w
package CG;
use strict;
# Code generator for 'Pascal' (see cg_base.pl)
sub blankLine {print "V;)
sub comment {print "{$_[0] }\n";)
sub startMsg {print "$_[0] = packed record\n"; }
sub endMsg {print "end;\n\n"; }
sub arrayType {
my ($name, $type, $size) = @_;
$size--;
print" $name: array[0…$size] of $type;\n";
)
sub simpleType {
my ($name, $type) = @_;
print" $name: $type;\n7 ',
}
1;