#!/usr/bin/perl -w

# gesc - Expert System Compiler for graduates (CISC 670 students)

# 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(<IN>) {
  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 <iostream>\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 {
  if (@rule_set) {
    process_rule_set(@rule_set);
    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;
  
  # accumulate the rules for one function

  push(@rule_set,"$fun_val $fun_test");}

  #print FUNS '  if (';
  
  #my($n) = 0;
  #while ($fun_test) {
    #if ($n > 0) {print FUNS " && ";}
    #$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";}

sub process_rule_set {
  my(@rule_set) = $_[0];
  }
