CB-I im WS99/00

Zusätze

Programm zur nichtdeterminsitschen Bottom-Up-Analyse mit backtracking

Ein wechselseitg rektursiver Algorithmus, in Perl programmiert. Die back-shift-Ausgaben sind z.T. etwas irreführend, da auch bei misslungene shift eine "back"-Ausgabe kommt.
#!/usr/local/bin/perl 
# -*-perl-*- mode
#
# realisiere die bottom-Up-analyse mit Backtracking
# 
# Eingabe: Grammatik Wort(e) auf stdin
# Ausgabe: Schritte
# 
# 


sub logmsg {
  local($level,@rest) = @_;

  $level<$verboselevel && print @rest;
}

#####################################
# eigentlicher Algorithmus

sub matchrule {
  # prüfe, ob eine Regel (für Reduktion) anwendbar ist
  local($rn,$left) = @_;
  my $rright = substr($rules[$rn],4);
  my $match = substr($left,-1*length($rright));
  
  logmsg(4,"match: $match ($left) vs $rright (",length($rright),")\n");
  return ( $match eq $rright ); 
}

sub applyrule {
  # führe die Reduktion gemäß der Regel aus
  local($rn,$left) = @_;
  my $rright = substr($rules[$rn],4);

  $left = substr($left,0,length($left)-length($rright));
  $left .= substr($rules[$rn],0,1);
  return $left;
}

sub reduce {
  # ermittle rekursiv die Ableitung
  local($left,$right) = @_;
  my $rn;

  logmsg(2,"($left,$right): ");
  # versuche, ab rule $rulestart eine passende Regel zu finden
  for ( $rn=0; $rn <= $#rules; $rn += 1 ) {
    logmsg(3,"try: rule $rn (",$rules[$rn],")\n");
    if ( matchrule($rn,$left) ) {
      logmsg(2,"reduce, Regel $rn (",$rules[$rn],")\n");
      reduce( applyrule($rn,$left), $right);
      # wenn das zurückkehrt, ist backtracking gemeint 
      # - nächste Regel versuchen
      logmsg(2,"back: Regel $rn\n");
    };
  };
  # keine angemessene Regel mehr gefunden; shift:
  wordshift($left,$right);
  # wenn es hierher zurückkehrt, muß backtracking 
  # 1 Ebene höher versucht werden:
  logmsg(2,"back: shift\n");
  return;
}

sub wordshift {
  local($left,$right) = @_;
  
  #logmsg(2,"($left,$right): ");
  # Ende prüfen ...
  if ($right eq "" && $left eq "S") {
    logmsg(1,"Wort $word in L(G)\n");
    exit 0;
  } elsif ($right eq "" && $left eq $word) {
    logmsg(1,"Wort $word nicht in L(G)\n");
    exit 0;
  } elsif ($right eq "") {
    return;
  }
  # ansonsten shift, und reduzieren ....
  logmsg(2,"shift\n");
  $left .= substr($right,0,1);
  $right = substr($right,1);
  reduce($left,$right);
}
  

######################## main
# Daten einlesen
$verboselevel=1;

while (<>) {
  chomp;
  /::=/ && ( push(@rules,$_), next );
  /^-v/ &&  ( $verboselevel = length($_), next );
  /^$/ || do {
    # ein zu bearbeitendes Wort
    $word = $_;
    logmsg(2,"Regeln:\n ");
    for ($i=0; $i<=$#rules;$i+=1) {
      logmsg(2,"$i: ",$rules[$i],"\n ");
    };
    logmsg(1,"\nWort: $word\n\n");

    # Start
    wordshift("",$word);
    # das darf nicht zurückkommen ?!
    die ("Fehler: Fall kann nicht vorkommen\n");
  }
}

      

Eingabe zu Blatt 4 Aufgabe 2

-vv
S::=ApeK
S::=Ape
S::=peK
S::=pe
S::=BR
A::=As
A::=s
B::=tWl
B::=tl
W::=atze
W::=aWe
W::=ae
R::=wurm
R::=ApeK
R::=Ape
R::=peK
R::=pe
K::=Kk
K::=k

tatzelspekk
      

Dietmar Lammers
Last modified: Mon Nov 29 15:06:39 MET 1999