#!/usr/bin/perl -w # esc - Expert System Compiler # read in the rule statements from the specification file and sort them if ($ARGV[0]) {$spec_file = $ARGV[0];} else {die 'no input file';} if ($spec_file !~ m/^.+\.idt/) {die 'not a specification (.idt) file';} open(IN,"<$spec_file"); while() { chomp($_); push(@spec,$_);} close IN; @spec = sort(@spec); # open the four intermediate files into which C++ code will be written open(ASK,'>_askdefs.cc'); open(PROTOS,'>_prototypes.cc'); open(FUNS,'>_functions.cc'); open(MAIN,'>_main.cc'); #initialize ASK file print ASK "\#include \n"; print ASK "using namespace std;\n"; # main loop; process each line of the specification $n = @spec; # number of lines in the specification $current_fun_name = ' '; for ($i = 0; $i < $n; $i++) { @x = split(/ /,$spec[$i],3); if ($x[0] eq 'ask') {process_ask($x[1],$x[2]);} elsif ($x[0] eq 'goal') {process_goal($x[1],$x[2]);} else {process_rule($x[0],$x[1],$x[2]);}} # finish off the last function if the FUNS file finish_fun(); # now make the final program and compile it close ASK; close PROTOS; close FUNS; close MAIN; $n = length($spec_file); $program_name = substr($spec_file,0,$n - 4); $program_name1 = "$program_name.cc"; system "cat _askdefs.cc _prototypes.cc _functions.cc _main.cc > $program_name1"; system "g++ $program_name1 -o $program_name.out"; sub process_ask { my($ask_fun_name) = $_[0]; my($prompt) = $_[1]; print ASK "\n"; print ASK "char * $ask_fun_name() {\n"; print ASK " static char result[10] = \"undecided\";\n"; print ASK " if (strcmp(result,\"undecided\")==0) \{\n"; print ASK " cout << \"$prompt\" ;\n"; print ASK " cin >> result;}\n"; print ASK " return result;}\n";} sub process_goal { my($main_fun_name) = $_[0]; my($response) = $_[1]; print MAIN "int main() {\n"; print MAIN " char * diagnosis;\n"; print MAIN " diagnosis = $main_fun_name();\n"; print MAIN " cout << \"$response\" << \" \" << diagnosis << endl;}\n";} sub process_rule { my($fun_name) = $_[0]; my($fun_val) = $_[1]; my($fun_test) = $_[2]; if ($current_fun_name ne $fun_name) { # first time fun_name is seen if ($current_fun_name ne ' ') { # finish previous definition finish_fun();} $current_fun_name = $fun_name; print PROTOS "char* $fun_name();\n"; print FUNS "char * $fun_name() {\n"; print FUNS " static char * result = \"undecided\";\n"; print FUNS " if (strcmp(result,\"undecided\")!=0) return result;\n";} process_one_branch($fun_val,$fun_test);} sub finish_fun { print FUNS " result = \"unknown\";\n"; print FUNS " return result;}\n";} sub process_one_branch { my($fun_val) = $_[0]; my($fun_test) = $_[1]; # get rid of 'if ' and ' and ' to simplify the condition list $fun_test =~ s/if //; $fun_test =~ s/ and / /g; print FUNS ' if ('; my($n) = 0; while ($fun_test) { if ($n > 0) {print FUNS " &&\n";} $n++; my(@x) = split(/ /,$fun_test,3); print FUNS " strcmp($x[0](),\"$x[1]\")==0"; $fun_test = $x[2];} print FUNS " ) {\n"; print FUNS " result = \"$x[1]\";\n"; print FUNS " return result;}\n";}