/*
* JFLAP - Formal Languages and Automata Package
*
*
* Susan H. Rodger
* Computer Science Department
* Duke University
* August 27, 2009
* Copyright (c) 2002-2009
* All rights reserved.
* JFLAP is open source software. Please see the LICENSE for terms.
*
*/
package grammar;
import gui.environment.Universe;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.SortedSet;
import java.util.TreeSet;
/**
* A Production object is a simple abstract class that represents a production
* rule in a grammar.
*
* @author Ryan Cavalcante
*/
public class Production implements Serializable {
/**
* Creates an instance of Production
.
*
* @param lhs
* the left hand side of the production rule.
* @param rhs
* the right hand side of the production rule.
*/
public Production(String lhs, String rhs) {
if(lhs == null) lhs = "";
if(rhs == null) rhs = "";
myLHS = lhs;
myRHS = rhs;
}
/**
* Sets the right hand side of production to rhs
.
*
* @param rhs
* the right hand side
*/
public void setRHS(String rhs) {
myRHS = rhs;
}
/**
* Sets the left hand side of production to lhs
.
*
* @param lhs
* the left hand side
*/
public void setLHS(String lhs) {
myLHS = lhs;
}
/**
* Returns a string representation of the left hand side of the production
* rule.
*
* @return a string representation of the lhs.
*/
public String getLHS() {
return myLHS;
}
/**
* Returns a string representation of the right hand side of the production
* rule.
*
* @return a string representation of the rhs.
*/
public String getRHS() {
return myRHS;
}
/**
* Returns all symbols (both variables in terminals) in a production.
*
* @return all symbols in a production
*/
public String[] getSymbols() {
SortedSet symbols = new TreeSet();
symbols.addAll(Arrays.asList(getVariables()));
symbols.addAll(Arrays.asList(getTerminals()));
return (String[]) symbols.toArray(new String[0]);
}
/**
* Returns all variables in the production.
*
* @return all variables in the production.
*/
public String[] getVariables() {
ArrayList list = new ArrayList();
String[] rhsVariables = getVariablesOnRHS();
for (int k = 0; k < rhsVariables.length; k++) {
if (!list.contains(rhsVariables[k])) {
list.add(rhsVariables[k]);
}
}
String[] lhsVariables = getVariablesOnLHS();
for (int i = 0; i < lhsVariables.length; i++) {
if (!list.contains(lhsVariables[i])) {
list.add(lhsVariables[i]);
}
}
return (String[]) list.toArray(new String[0]);
}
/**
* Returns all variables on the left hand side of the production.
*
* @return all variables on the left hand side of the production.
*/
public String[] getVariablesOnLHS() {
ArrayList list = new ArrayList();
if(myLHS == null) return new String[0];
for(int i = 0; i < myLHS.length(); i++) {
char c = myLHS.charAt(i);
if (ProductionChecker.isVariable(c))
list.add(myLHS.substring(i, i + 1));
}
return (String[]) list.toArray(new String[0]);
}
/**
* Returns all variables on the right hand side of the production.
*
* @return all variables on the right hand side of the production.
*/
public String[] getVariablesOnRHS() {
ProductionChecker pc = new ProductionChecker();
ArrayList list = new ArrayList();
for (int i = 0; i < myRHS.length(); i++) {
char c = myRHS.charAt(i);
if (ProductionChecker.isVariable(c))
list.add(myRHS.substring(i, i + 1));
}
return (String[]) list.toArray(new String[0]);
}
/**
* Returns all terminals in the production.
*
* @return all terminals in the production.
*/
public String[] getTerminals() {
ArrayList list = new ArrayList();
String[] rhsTerminals = getTerminalsOnRHS();
for (int k = 0; k < rhsTerminals.length; k++) {
if (!list.contains(rhsTerminals[k])) {
list.add(rhsTerminals[k]);
}
}
String[] lhsTerminals = getTerminalsOnLHS();
for (int i = 0; i < lhsTerminals.length; i++) {
if (!list.contains(lhsTerminals[i])) {
list.add(lhsTerminals[i]);
}
}
return (String[]) list.toArray(new String[0]);
}
/**
* Returns all terminals on the right hand side of the production.
*
* @return all terminals on the right hand side of the production.
*/
public String[] getTerminalsOnRHS() {
ProductionChecker pc = new ProductionChecker();
ArrayList list = new ArrayList();
for (int i = 0; i < myRHS.length(); i++) {
char c = myRHS.charAt(i);
if (ProductionChecker.isTerminal(c))
list.add(myRHS.substring(i, i + 1));
}
return (String[]) list.toArray(new String[0]);
}
/**
* Returns true if production
is equivalent to this
* production (i.e. they have identical left and right hand sides).
*
* @param production
* the production being compared to this production
* @return true if production
is equivalent to this
* production (i.e. they have identical left and right hand sides).
*/
public boolean equals(Object production) {
if (production instanceof Production) {
Production p = (Production) production;
return getRHS().equals(p.getRHS()) && getLHS().equals(p.getLHS());
}
return false;
}
/**
* Returns a hashcode for this production.
*
* @return the hashcode for this production
*/
public int hashCode() {
return myRHS.hashCode() ^ myLHS.hashCode();
}
/**
* Returns all terminals on the left hand side of the production.
*
* @return all terminals on the left hand side of the production.
*/
public String[] getTerminalsOnLHS() {
ArrayList list = new ArrayList();
for (int i = 0; i < myLHS.length(); i++) {
char c = myLHS.charAt(i);
if (ProductionChecker.isTerminal(c))
list.add(myLHS.substring(i, i + 1));
}
return (String[]) list.toArray(new String[0]);
}
/**
* Returns a string representation of the production object.
*
* @return a string representation of the production object.
*/
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append(getLHS());
// buffer.append("->");
buffer.append('\u2192');
String rhs = getRHS();
buffer.append(rhs.length() == 0 ? Universe.curProfile.getEmptyString() : rhs);
// buffer.append('\n');
return buffer.toString();
}
/**
* Returns the sequence of symbols in either the left or right hand side.
* For example, for the production A -> BCD
this would return
* the array of strings {"B","C","D"}
.
*/
public String[] getSymbolsOnRHS() {
ArrayList list = new ArrayList();
for (int i = 0; i < myRHS.length(); i++) {
char c = myRHS.charAt(i);
list.add(myRHS.substring(i, i + 1));
}
return (String[]) list.toArray(new String[0]);
}
/** the left hand side of the production. */
protected String myLHS;
/** the right hand side of the production. */
protected String myRHS;
}