import java.io.*;
/**
* This class implements the CYK algorithm
*
* @Shaun Ross
* @March 10, 2004
*/
public class CYK
{
// instance variables
public String [][] VijTable; //table for the CYK check
public FileReader FR; //instance of the File Reader class
public String outputFilename; //instance of the output file name
public FileWriter writer; //a file writer for html output
public PrintWriter out; //a way to use print and println with my file writer
public boolean startCheck; //check to see if the start symbol is in the last place VijTable
/**
* Constructor for objects of class CYK
* Initializes things needed for the CYK algorithm, FileReader, VijTable
* Also calls upon the algorithm
*/
public CYK(String fileName)
{
outputFilename = new String("");
outputFilename = fileName + ".html";
try
{
writer = new FileWriter(outputFilename);
out = new PrintWriter(writer);
}
catch ( Exception e )
{
e.printStackTrace();
}
FR = new FileReader(fileName);
VijTable = new String[FR.stringLength+1][FR.stringLength+1];
VijTable = initialize2DArray(VijTable, FR.stringLength+1, FR.stringLength+1);
algorithm();
startCheck = false;
finalCheck(FR.stringLength);
htmlOutput();
try
{
writer.close();
}
catch ( Exception e )
{
e.printStackTrace();
}
}
/**
* Final check to see if a string is in the grammar
* Side effect............... prints out if the grammar is in the language
*
* @param rows ---- the number of rows in the VijTable
* @return nothing
*/
private void finalCheck(int rows)
{
char startSymbol = FR.ruleArray[1][0];
//for loop goes through the length of the string in the last row of VijTable
for(int i= 0; i< VijTable[rows][0].length(); i++)
{
//check to see if the character at the position i is the startSymbol
if ( VijTable[rows][0].charAt(i) == startSymbol)
{
startCheck = true;
}
}
if(startCheck)
{
System.out.println();
System.out.println("<<<<<<<<<<<<<< THE STRING IS IN THE GRAMMAR >>>>>>>>>>>>>>");
System.out.println();
}
}//end finalCheck(int rows)
/**
* this is the actual algorithm of CYK
* begin
* {
* //Step 1
* for i:=1 to n do
* {
* Vi1:= {A|A_. a is a production and the ith symbol of x is a};
* }
* //Step 2
* for j:=2 to n do
* {
* //Step 3
* for i:= 1 to n-j+1 do
* {
* //Step 6
* Vij := nil;
* //Step 4
* for k:= 1 to j-1 do
* {
* //Step 5 --done in multiple parts because of
* the different combinations possible of BC
* Vij = Vij UNION {A|A -> BC is a production, B is in Vik and C
* is in Vi+k,j-k}
* }
* }
* }
* }
*
*
* @param none
* @return nothing
*/
private void algorithm()
{
String productions = new String(""); //a string of productions
String VijValue = new String(""); //the value of the Vij Position in the Table
String Vik = new String(""); //the Vik value
String Vother = new String(""); //the Vi+k,j-k value
boolean VikMult = false; //if there are multiple Vik values
boolean VotherMult = false; //if there are multiple Vi+k,j-k values
char VikSub, VotherSub; //Sub parts of Vik and Vi+k,j-k in chars
String VikSubstring = new String(""); //Vik substring constructed by the VikSub chars
String VotherSubstring = new String(""); //Vi+k,j-k substring constructed by the VotherSub chars
//put the string at the top of the VijTable
//Step 1
for(int i=0; i < FR.stringLength; i++)
{
VijValue = "";
VijValue = VijValue + FR.ruleArray[0][i];
VijTable[0][i] = VijValue;
productions = findProduction(VijValue);
VijTable[1][i] = productions;
}
//the rest of the algorithm
int i, k;
VijValue = "";
//Step 2
for( int j = 2; j <= FR.stringLength; j++)
{
//Step 3
for (i=0; i < (FR.stringLength-j+1); i++)
{
//Step 4
for(k = 1; k<=j-1; k++)
{
Vik = VijTable[k][i];
//check for multiples in Vik
if(Vik.length() > 1)
{
VikMult = true;
}
Vother = VijTable[j-k][i+k];
//check for multiples in Vother
if(Vother.length() > 1)
{
VotherMult = true;
}
//don't have multiples in Vik or Vother
if( !VikMult && !VotherMult )
{
VijValue = "";
VijValue = Vik + Vother;
productions = findProduction(VijValue);
//will check if the production rule is already there and
//insert it into the table
//Step 5
checkInsertProduction(productions, j, i);
}//end no multiples
//have multiples in Vik
else if(VikMult && !VotherMult)
{
//need to get all combonations from multiple Vik's and the Vother
for(int p=0; p < Vik.length(); p++)
{
VikSub = Vik.charAt(p);
if(VikSub == ',')
{
//do nothing it is a , not a grammar terminal or non terminal
}
//check to see if the combination has a rule that will work
else
{
VikSubstring = "";
VijValue = "";
VikSubstring = VikSubstring + VikSub;
VijValue = VikSubstring + Vother;
productions = findProduction(VijValue);
//will check if the production rule is already there and
//insert it into the table
//Step 5
checkInsertProduction(productions, j, i);
}
}
}//end multiple Vik
//have multiples in Vother
else if(!VikMult && VotherMult)
{
//need to get all combonations from multiple Vother's and the Vik
for(int l=0; l < Vother.length(); l++)
{
VotherSub = Vother.charAt(l);
if(VotherSub == ',')
{
//do nothing it is a , not a grammar terminal or non terminal
}
//check to see if the combination has a rule that will work
else
{
VijValue = "";
VotherSubstring = "";
VotherSubstring = VotherSubstring + VotherSub;
VijValue = Vik + VotherSubstring;
productions = findProduction(VijValue);
//will check if the production rule is already there and
//insert it into the table
//Step 5
checkInsertProduction(productions, j, i);
}
}
}//end multiple Vother
//have multiples in Vik and Vother
else if(VikMult && VotherMult)
{
int p;
for(int o = 0; o < Vik.length(); o++)
{
VikSubstring = "";
VikSub = Vik.charAt(o);
VikSubstring = VikSubstring + VikSub;
//need to get all combonations from multiple Vother's and the one Vik value
for(p=0; p < Vother.length(); p++)
{
VotherSub = Vother.charAt(p);
if(VotherSub == ',')
{
//do nothing it is a , not a grammar terminal or non terminal
}
//check to see if the combination has a rule that will work
else
{
VotherSubstring = "";
VijValue = "";
VotherSubstring = VotherSubstring + VotherSub;
VijValue = VikSubstring + VotherSubstring;
productions = findProduction(VijValue);
//will check if the production rule is already there and
//insert it into the table
//Step 5
checkInsertProduction(productions, j, i);
}
}//end for loop for Vother length
}//end for loop for Vik length
}//end multiple Vik and Vother
//reset the multiple booleans for Vik and Vother
VikMult = VotherMult = false;
}//end //Step 4 for(k = 1; k<=j-1; k++)
//Step 6 -- put nil if there are no productions that can make that substring
if (VijTable[j][i].length() < 1)
{
VijTable[j][i] = "nil";
}
}//end //Step 3 for (i=0; i < (FR.stringLength-j+1); i++)
}//end //Step 2 for( int j = 2; j <= FR.stringLength; j++)
}//end algorithm
/**
* findProduction finds if there is a rule that has the right hand side of the
* string To Match
*
* @param stringToMatch --the string needed to match a rule for
* @return String of the rule that matches the string
*/
private String findProduction(String stringToMatch)
{
String matchString = new String("");
String rulesThatApply = new String("");
char currentPosition;
int j = 3;
//start at 1 because it is the first production rule
for(int i = 0; i < FR.lineNumber-1; i++)
{
matchString = "";
//start at 3 for the start of right hand side
for(j = 3; j< FR.column+1; j++)
{
currentPosition = FR.ruleArray[i][j];
//read the entire production, if current possition is a | or a % we have
//read the entire right hand side of a rule
if (currentPosition == '|' || currentPosition == '%')
{
//check to see if we match what we are looking for
if(matchString.equals(stringToMatch))
{
//get the rule for this RHS match
if(rulesThatApply.length() > 0)
{
rulesThatApply = rulesThatApply + ',' + FR.ruleArray[i][0];
}
else
{
rulesThatApply = rulesThatApply+FR.ruleArray[i][0];
}
}
matchString = "";
}//end if (currentPosition == '|' || currentPosition == '%')
else
{
//add the character to the matchString
matchString = matchString + FR.ruleArray[i][j];
}
}//end for(j = 3; j< FR.column+1; j++)
}//end for(int i = 0; i < FR.lineNumber-1; i++)
return rulesThatApply;
}//end findProduction(String stringToMatch)
/**
* Check Insert Production, checks to see if there are already rules
* that are in the position of insertion of a new rule
*
* @param productions -- the string of the rule that applies
* @param j -- the row position in the VijTable
* @param i -- the column position in the VijTable
* @return nothing
*/
private void checkInsertProduction(String productions, int j, int i)
{
if(productions.length() < 1)
{
//didnt' find any rules
}
else if( VijTable[j][i].length() < 1)
{
//found rules and there aren't any rules that apply yet
VijTable[j][i]= productions;
}
else if( VijTable[j][i].length() >= 1 )
{
//found rules and there are already rules
//check for duplicates before we put them in the VijTable
productions = checkDuplicates(productions, j, i);
if( productions.length() > 0 )
{
VijTable[j][i] = VijTable[j][i] + "," + productions;
}
}
}//end checkInsertProduction(String productions, int j, int i)
/**
* Check Duplicates, checks to see if there are any duplicates in the
* productions string or the in the position of the VijTable
*
* @param productions -- the string of the rules that applie
* @param j -- the row position in the VijTable
* @param i -- the column position in the VijTable
* @return Sting of the production rules that aren't duplicates
*/
private String checkDuplicates( String productions , int j, int i)
{
String checkString = new String("");
String noDupsProductions = new String("");
char checkChar;
boolean duplicate = false;
//go through each production to see if it is already in VijTable
for(int k = 0; k< productions.length(); k++)
{
duplicate = false;
checkChar = productions.charAt(k);
//if it isn't a , then proceed
if(checkChar != ',')
{
//go over each element of VijTable to make sure not duplicated
for(int l = 0; l < VijTable[j][i].length(); l++)
{
if( VijTable[j][i].charAt(l) == checkChar)
{
duplicate = true;
}
}
//if it isn't a duplicate add it to the productions
if(!duplicate && noDupsProductions.length() >= 1)
{
checkString = "";
checkString = checkString + checkChar;
noDupsProductions = noDupsProductions + "," + checkString;
}
//if it isn't a duplicate and it is the first one to add to the new productions
else if(!duplicate && noDupsProductions.length() < 1)
{
checkString = "";
checkString = checkString + checkChar;
noDupsProductions = noDupsProductions + checkString;
}
}//end if(checkChar != ',')
}//end for(int k = 0; k< productions.length(); k++)
return noDupsProductions;
}//end private String checkDuplicates( String productions , int j, int i)
/**
* Initializes a 2D string array with "", nothing
*
* @param arrayToInitialize -- the 2D string array to initialize
* @param rows -- the # of rows
* @param columns -- the # of columns
* @return 2D String array
*/
private String [][] initialize2DArray(String [][] arrayToInitialize, int rows, int columns)
{
int j;
for(int i= 0; i<rows; i++)
{
for(j= 0; j<columns; j++)
{
arrayToInitialize[i][j] = new String("");
}
}
return arrayToInitialize;
}//end String [][] initialize2DArray(String [][] arrayToInitialize, int rows, int columns)
/**
* html Output, to create output in HTML format to put on the web
*
* @param none
* @return nothing
*/
public void htmlOutput()
{
out.println("<html>");
out.println("<head>");
out.println("<title>Output for CYK algorithm</title>");
out.println("</head>");
out.println("<body>");
out.println("<p>");
htmlPrintGrammar();
out.println("</p>");
out.println("<p>");
htmlPrintTestString();
out.println("</p>");
out.println("<p>");
htmlPrintVmatrix();
out.println("</p>");
out.println("<p>");
htmlPrintTruth();
out.println("</p>");
out.println("</body>");
out.println("</html>");
out.println();
}//end htmlOutput()
/**
* html print grammar, to create grammar output for web
*
* @param none
* @return nothing
*/
public void htmlPrintGrammar()
{
String rule = new String("");
out.println("<h3>Grammar:</h3>");
int j;
for(int i = 1; i < FR.ruleArray.length; i++)
{
for(j = 0; j < FR.ruleArray[i].length; j++)
{
if(FR.ruleArray[i][j] != '%')
{
rule = rule + FR.ruleArray[i][j];
}
}
out.println(rule + "<br />");
rule = "";
}
}//end htmlPrintGrammar()
/**
* html print test string, to create test string output for web
*
* @param none
* @return nothing
*/
public void htmlPrintTestString()
{
String testString = new String("");
for(int i=0; i < FR.stringLength; i++)
{
testString = testString + FR.ruleArray[0][i];
}
out.print("<h3>Input String: </h3>");
out.println(testString);
}//end htmlPrintTestString()
/**
* html print V matrix, to create V matrix output for web
*
* @param none
* @return nothing
*/
public void htmlPrintVmatrix()
{
out.println("<h3>V Matrix</h3>");
out.println("<table>");
int j;
for(int i = 1; i < VijTable.length; i++)
{
out.println("<tr align = \"center\">");
for(j = 0; j < VijTable[i].length-i; j++)
{
if(startCheck)
{
out.print("<td bgcolor=\"#66FF33\">" + VijTable[i][j] + "</td>");
}
else
out.print("<td bgcolor=\"#FF0000\">" + VijTable[i][j] + "</td>");
}
out.println("</tr>");
//out.println("<br />");
}
out.println("</table>");
}//end htmlPrintVmatrix()
/**
* html print truth, to print out if the grammar is in language output for web
*
* @param none
* @return nothing
*/
public void htmlPrintTruth()
{
String testString = new String("");
for(int i=0; i < FR.stringLength; i++)
{
testString = testString + FR.ruleArray[0][i];
}
if(startCheck)
{
out.print(testString);
out.println(" is in L(G)");
}
else
{
out.print(testString);
out.println(" is <b>NOT</b> in L(G)");
}
}//end htmlPrintTruth()
}//end public class CYK
|