/*
* Copyright (C) Chaperon. All rights reserved.
* -------------------------------------------------------------------------
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE file.
*/
package net.sourceforge.chaperon.model.grammar;
import net.sourceforge.chaperon.model.Violations;
import net.sourceforge.chaperon.model.symbol.Nonterminal;
import net.sourceforge.chaperon.model.symbol.SymbolList;
import net.sourceforge.chaperon.model.symbol.SymbolSet;
import net.sourceforge.chaperon.model.symbol.Terminal;
import java.io.Serializable;
/**
* This class presents a production of a grammar
*
* @author <a href="mailto:stephan@apache.org">Stephan Michels</a>
* @version CVS $Id: Production.java,v 1.6 2003/12/09 19:55:52 benedikta Exp $
*/
public class Production implements Serializable, Cloneable
{
private Nonterminal ntsymbol = new Nonterminal("noname");
private SymbolList definition = new SymbolList();
private Terminal precedence = null;
private String location = null;
/**
* Create an empty production.
*/
public Production() {}
/**
* Create a production.
*
* @param ntsymbol The symbol of this production.
*/
public Production(Nonterminal ntsymbol)
{
setSymbol(ntsymbol);
}
/**
* Create a production.
*
* @param ntsymbol The symbol of this production.
* @param definition Definition of the production.
*/
public Production(Nonterminal ntsymbol, SymbolList definition)
{
setSymbol(ntsymbol);
setDefinition(definition);
}
/**
* Set the symbol for this production
*
* @param ntsymbol Non terminal symbol
*/
public void setSymbol(Nonterminal ntsymbol)
{
if (ntsymbol==null)
throw new NullPointerException();
this.ntsymbol = ntsymbol;
}
/**
* Return the symbol from this production
*
* @return Nonterminal symbol
*/
public Nonterminal getSymbol()
{
return ntsymbol;
}
/**
* Set the definition for this production
*
* @param definition A list of symbols, which the definition of this production represented.
*/
public void setDefinition(SymbolList definition)
{
if (definition==null)
throw new NullPointerException();
this.definition = definition;
}
/**
* Return the definition.
*
* @return A list of Symbols, which the definition of this production represented.
*/
public SymbolList getDefinition()
{
return definition;
}
/**
* Return the the length of the Definition
*
* @return Lengt of the Definition
*/
public int getLength()
{
return definition.getSymbolCount();
}
/**
* Set the precedence for this production by a terminal symbol
*
* @param tsymbol Terminal symbol
*/
public void setPrecedence(Terminal tsymbol)
{
precedence = tsymbol;
}
/**
* Return the precedence symbol.
*
* @return Terminal symbol.
*/
public Terminal getPrecedence()
{
return precedence;
}
/**
* If the production contains a precedence symbol.
*
* @return True, if a precedence symbol is defined.
*/
public boolean hasPrecedence()
{
return precedence!=null;
}
/**
* Return all used symbols in this production
*
* @return Set of symbols.
*/
public SymbolSet getSymbols()
{
SymbolSet set = new SymbolSet();
set.addSymbol(ntsymbol);
set.addSymbol(definition);
if (precedence!=null)
set.addSymbol(precedence);
return set;
}
/**
* Set the location from the input source.
*
* @param location Location in the input source.
*/
public void setLocation(String location)
{
this.location = location;
}
/**
* Returns the location from the input source.
*
* @return Location in the input source.
*/
public String getLocation()
{
return location;
}
/**
* Validates the production.
*
* @return Return a list of violations, if this object isn't valid.
*/
public Violations validate()
{
Violations violations = new Violations();
if (ntsymbol==null)
violations.addViolation("No symbol is for the left side defined", location);
/*if ((definition==null) || (definition.getSymbolCount()<=0))
violations.addViolation("No symbols are for the right side defined",
location);*/
return violations;
}
/**
* Compares the production with another production.
*
* @param o Other object.
*
* @return True, if the production are equal.
*/
public boolean equals(Object o)
{
if (o==this)
return true;
if (o instanceof Production)
{
Production production = (Production)o;
if (precedence!=null)
return (ntsymbol.equals(production.ntsymbol)) &&
(definition.equals(production.definition)) &&
(precedence.equals(production.precedence));
else
return (ntsymbol.equals(production.ntsymbol)) &&
(definition.equals(production.definition)) && (production.precedence==null);
}
return false;
}
/**
* Return a string representation of the production.
*
* @return String representation of the production.
*/
public String toString()
{
StringBuffer buffer = new StringBuffer();
buffer.append(ntsymbol+" := ");
for (int j = 0; j<definition.getSymbolCount(); j++)
buffer.append(definition.getSymbol(j)+" ");
if (hasPrecedence())
buffer.append("[precedence="+getPrecedence()+"]");
return buffer.toString();
}
/**
* @return
*
* @throws CloneNotSupportedException
*/
public Object clone()
{
Production clone = new Production();
clone.ntsymbol = ntsymbol;
clone.definition = (SymbolList)definition.clone();
clone.precedence = precedence;
clone.location = location;
return clone;
}
}