///////////////////////////////////////////////////////////////////////////////
//                                                         
// Production.cc
// -------------
// dragon LR(1) production implementation
//                                               
// Design and Implementation by Bjoern Lemke               
//                                                         
// (C)opyright 2000-2007 Bjoern Lemke
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2, or (at your option)
// any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; see the file COPYING.  If not, write to
// the Free Software Foundation, 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
//
// IMPLEMENTATION MODULE
//
// Class: Production
// 
// Description: grammar production element modelling
//
///////////////////////////////////////////////////////////////////////////////


#include "Production.h"
   
Production::Symbol::Symbol() 
{
}

Production::Symbol::Symbol(const Symbol& s) 
{
    *this = s;
}

Production::Symbol::Symbol (const Chain& name, bool isTerm) 
{ 
    _name = name; 
    _isTerm = isTerm; 
}

Production::Symbol::~Symbol()
{
}

bool Production::getSymbolAtPos(Chain& symbol, int pos) const
{
    if (pos < _maxPos)
    {
	symbol = (Chain)_symbolList[pos].getName();
	return true;
    }
    return false;
}

bool Production::isTermAtPos(int pos) const
{

    return _symbolList[pos].isTerm();
}

const Chain& Production::Symbol::getName() const
{ 
    return _name; 
}

bool Production::Symbol::isTerm() const
{
    return _isTerm;
}

Production::Symbol& Production::Symbol::operator = (const Symbol& s) 
{
    _name = s._name;
    _isTerm = s._isTerm;
    return (*this);
}

Production::Production()
{
    _maxPos = 0;
}

Production::Production(const Production& p)
{
    *this = p;
}

Production::~Production()
{
}

unsigned long Production::getMaxPos() const
{
    return _maxPos;
}

void Production::addSymbol(const Chain& token, bool isTerm)
{
    _symbolList.Insert(Symbol(token, isTerm));
    _maxPos++;
}

void Production::setName(const Chain& name)
{
    _name = name;
}

void Production::setAction(const Chain& action)
{
    _action = action;
}

void Production::setId(unsigned long pid)
{
    _pid = pid;
}

const Chain& Production::getAction() const
{
    return _action;
}

const Chain& Production::getName() const
{
    return _name;
}

unsigned long Production::getId() const
{
    return _pid;
}

Chain Production::asChain() const
{

    Chain s = _name;
  
    s += "->";
    
    Symbol* pS = _symbolList.First();

    while ( pS )
    {
	s += " ";
	s += pS->getName();
	pS = _symbolList.Next();
    }
    return s;
}

Production& Production::operator = (const Production& p)
{
    _name = p._name;
    _action = p._action;
    _maxPos = p._maxPos;
    _symbolList = p._symbolList;
    _pid = p._pid;
    return (*this);   
}

bool Production::operator == (const Production& p) const
{
    
    // cout << "Prod: =operator called: comapring " << _name << " and " << p._name << endl;
    if (_name != p._name)
	return false;
    
    // cout << "Prod-1: Names matched" << endl;

    Symbol* pS1 = _symbolList.First();
    Symbol* pS2 = p._symbolList.First();

    while (pS1 && pS2) 
    {
	if ((Chain)pS1->getName() != (Chain)pS2->getName())
	    return (false);

	pS1 = _symbolList.Next();
	pS2 = p._symbolList.Next();
    }

    // cout << "Prod-2: symbols matched" << endl;

    if (pS1 || pS2)
	return (false);

    // cout << "Prod-3: len matched" << endl;

    return (true);
}
