#!/usr/local/bin/perl -w
#
# TMTool: convert a spec for a Turing machine various forms.
#
# Peter Gammie - December, 1998 - peteg@unsw.edu.au
# (C) 1998 purely for the purposes of GPL'ing it.
#
use strict;
use TMParse;

# Constants
my $halt = 1;
my ($moveNONE, $moveLEFT, $moveRIGHT) = (0 .. 2);

MAIN: {
  my($filename, $template);

  if($#ARGV > 0) {
    $template = shift(@ARGV);
    die "can't open $template." if(!(-r $template));
  } else {
    die "Usage $0 template filename\n";
  }

  while($#ARGV > -1) {
    $filename = shift(@ARGV);
    die "can't open $filename." if(!(-r $filename));

    my $parser = TMParse->new(FileHandle->new($filename, "r"));
    $parser->run();

    printHTML($parser, $filename, $template);
#    printTape($filename);
#    printPost($filename);
  }
}

sub toUNARY {
  my $number = shift(@_);
  my $output = "";

  for(; $number > 0; $number--) {
    $output .= "0";
  }
  return $output;
}

#######################################################################

# Generate an HTML version of the file
sub printHTML {
  my $parser = shift(@_);
  my $filename = shift(@_);
  my $template = shift(@_);
  my $text = "";

  open(FHTML, ">$filename" . ".html") or die "can't open $filename" . ".html: $!";
  open(FTEMPLATE, "<$template") or die "can't open $template: $!";
  print "printHTML: generating output...";

  $parser->genHTML();

  while(<FTEMPLATE>) {
    while(/<<\$(.+?)>>/) {
#print STDERR $1. " -> " . $vars{$1} . "\n";     
      my $t = $parser->{METADATA}->{$1};
      if(defined($t) && $t ne "") {
	s/<<\$$1>>/$t/e;
      } else {
        $_ = "";
      }
    }
    $text .= $_;
  }

  print FHTML $text;
  close(FHTML);
  close(FTEMPLATE);
  print "done\n";
}

__DATA__

#######################################################################

# Print out a post system equivalent to this Turing machine
# Construction ripped from  Minsky, "Computation: Finite and Infinite Machines"
#  Canonical Systems for Representation of Turing Machines, p232
# (hopefully with extensions for multiple tapes)
sub printPost {
  my $filename = shift(@_);

  # Only works for single tape machines
  if($vars{"numTapes"} > 1) {
    print "printPost only operates on machines with a single tape. (skipping)\n";
    return;
  }

  open(FPOST, ">$filename" . ".post") or die "can't open $filename" . ".post: $!";
  print "printPost: generating output...";

  print FPOST "# Post system for $filename\n\n";
  print FPOST "sigma = \".*\"\n\n";

  # The tape string is the axiom
  print FPOST "# Tape string\n\"" . num2sym(0) . "<" . num2name(0) . ">" . (defined($vars{"tapeString"}->[1]) ? $vars{"tapeString"}->[1] : "") . num2sym(0) . "\"\n\n";

  # Generate state productions
  for(my $stateCount = 0; $stateCount < $numStates; $stateCount++) {
    if(vec($stateDefined, $stateCount, 1)) {
      # Add in some generic "extend tape" productions
      my $st = num2name($stateCount);
      print FPOST "# Tape extension stuff\n";
      print FPOST "\"(.*)<$st>\" -> \"\${1}<$st>" . num2sym(0) . "\"\n";
      print FPOST "\"<$st>(.*)\" -> \"" . num2sym(0) . "<$st>\${1}\"\n\n";

#      print num2name($stateCount) . " defined(" . vec($stateDefined, $stateCount, 1) . ")\n";
      for(my $symCount = 0; $symCount < length($vars{'alphabet'}); $symCount++) {
#	print "blah : $stateCount (". num2name($stateCount) . ") ; $numStates\n";

	if(defined($states[$stateCount][1][$symCount])) {
	  print FPOST postPrintState($states[$stateCount][1][$symCount]);
#	  print num2name($stateCount) . " '" . num2sym($symCount) . "' (real)\n";
#	  print FTAPE printState($states[$stateCount][1][$symCount]);
#	  print printState($states[$stateCount][1][$symCount]) . "\n";
	}
      }
    }
  }

  close(FPOST);
  print "done\n";
}

sub postPrintState {
  my $state = shift(@_);
  my $output = "# Transition for ($state).\n";

  $state =~ /^(.+),(.),(.),(.),(.+)$/;
  my $qi = $1;
  my $sj = $2;
  my $sij = $3;
  my $dij = $4;
  my $qij = $5;

  if($dij =~ /L/i) {
    for(my $i = 0; $i < length($vars{"alphabet"}); $i++) {
      my $sym = substr($vars{"alphabet"}, $i, 1);
      $output .= "\"(.*)$sym<$qi>$sj(.*)\" -> \"\${1}<$qij>$sym$sij\${2}\"\n";
    }
  } elsif($dij =~ /R/i) {
    for(my $i = 0; $i < length($vars{"alphabet"}); $i++) {
      my $sym = substr($vars{"alphabet"}, $i, 1);
      $output .= "\"(.*)$sym<$qi>$sj(.*)\" -> \"\${1}$sym$sij<$qij>\${2}\"\n";
    }
  } else {
    for(my $i = 0; $i < length($vars{"alphabet"}); $i++) {
      my $sym = substr($vars{"alphabet"}, $i, 1);
      $output .= "\"(.*)$sym<$qi>$sj(.*)\" -> \"\${1}$sym<$qij>$sij\${2}\"\n";
    }
  }

  return($output . "\n");
}
