///////////////////////////////////////////////////////////////////////////////
//                                                         
// Dragon.cc
// ---------
// Dragon implementation module
//                                               
// 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: Dragon 
// 
// Description: body module for the dragon parser generater 
//
///////////////////////////////////////////////////////////////////////////////

// BASE INCLUDES
#include <lfc/Exception.h>
#include <lfc/Chain.h>
#include <lfc/File.h>
#include <lfc/Tokenizer.h>
#include <lfc/ListT.h>
#include <lfc/SetT.h>

// DRAGON INCLUDES
#include "Production.h"
#include "Terminal.h"
#include "LR1Element.h"
#include "Dragon.h"
#include "Worm.h"
#include "LR1Analyser.h"
#include "LALRAnalyser.h"

#define LOADCOUNT 50

Dragon::Dragon(const Chain& parserName, bool javaMode, ParserMode mode, bool dynamicTable)
{
    _parserName = parserName;
    _javaMode = javaMode;
    _dynamicTable = dynamicTable;
    _mode = mode;
}

Dragon::~Dragon()
{
}

void Dragon::generate(bool dumpIt)
{
    
    cout << "Reading Header ..." << endl;
    readHeader();
    
    cout << "Reading Terminals ..." << endl;
    readTerminals();

    cout << "Reading Productions ..." << endl;
    readProductions();
    
    cout << "Checking Productions ..." << endl;
    checkProductions();

    cout << "Analysing ..." << endl;
    createParseTable();

    if ( dumpIt )
    {
	cout << "Productions" << endl;

	Production* pP =  _productionSet.First();
	while (pP)
	{
	    cout << pP->getId() <<  " : " << pP->asChain() << endl;
	    pP =  _productionSet.Next();
	}

	cout << "Parse Table" << endl;
	cout << "-----------" << endl;
	printParseTable();

    } 
    else
    {
	cout << "Generating Code ..." << endl;
	generateCode();
    }
}

void Dragon::printParseTable()
{

    
    ParseTableEntry *pPTE = _parseTable.First();
    while (pPTE)
    {
	switch (pPTE->getAction())
	{
	case ParseTableEntry::SHIFT:
	    cout << pPTE->getState() << " SHIFT " << pPTE->getToken() << " " << pPTE->getArg() << endl;
	    break;
	case ParseTableEntry::REDUCE:
	    cout << pPTE->getState() << " REDUCE " << pPTE->getToken() << " " << pPTE->getArg() << endl;
	    break;
	case ParseTableEntry::JUMP:
	    cout << pPTE->getState() << " JUMP " << pPTE->getToken() << " " << pPTE->getArg() << endl;
	    break;
	case ParseTableEntry::ACCEPT:
	    cout << pPTE->getState() << " ACCEPT" << pPTE->getToken() << " " << pPTE->getArg() << endl;
	    break;
	}
	pPTE = _parseTable.Next();
    }

    
}

void Dragon::readHeader()
{
    
    Chain defFileName = _parserName + ".def";
    
    // cout << "open file " << defFileName << endl;

    File fin(defFileName);

    fin.open(File::READ);

    bool sepRead = false;

    Chain line;
    bool sectionRead = false;
    while (fin.readLine(line) && sectionRead == false)
    {
	line=line.cutTrailing(Chain(" \t"));
	if ( line == Chain("HEADER"))
	{
	    while (fin.readLine(line) && sectionRead == false) 
	    {
		line=line.cutTrailing(Chain(" \t"));
		if (line && line[0] != '#')
		{
		    if (line != Chain("END"))
		    {
			Tokenizer tok(line, " \t");
			Chain name, value;
			if (tok.nextToken(name))
			{		      
			    tok.getTail(value);

			    value=value.cutTrailing(Chain(" \t"));			
    
			    if (name == Chain("SEPSIGN"))
			    {
				_sepsignList.Insert(value);
			    }
			    if (name == Chain("SEPIGNORE"))
			    {
				_sepignoreList.Insert(value);
			    }
			    if (name == Chain("IGNORE"))
			    {
				Terminal t(value, value, 0);
				_terminalSet.Insert(t);
				_reserveList.Insert(value);
			    }
			}		      
			else
			{
			    Chain msg = "scanning of line <" + line + "> failed.";
			    throw Exception(EXLOC, msg);
			}
		    }
		    else
		    {
			sectionRead = true;
		    }
		}
	    }
	}
    }
}

void Dragon::readTerminals()
{
    
    Chain defFileName = _parserName + ".def";
    
    File fin(defFileName);

    fin.open(File::READ);

    Chain line;

    int num=1;

    bool sectionRead = false;

    while (fin.readLine(line) && sectionRead == false)
    {
	line=line.cutTrailing(Chain(" \t"));
	if ( line == Chain("TOKENSET"))
	{
	    while (fin.readLine(line) && sectionRead == false) 
	    {
		line=line.cutTrailing(Chain(" \t"));
		if (line && line[0] != '#')
		{
		    if (line != Chain("END"))
		    {

			Tokenizer *pTok;

			if (line[0] == '!')
			{
			    Tokenizer tok(line, " ");
			    Chain septoken;
			    tok.nextToken(septoken);
			    Chain sep = septoken.cutTrailing('!');
			   
			    pTok = new Tokenizer(line, sep);
			
			    Chain escToken;
			    pTok->nextToken(escToken);

			}
			else
			{
			    pTok = new Tokenizer(line, ":");
			}

			Chain regexp, token;
			if (pTok->nextToken(regexp))
			{
			    if (pTok->nextToken(token))
			    {			      
				token = token.cutTrailing(Chain(" \t"));
				regexp = regexp.cutTrailing(Chain(" \t")); 
				Terminal t(token, regexp, num);
				_terminalSet.Insert(t);
				num++;
			    }
			    else 
			    {
				Chain msg = "scanning of line <" + line + "> failed.";
				throw Exception(EXLOC, msg);
				
			    }
			} 
			else
			{
			    Chain msg = "scanning of line <" + line + "> failed.";
			    throw Exception(EXLOC, msg);				
			}

			delete pTok;
			
		    }
		    else
		    {
			sectionRead = true;
		    }
		}
	    }    
	}
    }
    fin.close();
}

void Dragon::readProductions()
{

    Chain defFileName = _parserName + ".def";
    
    File fin(defFileName);

    fin.open(File::READ);

    Chain line;

    bool sectionRead = false;

    unsigned long pid = 0;

    while (fin.readLine(line) && sectionRead == false)
    {
	line=line.cutTrailing(Chain(" \t"));
	if ( line == Chain("PRODUCTIONSET"))
	{
	    
	    while (fin.readLine(line) && sectionRead == false) 
	    {
		line=line.cutTrailing(Chain(" \t"));
		if (line && line[0] != '#')
		{
		    if (line != Chain("END"))
		    {

			Tokenizer tok(line, " \t");
			Chain token;
			
			if (tok.nextToken(token))
			{
			    Production prod;
			    
			    prod.setName(token);
			    prod.setId(pid);

			    pid++;

			    if (tok.nextToken(token))
			    {
				if (token != Chain(":"))
				{
				    Chain msg = "Invalid grammer token " + token;
				    throw Exception(EXLOC, msg);				    
				}
				while (tok.nextToken(token))
				{
				    if (token != Chain(";"))
				    {
					if ( _terminalSet.Find(Terminal(token)) )
					{
					    prod.addSymbol(token, true);
					}
					else
					{
					    prod.addSymbol(token, false);	       
					}
				    }
				    else 
				    {
					if (tok.nextToken(token))
					{				   
					    prod.setAction(token);	       
					}
					else
					{
					    // no action given
					}
				    }	
				}
				if ( !  _productionSet.Insert(prod) )
				{			       
				    Chain msg = "Duplicate production <" + prod.getName() + "> detected.";
				    throw Exception(EXLOC, msg);
				}
			    }
			}			
		    }
		    else
		    {
			sectionRead = true;
		    }
		}
	    }    
	}
    }
    fin.close();
}

void Dragon::checkProductions()
{

    ListT<Chain> prodNameList;

    Chain startProd;

    Production* pP =  _productionSet.First();
    while (pP)
    {
	if ( pP->getId() == 0 )
	    startProd = pP->getName();
	prodNameList.Insert(pP->getName());
	pP =  _productionSet.Next();
    }

    // check for unknown productions
    pP =  _productionSet.First();
    while (pP)
    {
	int pos = pP->getMaxPos() - 1;
	
	while ( pos >= 0 )
	{   
	    if ( ! pP->isTermAtPos(pos) )
	    {
		Chain symbol;
		pP->getSymbolAtPos(symbol, pos);
		if ( ! prodNameList.Find(symbol) )
		{
		    Chain msg = "Unknown symbol " + symbol;
		    throw Exception(EXLOC, msg);
		}
	    }
	    pos--;
	}
	pP =  _productionSet.Next();
    }

    // check for useless productions

    Chain *pS  =  prodNameList.First();
    while (pS)
    {

	bool notFound = true;
	pP =  _productionSet.First();
	while (pP && notFound )
	{
	
	    if ( pP->getName() != *pS )
	    {
		int pos = pP->getMaxPos() - 1;
		
		while ( pos >= 0 && notFound)
		{   
		    if ( ! pP->isTermAtPos(pos) )
		    {
			Chain symbol;
			pP->getSymbolAtPos(symbol, pos);
			if ( symbol == *pS )
			{
			    notFound = false;
			}
		    }
		    pos--;
		}
	    }
	    pP =  _productionSet.Next();
	}
	
	if ( notFound && *pS != startProd)
	{
	    Chain msg = "Useless production " + *pS;
	    throw Exception(EXLOC, msg);  
	}

	// cout << "Production " << *pS << " ok" << endl;
	pS  =  prodNameList.Next();
    }    
}

void Dragon::createParseTable()
{

    hashFirstSet();
    
    if ( _mode == LR1 )
    {
	LR1Analyser lr1( &_terminalSet, &_productionSet, &_firstHashSet);
	_numStates = lr1.analyse(_LR1HashSet, _LR1TransSet);
    }
    else
    {
	LALRAnalyser lalr( &_terminalSet, &_productionSet, &_firstHashSet);
	_numStates = lalr.analyse(_LR1HashSet, _LR1TransSet);	
    }
    
    createTable();
    
}

void Dragon::hashFirstSet()
{
    // create first set 
    
    SetT<Chain> prodSet;
    
    Production *pP = _productionSet.First();
    while (pP)
    {
	prodSet.Insert(pP->getName());
	pP = _productionSet.Next();
    }
    Chain *pS = prodSet.First();
    while (pS)
    {
	SetT<Chain> firstSet;
	getFirstSet(firstSet, *pS);
	FirstHash h(*pS, firstSet);
	_firstHashSet.Insert(h);
	pS = prodSet.Next();
    }
}


void Dragon::getFirstSet(SetT<Chain>& firstSet, const Chain& s)
{
    Terminal* pT = _terminalSet.First();
    while (pT)
    {
	if ((Chain)pT->getName() == s)
	{
	    firstSet.Insert(s);
	    return;
	}
	pT = _terminalSet.Next();
    }
    
    SetT<Chain> todoSet;    
    SetT<Chain> doneSet;

    todoSet.Insert(s);

    while ( ! todoSet.isEmpty() )
    {
	 
	Chain* pS = todoSet.First();

	SetT<Production> privateProdSet = _productionSet;

	Production* pP = privateProdSet.First();
	while (pP)
	{
	    if ( (Chain)pP->getName() == *pS ) 
	    {
		Chain s;
		if ( pP->getSymbolAtPos(s, 0) )
		{ 
		    if (pP->isTermAtPos(0))
		    {
			firstSet.Insert(s);
		    }
		    else
		    {			
			if ( ! doneSet.Find(s) )
			{
			    todoSet.Insert(s);
			}
		    }
		}
		else
		{
		    if ( _epsSet.Find(*pS) == 0 )
		    {
			_epsSet.Insert(*pS);
			getEpsilonJump(firstSet, *pS);
			_epsSet.Remove(*pS);
		    }
		    
		}	       
	    }
	    
	    pP = privateProdSet.Next();

	}
	
	doneSet.Insert(*pS);
	todoSet.Remove(*pS);       

    }

}

void Dragon::getEpsilonJump(SetT<Chain>& firstSet, const Chain& prod)
{

    SetT<Production> privateProdSet = _productionSet;

    SetT<Chain> todoSet;
    SetT<Chain> doneSet;

    todoSet.Insert(prod);

    while ( ! todoSet.isEmpty() )
    {
	Chain* pS = todoSet.First();

	Production *pP = privateProdSet.First();
	
	while (pP)
	{
	    int i=0;
	    Chain sym;
	    while (pP->getSymbolAtPos(sym, i))
	    {		
		if (sym == *pS)
		{    
		    if ( pP->getSymbolAtPos(sym, i+1))
		    {
			if (pP->isTermAtPos(i+1))
			{
			    // cout << "Inserting " << sym << " into first set" << endl;
			    firstSet.Insert(sym);
			}
			else
			{
			
			    // cout << "Getting first set for " << sym << endl;
			    
                            if ( (Chain)sym == (Chain)prod)
			    {
				// cout << "Detecting loop ..." << endl;
				// calling getFirstSet for the same production 
				// leads to an infinite recursive loop		 
			    }
			    else
			    { 
				getFirstSet(firstSet, sym);
			    }			
			}
		    }
		    else
		    {
			
			// cout << "Inserting backtrack prod " << pP->getName() << " into todo set" << endl;
			if (doneSet.Find(pP->getName()) == 0 && pP->getId() != 0 )
			    todoSet.Insert(pP->getName());
			else
			    firstSet.Insert(Chain("$"));
		    }
		}
		i++;
	    }
	    pP = privateProdSet.Next();
	}
	
	doneSet.Insert(*pS);
	todoSet.Remove(*pS);

    }
}


void Dragon::createTable()
{

    cout << "Creating syntax table ..." << endl;
    
    LR1Hash* pH = _LR1HashSet.First();
    
    int i=0;
    while (pH)
    {


	rotate();

	/*
	if ( i % 100 == 0 )
	{
	    cout << i << "...";
	    cout.flush();
	}
	*/


	LR1Element* pE = pH->getSet().First();
	while (pE)
	{

	    Chain token;
	    if (pE->getSymbolAtPos(token))
	    {
		if ( ! pE->isProdAtPos() )
		{
		    LR1Trans* pT = _LR1TransSet.First();
		    while (pT)
		    {			
			if ( (Chain)pT->getToken() == (Chain)token 
			     && pT->getSid() == pH->getId() )
			{
			    ParseTableEntry e(pH->getId(), token, ParseTableEntry::SHIFT, pT->getTid());
			    
			    ParseTableEntry* pPTE = _parseTable.Find(e);
			    if ( pPTE)
			    {
				if ( pPTE->getAction() == ParseTableEntry::SHIFT && pPTE->getArg() != pT->getTid() )
				{
				 
				    cout << "------ Set A ------" << pPTE->getArg() << endl;
				    LR1Hash *pH = _LR1HashSet.First();
				    while (pH)
				    {
					if (pH->getId() == pPTE->getArg())
					{
					    LR1Element *pE = pH->getSet().First();
					    while (pE)
					    {
						cout << pE->asChain() << endl;
						pE = pH->getSet().Next();
					    }
					}

					pH = _LR1HashSet.Next();
				    }
				    cout << "------ Set B ------" << pT->getTid() << endl;
				    pH = _LR1HashSet.First();
				    while (pH)
				    {
					if (pH->getId() == pT->getTid())
					{
					    LR1Element *pE = pH->getSet().First();
					    while (pE)
					    {
						cout << pE->asChain() << endl;
						pE = pH->getSet().Next();
					    }
					}

					pH = _LR1HashSet.Next();
				    }

				    Chain msg = "Detected shift/shift conflict with production " + pE->asChain();
				    throw Exception(EXLOC, msg);
				    
				}
				if ( pPTE->getAction() == ParseTableEntry::REDUCE )
				{
				    Chain msg = "Detected shift/reduce conflict with production " + pE->asChain();
				    throw Exception(EXLOC, msg);
				}
			    }
			    else
			    {
				_parseTable.Insert(e);
			    }
			}
			pT = _LR1TransSet.Next();
		    }		   		   
		}		
	    }
	    else
	    {
		if ( pE->getProdId() != 0 ) // not start production
		{
		    ParseTableEntry e(pH->getId(), pE->getFirst(), ParseTableEntry::REDUCE, pE->getProdId());
		    
		    ParseTableEntry* pPTE = _parseTable.Find(e);
		    if ( pPTE)
		    {		     
			if ( pPTE->getAction() == ParseTableEntry::SHIFT )
			{
			    Chain msg = "Detected shift/reduce conflict with production " + pE->asChain();
			    throw Exception(EXLOC, msg);
			}
			else if ( pPTE->getAction() == ParseTableEntry::REDUCE )
			{
			    Chain msg = "Detected reduce/reduce conflict with production " + pE->asChain();
			    throw Exception(EXLOC, msg);

			}			
		    }
		    else
		    {
			_parseTable.Insert(e);
		    }
		}
		else 
		{
		    if ( (Chain)pE->getFirst() == Chain("$"))
		    {
			ParseTableEntry e(pH->getId(), pE->getFirst(), ParseTableEntry::ACCEPT);
			_parseTable.Insert(e);
		    }
		}
	    }
	    pE = pH->getSet().Next();
	}

	// create jump table

	LR1Trans* pT = _LR1TransSet.First();
	while (pT)
	{			
	    if ( pT->getSid() == pH->getId() && 
		 ! _terminalSet.Find(Terminal(pT->getToken())))		
	    {
		ParseTableEntry e(pH->getId(), pT->getToken(), ParseTableEntry::JUMP, pT->getTid());
		_parseTable.Insert(e);
	    }
	    pT = _LR1TransSet.Next();
	}
	pH = _LR1HashSet.Next();

	i++;
    }
}

void Dragon::generateCode()
{
    if ( _javaMode )
    {
	generateJavaCode();
    }
    else
    {
	generateHeaderCode();
	generateMethodCode();
    }
}

void Dragon::generateHeaderCode()
{

    Chain headerFileName = _parserName + ".h";
    
    File fout(headerFileName);
    
    fout.open(File::WRITE);
    
    fout << "//\n";
    fout << "// File: "<< _parserName << ".h\n";
    fout << "// This code was produced by the dragon parser generator\n";
    fout << "//\n";
    fout << "#include <lfc/Exception.h>\n";
    fout << "#include <lfc/Chain.h>\n";
    fout << "#include <lfc/ListT.h>\n";
    fout << "#define MAXTOKENVAL 100\n";
    fout << "\n";
    fout << "class " << _parserName << "\n";
    fout << "{\n";
    fout << "\n";
    fout << "public:\n";
    fout << "\n";
    fout << "   " << _parserName << "();\n";
    fout << "   ~" << _parserName << "();\n";
    fout << "\n";
    fout << "   void parse();\n";
    fout << "   ListT<Chain>& getTokenList() { return _tokenList; }\n";
    fout << "\n";
    fout << "protected:\n";
    fout << "\n";
    fout << "   virtual char nextChar() = 0;\n";
    fout << "   virtual void backChar() = 0;\n";

    SetT<Chain> actionList;

    Production *pProd = _productionSet.First();
    while (pProd)
    {
	if ( pProd->getAction() )
	{
	    actionList.Insert(pProd->getAction());
	}
	pProd = _productionSet.Next();
    }   

    Chain *pAction = actionList.First();
    while (pAction)
    {
	fout << "   virtual void " << *pAction << "() = 0;\n";
	pAction = actionList.Next();
    }

    fout << "\n";

    fout << "   enum Token {\n";
    
    Terminal *pTerm = _terminalSet.First();
    while (pTerm)
    {
	fout << "      " << pTerm->getName() << ",\n";
	pTerm = _terminalSet.Next();
    }

    // CHANGE : Dollar changed to ENDTOKEN
    fout << "      ENDTOKEN\n";   
    fout << "   };\n";

    fout << "   void setReserved(Token t);\n";

    fout << "\n";
    fout << "private:\n";
    fout << "\n";
    fout << "   enum Symbol { PROD, TOKEN, NONE };\n";
    fout << "   enum ScannerStateType { START, INTERMEDIATE, FINAL, ANY };\n";
    fout << "   enum Action { SHIFT, REDUCE, ACCEPT, NULLACTION };\n";
    fout << "   enum Production {\n";
    // filter out distinct production symbols
    SetT<Chain> symbolSet;

    pProd = _productionSet.First();
    while (pProd)
    {
	symbolSet.Insert(pProd->getName());
	pProd = _productionSet.Next();
    }   

    Chain *pS = symbolSet.First();
    while (pS)
    {
	fout << "      " << *pS;
	pS = symbolSet.Next();
	if (pS)
	    fout << ",\n";
	else
	    fout << "\n";
	  
    }
    fout << "   };\n";

    _numProd = symbolSet.Size();

    fout << "   void loadScanner();\n";
    
    int mcount = 0;
    fout << "   void loadParser" + Chain(mcount) + "();\n";
    int lcount=0;

    ParseTableEntry *pPTE = _parseTable.First();
    while (pPTE)
    {
	lcount++;
	pPTE = _parseTable.Next();
	if ( pPTE && lcount == LOADCOUNT )
	{
	    mcount++;
	    lcount=0;
	    fout << "   void loadParser" + Chain(mcount) + "();\n";
	}
    }

    mcount++;
    fout << "   void loadParser" + Chain(mcount) + "();\n";

    fout << "\n";
    fout << "   class ScannerStateEntry {\n";
    fout << "\n";
    fout << "   public:\n";
    fout << "\n";
    fout << "      ScannerStateEntry();\n";
    fout << "      ScannerStateEntry(int state, ScannerStateType type = INTERMEDIATE);\n";
    fout << "      ScannerStateEntry& operator = (const ScannerStateEntry& s);\n";
    fout << "      bool operator == (const ScannerStateEntry& s);\n";
    fout << "\n";
    fout << "	   int getState();\n";
    fout << "      ScannerStateType getType();\n";
    fout << "\n";
    fout << "   private:\n";
    fout << "\n";
    fout << "      int _state;\n";
    fout << "      ScannerStateType _type;\n";
    fout << "   };\n";
    fout << "\n";
    fout << "class ScannerTransEntry {\n";
    fout << "\n";
    fout << "   public:\n";
    fout << "\n";
    fout << "      ScannerTransEntry();\n";
    fout << "      ScannerTransEntry(int state, char c);\n";
    fout << "      ScannerTransEntry(int state, char c, int fstate);\n";
    fout << "      ScannerTransEntry& operator = (const ScannerTransEntry& s);\n";
    fout << "      bool operator == (const ScannerTransEntry& s);\n";
    fout << "\n";
    fout << "      int getFState();\n";
    fout << "\n";
    fout << "   private:\n";
    fout << "\n";
    fout << "      int  _state;\n";
    fout << "      char _c;\n";
    fout << "      int _fstate;\n";
    fout << "   };\n";
    fout << "\n";
    fout << "   class Scanner {\n";
    fout << "\n";
    fout << "   public:\n";
    fout << "\n";
    fout << "      Scanner();\n";
    fout << "      Scanner(Token t);\n";
    fout << "\n";
    fout << "      Token getToken();\n";
    fout << "      void addState(ScannerStateEntry s);\n";
    fout << "      void addTransition(ScannerTransEntry t);\n";
    fout << "      bool checkPattern(const Chain& pattern);\n";
    fout << "\n";
    fout << "   private:\n";
    fout << "\n";
    fout << "      Token _token;\n";
    fout << "      ListT<ScannerStateEntry> _stateList;\n";
    fout << "      ListT<ScannerTransEntry> _transList;\n";
    fout << "   };\n";
    fout << "\n";


    fout << "   ListT<Scanner> _scannerList;";
    fout << "\n";
    fout << "   class StackEntry {\n";
    fout << "\n";
    fout << "   public:\n";
    fout << "\n";
    fout << "      StackEntry();\n";
    fout << "      StackEntry(Symbol prod, int num, int state, Chain tval = \"\");\n";
    fout << "      StackEntry& operator = (const StackEntry& a);\n";
    fout << "\n";
    fout << "      int getState();\n";
    fout << "      Symbol getSymbol();\n";
    fout << "      Chain& getTval();\n";

    fout << "\n";
    fout << "   private:\n";
    fout << "\n";
    fout << "      Symbol _symbol;\n";
    fout << "      int _num;\n";
    fout << "      int _state;\n";
    fout << "      Chain _tval;\n";
    fout << "   };\n";
    fout << "\n";
    fout << "   class ActionEntry {\n";
    fout << "\n";
    fout << "   public:\n";
    fout << "\n";
    fout << "      ActionEntry();\n";
    fout << "      ActionEntry(Action action, int num);\n";
    fout << "      bool operator == (const ActionEntry& a);\n";
    fout << "      ActionEntry& operator = (const ActionEntry& a);\n";
    fout << "\n";
    fout << "      Action getAction();\n";
    fout << "      int getNum();\n";
    fout << "\n";
    fout << "   private:\n";
    fout << "\n";
    fout << "      Action _action;\n";
    fout << "      int _num;\n";
    fout << "   };\n";
    fout << "\n";


    if ( _dynamicTable )
    {
	fout << "   ActionEntry** _actionMap;\n";
	fout << "   int** _jumpMap;\n";
    }
    else
    {
	fout << "   ActionEntry _actionMap[" << _numStates + 1 << "][" << _terminalSet.Size()  + 1<< "];\n";
	fout << "   int _jumpMap[" << _numStates + 1 << "][" << _numProd + 1<< "];\n";
    }

    fout << "\n";
    fout << "   class ProdEntry {\n";
    fout << "\n";
    fout << "   public:\n";
    fout << "\n";
    fout << "      ProdEntry();\n";
    fout << "      ProdEntry(int id);\n";
    fout << "      ProdEntry(int id, Production prod, int numSymbol);\n";
    fout << "      bool operator == (const ProdEntry& a);\n";
    fout << "      ProdEntry& operator = (const ProdEntry& a);\n";
    fout << "\n";
    fout << "      int getId();\n";
    fout << "      Production getProd();\n";
    fout << "      int getNumSymbol();\n";
    fout << "\n";
    fout << "   private:\n";
    fout << "\n";
    fout << "      int _id;\n";
    fout << "      Production _prod;\n";
    fout << "      int _numSymbol;\n";
    fout << "\n";
    fout << "   };\n";
    fout << "\n";
    fout << "   ListT<ProdEntry> _prodInfo;\n";
    fout << "\n";
    fout << "   bool isSepIgnore(char c);\n";
    fout << "   bool isSepSign(char c);\n";
    fout << "   bool shiftToken();\n";

    fout << "\n";
    fout << "   bool getAction(int state, Token token, Action& a, int& num);\n";
    fout << "   bool getJump(int state, Production prod, int& fstate);\n";
    fout << "\n";
    fout << "   Token _reservedToken;\n";
    fout << "   bool _isReserved;\n";
    fout << "   Token _token;\n";
    fout << "   char _tokenVal[MAXTOKENVAL];\n";
    fout << "   ListT<Chain> _tokenList;\n";
    fout << "\n";
    fout << "};\n";

    fout.close();
}

void Dragon::generateMethodCode()
{

    Chain methodFileName = _parserName + ".cc";
    
    File fout(methodFileName);

    fout.open(File::WRITE);

    fout << "//\n";
    fout << "// File: "<< _parserName << ".cc\n";
    fout << "// This code was produced by the dragon parser generator\n";
    fout << "//\n";

    fout << "#include \"" << _parserName << ".h\"\n";
    fout << "#include <lfc/Exception.h>\n";
    fout << "#include <lfc/StackT.h>\n";

    fout << "\n";
    fout << _parserName << "::ScannerStateEntry::ScannerStateEntry()\n";
    fout << "{\n";
    fout << "}\n";
    fout << "\n";
    fout << _parserName << "::ScannerStateEntry::ScannerStateEntry(int state, ScannerStateType type)\n";
    fout << "{\n";
    fout << "   _state = state;\n";
    fout << "   _type = type;\n";
    fout << "}\n";
    fout << "\n";
    fout << _parserName << "::ScannerStateEntry& " << _parserName << "::ScannerStateEntry::operator = (const " << _parserName << "::ScannerStateEntry& s)\n";
    fout << "{\n";
    fout << "   _state = s._state;\n";
    fout << "   _type = s._type;\n";
    fout << "   return(*this);\n";
    fout << "}\n";
    fout << "\n";
    fout << "bool " << _parserName << "::ScannerStateEntry::operator == (const " << _parserName << "::ScannerStateEntry& s)\n";
    fout << "{\n";
    fout << "   if ( _state == s._state )\n";
    fout << "      return true;\n";
    fout << "   return false;\n";
    fout << "}\n";
    fout << "\n";
    fout << _parserName << "::ScannerStateType " << _parserName << "::ScannerStateEntry::getType()\n";
    fout << "{\n";
    fout << "   return _type;\n";
    fout << "}\n";
    fout << "int " << _parserName << "::ScannerStateEntry::getState()\n";
    fout << "{\n";
    fout << "   return _state;\n";
    fout << "}\n";
    fout << "\n";
    fout << "\n";
    fout << _parserName << "::ScannerTransEntry::ScannerTransEntry()\n";
    fout << "{\n";
    fout << "}\n";
    fout << "\n";
    fout << _parserName << "::ScannerTransEntry::ScannerTransEntry(int state, char c)\n";
    fout << "{\n";
    fout << "   _state = state;\n";
    fout << "   _c = c;\n";
    fout << "}\n";
    fout << "\n";
    fout << _parserName << "::ScannerTransEntry::ScannerTransEntry(int state, char c, int fstate)\n";
    fout << "{\n";
    fout << "   _state = state;\n";
    fout << "   _c = c;\n";
    fout << "   _fstate = fstate;\n";
    fout << "}\n";
    fout << "\n";
    fout << _parserName << "::ScannerTransEntry& " << _parserName << "::ScannerTransEntry::operator = (const " << _parserName << "::ScannerTransEntry& s)\n";
    fout << "{\n";
    fout << "   _state = s._state;\n";
    fout << "   _c = s._c;\n";
    fout << "   _fstate = s._fstate;\n";
    fout << "   return(*this);\n";
    fout << "}\n";
    fout << "\n";
    fout << "bool " << _parserName << "::ScannerTransEntry::operator == (const " << _parserName << "::ScannerTransEntry& s)\n";
    fout << "{\n";
    fout << "   if ( _state == s._state && _c == s._c)\n";
    fout << "      return true;\n";
    fout << "   return false;\n";
    fout << "}\n";
    fout << "\n";
    fout << "int "<< _parserName << "::ScannerTransEntry::getFState()\n";
    fout << "{\n";
    fout << "   return _fstate;\n";
    fout << "}\n";
    fout << "\n";


    fout << "\n";
    fout << _parserName << "::Scanner::Scanner()\n";
    fout << "{\n";
    fout << "}\n";
    fout << "\n";


    fout << "\n";
    fout << _parserName << "::Scanner::Scanner(Token t)\n";
    fout << "{\n";
    fout << "   _token = t;\n";
    fout << "}\n";
    fout << "\n";

    fout << _parserName << "::Token " << _parserName << "::Scanner::getToken()\n";
    fout << "{\n";
    fout << "   return _token;\n";
    fout << "}\n";
    fout << "\n";

    fout << "void " << _parserName << "::Scanner::addState(ScannerStateEntry s)\n";
    fout << "{\n";
    fout << "   _stateList.Insert(s);\n";
    fout << "}\n";
    fout << "\n";

    fout << "void " << _parserName << "::Scanner::addTransition(ScannerTransEntry t)\n";
    fout << "{\n";
    fout << "   _transList.Insert(t);\n";
    fout << "}\n";
    fout << "\n";

    fout << "bool " << _parserName << "::Scanner::checkPattern(const Chain& p)\n";
    fout << "{\n";

    fout << "   unsigned long state = 0;\n";
    fout << "   ScannerStateEntry* pS = _stateList.First();\n";

    fout << "   while (pS)\n";
    fout << "   {\n";
    fout << "      if (pS->getType() == START || pS->getType() == ANY)\n";
    fout << "      {\n";
    fout << "         state = pS->getState();\n";
    fout << "         pS = 0;\n";
    fout << "      }\n";
    fout << "      else\n";
    fout << "      {\n";
    fout << "         pS = _stateList.Next();\n"; 
    fout << "      }\n";
    fout << "   }\n";
    fout << "   unsigned long i = 0;\n";
    fout << "   ScannerTransEntry* pT = \n";
    fout << "   _transList.Find(ScannerTransEntry(state, p[i]));\n";
    fout << "   while (pT)\n";
    fout << "   {\n";
    fout << "      ScannerStateEntry* pS = _stateList.Find(ScannerStateEntry(pT->getFState())); \n";
    fout << "      if (pS)\n";
    fout << "      {\n";
    fout << "         if ( ( i == p.length()-2 ) && ( pS->getType() == FINAL || pS->getType() == ANY))\n";
    fout << "         {\n";
    fout << "            return true;\n";
    fout << "         }\n";
    fout << "         else\n";
    fout << "         {\n";
    fout << "            state = pT->getFState();\n";
    fout << "         }\n";
    fout << "      }\n";
    fout << "      else\n";
    fout << "      {\n";
    fout << "         return false;\n";
    fout << "      }\n";
    fout << "      i++;\n"; 
    fout << "      pT = _transList.Find(ScannerTransEntry(state, p[i]));\n";
    fout << "   }\n";
    fout << "   return false;\n";
    fout << "}\n";


    fout << _parserName << "::StackEntry::StackEntry()\n";
    fout << "{\n";
    fout << "   _symbol = NONE;\n";
    fout << "}\n";
    fout << "\n";
    fout << _parserName << "::StackEntry::StackEntry(Symbol symbol, int num, int state, Chain tval)\n";
    fout << "{\n";
    fout << "   _symbol=symbol;\n";
    fout << "   _num=num;\n";
    fout << "   _state=state;\n";
    fout << "   _tval=tval;\n";
    fout << "}\n";
    fout << "\n";
    fout << _parserName << "::StackEntry& " << _parserName << "::StackEntry::operator = (const " << _parserName << "::StackEntry& se)\n";
    fout << "{\n";
    fout << "   _symbol=se._symbol;\n";
    fout << "   _num=se._num;\n";
    fout << "   _state=se._state;\n";
    fout << "   _tval=se._tval;\n";
    fout << "   return(*this);\n";
    fout << "}\n";
    fout << "\n";
    fout << "int " << _parserName << "::StackEntry::getState()\n";
    fout << "{\n";
    fout << "   return _state;\n";
    fout << "}\n";
    fout << _parserName << "::Symbol " << _parserName << "::StackEntry::getSymbol()\n";
    fout << "{\n";
    fout << "   return _symbol;\n";
    fout << "}\n";
    fout << "Chain& " << _parserName << "::StackEntry::getTval()\n";
    fout << "{\n";
    fout << "   return _tval;\n";
    fout << "}\n";

    fout << "\n";
    fout << _parserName << "::ActionEntry::ActionEntry()\n";
    fout << "{\n";
    fout << "   _action=NULLACTION;\n";
    fout << "}\n";
    fout << "\n";
    fout << _parserName << "::ActionEntry::ActionEntry(Action action , int num)\n";
    fout << "{\n";
    fout << "   _action=action;\n";
    fout << "   _num=num;\n";
    fout << "}\n";
    fout << "\n";
    fout << "bool " << _parserName << "::ActionEntry::operator == (const " << _parserName << "::ActionEntry& ae)\n";
    fout << "{\n";
    fout << "   if (_action == ae._action && _num == ae._num)\n";
    fout << "      return true;\n";
    fout << "   return false;\n";
    fout << "}\n";
    fout << "\n";
    fout << _parserName << "::ActionEntry& " << _parserName << "::ActionEntry::operator = (const " << _parserName << "::ActionEntry& ae)\n";
    fout << "{\n";
    fout << "   _action=ae._action;\n";
    fout << "   _num=ae._num;\n";
    fout << "   return(*this);\n";
    fout << "}\n";
    fout << "\n";
    fout << _parserName << "::Action " << _parserName << "::ActionEntry::getAction()\n";
    fout << "{\n";
    fout << "   return _action;\n";
    fout << "}\n";
    fout << "\n";
    fout << "int " << _parserName << "::ActionEntry::getNum()\n";
    fout << "{\n";
    fout << "   return _num;\n";
    fout << "}\n";
    fout << "\n";
    fout << _parserName << "::ProdEntry::ProdEntry()\n";
    fout << "{\n";
    fout << "}\n";
    fout << "\n";
    fout << _parserName << "::ProdEntry::ProdEntry(int id)\n";
    fout << "{\n";
    fout << "   _id = id;\n";
    fout << "}\n";
    fout << "\n";
    fout << _parserName << "::ProdEntry::ProdEntry(int id, Production prod, int numSymbol)\n";
    fout << "{\n";
    fout << "   _id = id;\n";
    fout << "   _prod = prod;\n";
    fout << "   _numSymbol = numSymbol;\n";
    fout << "}\n";
    fout << "\n";
    fout << "bool " << _parserName << "::ProdEntry::operator == (const " << _parserName << "::ProdEntry& pe)\n";
    fout << "{\n";
    fout << "   if (_id == pe._id)\n";
    fout << "      return true;\n";
    fout << "   return false;\n";
    fout << "}\n";
    fout << "\n";
    fout << _parserName << "::ProdEntry& " << _parserName << "::ProdEntry::operator = (const " << _parserName << "::ProdEntry& pe)\n";
    fout << "{\n";
    fout << "   _id = pe._id;\n";
    fout << "   _prod = pe._prod;\n";
    fout << "   _numSymbol = pe._numSymbol;\n";
    fout << "   return(*this);\n";
    fout << "}\n";
    fout << "\n";
    fout << "\n";
    fout << "int " << _parserName << "::ProdEntry::getId()\n";
    fout << "{\n";
    fout << "   return _id;\n";
    fout << "}\n";
    fout << "\n";
    fout << _parserName << "::Production " << _parserName << "::ProdEntry::getProd()\n";
    fout << "{\n";
    fout << "   return _prod;\n";
    fout << "}\n";
    fout << "\n";
    fout << "int " << _parserName << "::ProdEntry::getNumSymbol()\n";
    fout << "{\n";
    fout << "   return _numSymbol;\n";
    fout << "}\n";


    fout << "void " << _parserName << "::loadScanner()\n";
    fout << "{\n";
    int sid=0;    
    for (int i = 1; i<=_terminalSet.Size(); i++)
    {
	Terminal *pTerm = _terminalSet.First();
	while (pTerm && pTerm->getNum() != i)
	{
	    pTerm = _terminalSet.Next();
	}
	if (pTerm)
	{

	    Worm w(pTerm->getRegExp(), pTerm->getName());
	 
	    w.makeOptimalDEA();
	    
	    Chain scanner = "s" + Chain(sid);
	    
	    fout << "   Scanner " << scanner << "(" << pTerm->getName() << ");\n";
	    
	    FSMState *pS = w.getStateTable().First();	
	    while (pS)
	    {   
		
		fout << "   " << scanner << ".addState(ScannerStateEntry("
		     << pS->Num() << " ,";
		
		switch (pS->Type())
		{
		case START:
		    fout << "START));\n";
		    break;
		case FINAL:
		    fout << "FINAL));\n";	
		    break;
		case ANY:
		    fout << "ANY));\n";	
		    break;
		case NONE:
		    fout << "INTERMEDIATE));\n";
		    break;
		}
		
		pS = w.getStateTable().Next();
	    }
	    
	    FSMTransition *pT = w.getTransitionTable().First();
	    
	    while (pT)
	    {
		
		fout << "   " << scanner << ".addTransition(ScannerTransEntry("
		     << pT->Source() << " ,'" << pT->Sign() << "' ," << pT->Target() << "));\n";
		
		pT = w.getTransitionTable().Next();
	    }
	    
	    
	    fout << "   _scannerList.Insert(" << scanner << ");\n";
	    
	    fout << "\n";	
	    
	    sid++;
	}
	
	
    }

    fout << "}\n";

    int mcount = 0;
    fout << "void " << _parserName << "::loadParser" + Chain(mcount) + "()\n";
    fout << "{\n";
    int lcount=0;

    ParseTableEntry *pPTE = _parseTable.First();
    while (pPTE)
    {
	Chain token = pPTE->getToken();
	if ( token == Chain("$") )
	    token = Chain("ENDTOKEN");

	switch (pPTE->getAction())
	{
	case ParseTableEntry::SHIFT:
	    fout << "   _actionMap["
		 << pPTE->getState() << "][" << token
		 << "] = ActionEntry(SHIFT, " << pPTE->getArg() << ");\n";
	    break;
	case ParseTableEntry::REDUCE:
	    fout << "   _actionMap["
		 << pPTE->getState() << "][" << token
		 << "] = ActionEntry(REDUCE, " << pPTE->getArg() << ");\n";
	    break;
	case ParseTableEntry::JUMP:
	    fout << "   _jumpMap["
		 << pPTE->getState() << "][" << token
		 << "] = " << pPTE->getArg() << ";\n";
	    break;
	case ParseTableEntry::ACCEPT:
	    fout << "   _actionMap["
		 << pPTE->getState() << "][" << token
		 << "] = ActionEntry(ACCEPT, " << pPTE->getArg() << ");\n";
	    break;
	}
	lcount++;
	pPTE = _parseTable.Next();

	if ( pPTE && lcount == LOADCOUNT )
	{
	    mcount++;
	    lcount=0;
	    fout << "}\n";
	    fout << "void " << _parserName << "::loadParser" + Chain(mcount) + "()\n";
	    fout << "{\n";
	}

    }

    fout << "}\n";

    mcount++;
    fout << "void " << _parserName << "::loadParser" + Chain(mcount) + "()\n";
    fout << "{\n";

    Production *pP = _productionSet.First();
    while (pP)
    {

	fout << "   _prodInfo.Insert(ProdEntry("
	     << pP->getId() << ", " << pP->getName() << ", "
	     << pP->getMaxPos() << "));\n";	

	pP = _productionSet.Next();
    }

    fout << "}\n";

    fout << "\n";
    fout << _parserName << "::" << _parserName << "()\n";
    fout << "{\n";

    if ( _dynamicTable )
    {
	fout << "   _actionMap = (ActionEntry**) malloc ( " << _numStates + 1 << " * sizeof(ActionEntry*));\n";
	fout << "   _jumpMap = (int**) malloc( " << _numStates + 1 << " * sizeof (int*));\n";
	fout << "   for ( int c = 0 ; c < " <<  _numStates + 1 << " ; c++ )\n";
	fout << "   {\n";
	fout << "      _actionMap[c] = (ActionEntry*) malloc( " << _terminalSet.Size() +1 << " * sizeof(ActionEntry));\n";
	fout << "      _jumpMap[c] = (int*) malloc( " << _numProd + 1 << " * sizeof (int));\n";
	fout << "   }\n";
    }

    fout << "   loadScanner();\n";

    fout << "   for ( int i=0; i < " << _numStates + 1<< "; i++)\n";
    fout << "   {\n";
    fout << "      int j;\n";
    fout << "      for ( j = 0; j < " << _terminalSet.Size() + 1  <<  "; j++)\n";
    fout << "         _actionMap[i][j] = ActionEntry();\n";
    fout << "      for ( j = 0; j < " << _numProd + 1  <<  "; j++)\n";
    fout << "         _jumpMap[i][j] = -1;\n";
    fout << "   }\n";

    for ( int i=0; i<=mcount; i++)
    {
	fout << "   loadParser" + Chain(i) + "();\n";	
    }    
    fout << "   _isReserved = false;\n";

    fout << "}\n";
    fout << "\n";
    fout << _parserName << "::~" << _parserName << "()\n";
    fout << "{\n";

    if ( _dynamicTable )
    {
	fout << "   for ( int c = 0 ; c < " << _numStates + 1 << " ; c++ )\n";
	fout << "   {\n";
	fout << "      free (_actionMap[c]);\n";
	fout << "      free (_jumpMap[c]);\n";
	fout << "   }\n";
	fout << "   free (_actionMap);\n";
	fout << "   free (_jumpMap);\n";
    }

    fout << "}\n";
    fout << "\n";
    fout << "void " << _parserName << "::parse()\n";
    fout << "{\n";
    fout << "   StackT<StackEntry> s;\n";
    fout << "   StackEntry se(NONE, 0, 0);\n";
    fout << "   s.Push(se);\n";
    fout << "   _isReserved = false;\n";
    fout << "   if ( shiftToken() == false )\n";
    fout << "   {\n";
    fout << "      Chain msg = \"Parse error at token <\" + Chain(_tokenVal) + \">.\";\n";
    fout << "      throw Exception(EXLOC, msg);\n";
    fout << "   }\n";
    fout << "   while ( true )\n";
    fout << "   {\n";
    fout << "      Action a;\n";
    fout << "      int num;\n";
    fout << "      if ( getAction(s.getTop()->getState(), _token, a, num) )\n";
    fout << "      {\n";
    fout << "         switch (a)\n";
    fout << "         {\n";
    fout << "            case SHIFT:\n";
    fout << "            {\n";
    fout << "               StackEntry se(TOKEN, _token, num, _tokenVal);\n";
    fout << "               s.Push(se);\n";
    fout << "               if ( shiftToken() == false )\n";
    fout << "               {\n";
    fout << "                  Chain msg = \"Parse error at token <\" + Chain(_tokenVal) + \">.\";\n";
    fout << "                  throw Exception(EXLOC, msg);\n";
    fout << "               }\n";
    fout << "               break;\n";
    fout << "            }\n";
    fout << "            case REDUCE:\n";
    fout << "            {\n";
    fout << "               _tokenList.Empty();\n";
    fout << "               ProdEntry* pPE = _prodInfo.Find(num);\n";
    fout << "               for (int i=0; i<pPE->getNumSymbol();i++)\n";
    fout << "               {\n";
    fout << "                  StackEntry se;\n";
    fout << "                  s.Pop(se);\n";
    fout << "                  if (se.getSymbol() == TOKEN)\n";
    fout << "                     _tokenList.Insert(se.getTval());\n";
    fout << "               }\n";
    fout << "               int fstate;\n";
    fout << "               if (getJump(s.getTop()->getState(), pPE->getProd(), fstate))\n";
    fout << "               {\n";
    fout << "                  StackEntry se(PROD, pPE->getId(), fstate, _tokenVal);\n";
    fout << "                  s.Push(se);\n";
    fout << "               }\n";
    fout << "               else\n";
    fout << "               {\n";
    fout << "                  Chain msg = \"Cannot reduce after token <\" + Chain(_tokenVal) + \">.\";\n";
    fout << "                  throw Exception(EXLOC, msg);\n";
    fout << "               }\n";
    fout << "               switch (num)\n";
    fout << "               {\n";

    pP = _productionSet.First();
    while (pP)
    {
	if ( pP->getId() != 0 && pP->getAction() )
	{
	    fout << "                  case " << pP->getId() << ":\n" 
		 << "                     " << pP->getAction() << "();\n"
		 << "                     break;\n";	
	}
	    pP = _productionSet.Next();
    }

    fout << "               }\n";
    fout << "               break;\n";
    fout << "            }\n";
    fout << "            case ACCEPT:\n";
    fout << "            {\n";

    pP = _productionSet.First();
    while (pP)
    {
	if ( pP->getId() == 0 && pP->getAction() )
	{ 
	    fout << "               " << pP->getAction() << "();\n";
	}
	pP = _productionSet.Next();
    }


    fout << "               return;\n";
    fout << "            }\n";
    fout << "            default:\n";
    fout << "               break;\n";
    fout << "         }\n";
    fout << "      }\n";
    fout << "      else\n";
    fout << "      {\n";
    fout << "         Chain msg = \"Parse error at token <\" + Chain(_tokenVal) + \">.\";\n";
    fout << "         throw Exception(EXLOC, msg);\n";
    fout << "      }\n";
    fout << "   }\n";
    fout << "}\n";
    fout << "\n";
    fout << "\n";
    fout << "bool " << _parserName << "::getAction(int state, " << _parserName << "::Token token, " <<  _parserName << "::Action& a, int& num)\n";
    fout << "{\n";
    fout << "    if (_actionMap[state][token].getAction() != NULLACTION )\n";
    fout << "    {\n";
    fout << "	a = _actionMap[state][token].getAction();\n";
    fout << "	num = _actionMap[state][token].getNum();\n";
    fout << "	return true;\n";
    fout << "    }\n";
    fout << "    else\n";
    fout << "    {\n";
    fout << "	return false;\n";
    fout << "    }\n";
    fout << "}\n";
    fout << "\n";
    fout << "bool " << _parserName << "::getJump(int state, Production prod, int& fstate)\n";
    fout << "{\n";
    fout << "    if ( _jumpMap[state][prod] > 0 )\n";
    fout << "    {\n";
    fout << "       fstate = _jumpMap[state][prod];\n";
    fout << "	    return true;\n";
    fout << "    }\n";
    fout << "    else\n";
    fout << "    {\n";
    fout << "	    return false;\n";
    fout << "    }\n";
    fout << "}\n";
    fout << "\n";

    fout << "bool " << _parserName << "::isSepSign(char c)\n";
    fout << "{\n";
    
    Chain *pSep = _sepsignList.First();
    
    while (pSep)
    {
	
	fout << "   if (c == " << *pSep << ") return true;\n";
	pSep = _sepsignList.Next();
    }
    fout << "   return false;\n";
    fout << "}\n";

    fout << "bool " << _parserName << "::isSepIgnore(char c)\n";
    fout << "{\n";
    
    pSep = _sepignoreList.First();
    
    while (pSep)
    {
	
	fout << "   if (c == " << *pSep << ") return true;\n";
	pSep = _sepignoreList.Next();
    }
    fout << "   return false;\n";
    fout << "}\n";



    fout << "bool " << _parserName << "::shiftToken()\n";
    fout << "{\n";
    
    
    fout << "   unsigned long i=0;\n";
    fout << "   char c;\n";
    fout << "   while ( isSepIgnore(c = nextChar()) && ! _isReserved );\n";

    fout << "   if ( _isReserved )\n";
    fout << "   {\n";
    fout << "      _token = _reservedToken;\n";
    fout << "      _isReserved = false;\n";
    fout << "      return true;\n";
    fout << "   }\n";

    fout << "   if (c == 0)\n";
    fout << "   {\n";
    fout << "      _token = ENDTOKEN;\n";
    fout << "      return true;\n";
    fout << "   }\n";
    
    fout << "   if (isSepSign(c))\n";
    fout << "   {\n";
    fout << "      _tokenVal[i]=c;\n";
    fout << "       i++;\n";
    fout << "   }\n";
    fout << "   else\n";
    fout << "   {\n";
    fout << "      while (c && ! isSepIgnore(c) && ! ( isSepSign(c) && i>0 ) )\n";
    fout << "      {\n";
    fout << "         _tokenVal[i]=c;\n";
    fout << "         i++;\n";
    fout << "         c = nextChar();\n";
    fout << "      }\n"; 
    fout << "      if (isSepSign(c)) backChar();\n";
    fout << "   }\n";
    fout << "   _tokenVal[i]=0;\n";
    fout << "   Scanner* pS = _scannerList.First();\n";
    fout << "   while (pS)\n";
    fout << "   {\n";
    fout << "      if (pS->checkPattern(_tokenVal))\n";
    fout << "      {\n";
    fout << "         _token = pS->getToken();\n";
    fout << "         return true;\n";
    fout << "      }\n";
    fout << "      pS=_scannerList.Next();\n";
    fout << "   }\n";
    fout << "   return false;\n";
    fout << "}\n";


    fout << "void " << _parserName << "::setReserved(Token t)\n";
    fout << "{\n";
    fout << "   _reservedToken = t;\n";
    fout << "   _isReserved = true;\n";
    fout << "}\n";

    
    fout.close();
    return;
}


void Dragon::generateJavaCode()
{

    Chain javaFileName = _parserName + ".java";
    
    File fout(javaFileName);
    
    fout.open(File::WRITE);
    
    fout << "//\n";
    fout << "// File: "<< _parserName << ".java\n";
    fout << "// This code was produced by the dragon parser generator\n";
    fout << "//\n";
    fout << "import java.util.ArrayList;\n";
    fout << "import java.util.List;\n";
    fout << "import java.util.Stack;\n";

    fout << "\n";
    fout << "class " << _parserName << "\n";
    fout << "{\n";
    fout << "\n";
    fout << "   final int MAXTOKENVAL = 1000;\n";
    fout << "   List<String> _tokenList = new ArrayList<String>();\n";
    fout << "   Token _reservedToken;\n";
    fout << "   boolean _isReserved;\n";
    fout << "   Token _token;\n";
    fout << "   char _tokenVal[] = new char[MAXTOKENVAL];\n";
    fout << "   int _tokenLen = 0;\n";

    fout << "   int _actNum;\n";
    fout << "   Action _actAction;\n";
    fout << "   int _actFState;\n";

    fout << "\n";
    fout << "   enum Symbol { PROD, TOKEN, NONE };\n";
    fout << "   enum ScannerStateType { START, INTERMEDIATE, FINAL, ANY };\n";
    fout << "   enum Action { SHIFT, REDUCE, ACCEPT };\n";
    fout << "   enum Production {\n";

    // filter out distinct production symbols

    SetT<Chain> symbolSet;

    Production *pProd = _productionSet.First();
    pProd = _productionSet.First();
    while (pProd)
    {
	symbolSet.Insert(pProd->getName());
	pProd = _productionSet.Next();
    }   

    Chain *pS = symbolSet.First();
    while (pS)
    {
	fout << "        " << *pS;
	pS = symbolSet.Next();
	if (pS)
	    fout << ",\n";
	else
	    fout << "\n";
	  
    }
    fout << "    };\n";
    
    fout << "    public List<String> getTokenList() { return _tokenList; }\n";
    fout << "\n";
    fout << "    // source stream \n";
    fout << "    public char nextChar() throws Exception { return 0; };\n";
    fout << "    public void backChar() {};\n";

    SetT<Chain> actionList;

    pProd = _productionSet.First();
    while (pProd)
    {
	if ( pProd->getAction() )
	{
	    actionList.Insert(pProd->getAction());
	}
	pProd = _productionSet.Next();
    }   

    Chain *pAction = actionList.First();
    while (pAction)
    {
	fout << "    public void " << *pAction << "() throws Exception {}\n";
	pAction = actionList.Next();
    }

    fout << "\n";

    fout << "    enum Token {\n";
    
    Terminal *pTerm = _terminalSet.First();
    while (pTerm)
    {
	fout << "        " << pTerm->getName() << ",\n";
	pTerm = _terminalSet.Next();
    }

    fout << "        ENDTOKEN\n";   
    fout << "    };\n";

    fout << "    void setReserved(Token t)\n";
    fout << "    {\n";
    fout << "       _reservedToken = t;\n";
    fout << "       _isReserved = true;\n";
    fout << "    }\n";



    // Sub Class ScannerStateEntry

    fout << "\n";
    fout << "   class ScannerStateEntry\n";
    fout << "   {\n";
    fout << "      int  _state;\n";
    fout << "      ScannerStateType _type;\n";
    fout << "\n";
    fout << "      ScannerStateEntry() {};\n";
    fout << "      ScannerStateEntry(int state)\n";
    fout << "      {\n";
    fout << "         _state = state;\n";
    fout << "      };\n";
    fout << "      ScannerStateEntry(int state, ScannerStateType type)\n";
    fout << "      {\n";
    fout << "         _state = state;\n";
    fout << "         _type = type;\n";
    fout << "      };\n";
    fout << "      public int getState() { return _state; }\n";
    fout << "      public ScannerStateType getType() { return _type; }\n";
    fout << "      public boolean equals(Object o)\n";
    fout << "      {\n";
    fout << "          if ( _state == ((ScannerStateEntry)o)._state )\n";
    fout << "             return true;\n";
    fout << "          return false;\n";
    fout << "      }\n";
    fout << "   }\n";
    fout << "\n";

    // Sub Class ScannerTransEntry

    fout << "   class ScannerTransEntry\n";
    fout << "   {\n";
    fout << "\n";
    fout << "      int _state;\n";
    fout << "      int _fstate;\n";
    fout << "      char _c;\n";
    fout << "\n";
    fout << "      ScannerTransEntry() {};\n";
    fout << "      ScannerTransEntry(int state, char c)\n";
    fout << "      {\n";
    fout << "         _state = state;\n";
    fout << "         _c = c;\n";
    fout << "      }\n";
    fout << "      ScannerTransEntry(int state, char c, int fstate)\n";
    fout << "      {\n";
    fout << "         _state = state;\n";
    fout << "         _fstate = fstate;\n";
    fout << "         _c = c;\n";
    fout << "      }\n";
    fout << "\n";

    fout << "      public boolean equals(Object o)\n";
    fout << "      {\n";
    fout << "          if ( _state == ((ScannerTransEntry)o)._state && _c == ((ScannerTransEntry)o)._c )\n";
    fout << "             return true;\n";
    fout << "          return false;\n";
    fout << "      }\n";
    fout << "      public int getFState() { return _fstate; };\n";
    fout << "   }\n";
    fout << "\n";

    // Sub Class Scanner

    fout << "   class Scanner\n";
    fout << "   {\n";
    fout << "      Token _t;\n";
    fout << "      List<ScannerStateEntry> _stateList;\n";
    fout << "      List<ScannerTransEntry> _transList;\n";
    fout << "      Scanner()\n";
    fout << "      {\n";
    fout << "         _stateList = new ArrayList<ScannerStateEntry>();\n";
    fout << "         _transList = new ArrayList<ScannerTransEntry>();\n";
    fout << "      }\n";
    fout << "      Scanner(Token t)\n";
    fout << "      {\n";
    fout << "         _t = t;\n";
    fout << "         _stateList = new ArrayList<ScannerStateEntry>();\n";
    fout << "         _transList = new ArrayList<ScannerTransEntry>();\n";
    fout << "      }\n";
    fout << "\n";
    fout << "      Token getToken() { return _t; }\n";
    fout << "      void addState(ScannerStateEntry s)\n";
    fout << "      {\n";
    fout << "         _stateList.add(s);\n";
    fout << "      }\n";
    fout << "      void addTransition(ScannerTransEntry t)\n";
    fout << "      {\n";
    fout << "         _transList.add(t);\n";
    fout << "      }\n";

    fout << "      public boolean checkPattern(String pattern)\n";
    fout << "      {\n";
    fout << "         int state = 0;\n";
    fout << "         int i = 0;\n";
    fout << "         while ( i < _stateList.size() )\n";
    fout << "         {\n";
    fout << "            ScannerStateEntry pS = _stateList.get(i);\n";
    fout << "            if (pS.getType() == ScannerStateType.START || pS.getType() == ScannerStateType.ANY)\n";
    fout << "            {\n";
    fout << "               state = pS.getState();\n";
    fout << "            }\n";
    fout << "            i++;\n";
    fout << "         }\n";
    fout << "         i = 0;\n";

    fout << "         if ( _transList.contains ( new ScannerTransEntry(state, pattern.charAt(i) ) ) )\n";
    fout << "         {\n";
    fout << "            ScannerTransEntry pT = _transList.get( _transList.indexOf(new ScannerTransEntry(state, pattern.charAt(i))));\n";
    fout << "            while ( pT != null )\n";
    fout << "            {\n";
    fout << "               if (_stateList.contains(new ScannerStateEntry(pT.getFState())))\n";
    fout << "               {\n";
    fout << "                  ScannerStateEntry pS = _stateList.get( _stateList.indexOf(new ScannerStateEntry(pT.getFState()))); \n";
    fout << "                  if ( ( i == pattern.length()-1 ) && ( pS.getType() == ScannerStateType.FINAL || pS.getType() == ScannerStateType.ANY))\n";
    fout << "                  {\n";
    fout << "                     return true;\n";
    fout << "                  }\n";
    fout << "                  else\n";
    fout << "                  {\n";
    fout << "                     state = pT.getFState();\n";
    fout << "                  }\n";
    fout << "               }\n";
    fout << "               else\n";
    fout << "               {\n";
    fout << "                  return false;\n";
    fout << "               }\n";
    fout << "               i++;\n";
    fout << "               if ( i < pattern.length() && _transList.contains(new ScannerTransEntry(state, pattern.charAt(i))))\n";
    fout << "               {\n";
    fout << "                  pT = _transList.get( _transList.indexOf( new ScannerTransEntry(state, pattern.charAt(i))));\n";
    fout << "               }\n";
    fout << "               else\n";
    fout << "               {\n";
    fout << "                  return false;\n";
    fout << "               }\n";
    fout << "            }\n";
    fout << "         }\n";
    fout << "         return false;\n";
    fout << "      }\n";
    fout << "   };\n";
    fout << "\n";
    fout << "   List<Scanner> _scannerList;";
    fout << "\n";

    // Sub Class StackEntry

    fout << "   class StackEntry {\n";
    fout << "\n";
    fout << "      Symbol _symbol;\n";
    fout << "      int  _num;\n";
    fout << "      int  _state;\n";
    fout << "      String  _tval;\n";
    fout << "\n";
    fout << "      StackEntry() { _symbol = Symbol.NONE; }\n";
    fout << "      StackEntry(Symbol prod, int num, int state, String tval)\n";
    fout << "      {\n";
    fout << "         _symbol = prod;\n";
    fout << "         _num = num;\n";
    fout << "         _state = state;\n";
    fout << "         _tval = tval;\n";
    fout << "      };\n";
    fout << "\n";
    fout << "      public int getState() { return _state; }\n";
    fout << "      public Symbol getSymbol() { return _symbol; }\n";
    fout << "      public String getTval() { return _tval; }\n";
    fout << "   };\n";
    fout << "\n";
    fout << "   class ActionEntry {\n";
    fout << "\n";
    fout << "      int _state;\n";
    fout << "      Token _token;\n";
    fout << "      Action _action;\n";
    fout << "      int _num;	\n";
    fout << "\n";
    fout << "      ActionEntry() {}\n";
    fout << "      ActionEntry(int state, Token token) { _state = state; _token = token; }\n";
    fout << "      ActionEntry(int state, Token token, Action action, int num)\n";
    fout << "      {\n";
    fout << "         _state=state;\n";
    fout << "         _token=token;\n";
    fout << "         _action=action;\n";
    fout << "         _num=num;\n";
    fout << "      }\n";
    fout << "      public boolean equals(Object a)\n";
    fout << "      {\n";
    fout << "         if ( _state == ((ActionEntry)a)._state && _token == ((ActionEntry)a)._token )\n";
    fout << "            return true;\n";
    fout << "         return false;\n";
    fout << "      }\n";
    fout << "\n";
    fout << "      public Action getAction() { return _action; }\n";
    fout << "      public int getNum() { return _num; }\n";
    fout << "\n";
    fout << "   };\n";
    fout << "\n";
    fout << "   List<ActionEntry> _actionMap;\n";
    fout << "\n";
    fout << "   class JumpEntry {\n";
    fout << "\n";
    fout << " 	   int _state;\n";
    fout << "	   Production _prod;\n";
    fout << "	   int _fstate;	\n";
    fout << "\n";
    fout << "	   JumpEntry() {}\n";
    fout << "	   JumpEntry(int state, Production prod) { _state = state; _prod = prod; }\n";
    fout << "	   JumpEntry(int state, Production prod, int fstate) { _state = state; _prod = prod; _fstate = fstate; }\n";
    fout << "	   public boolean equals(Object j)\n";
    fout << "      {\n";
    fout << "         if ( _state == ((JumpEntry)j)._state && _prod == ((JumpEntry)j)._prod )\n";
    fout << "            return true;\n";
    fout << "         return false;\n";
    fout << "      };\n";
    fout << "\n";
    fout << "      public int getFState() { return _fstate; }\n";
    fout << "\n";
    fout << "   }\n";
    fout << "\n";
    fout << "   List<JumpEntry> _jumpMap;\n";
    fout << "\n";
    fout << "   class ProdEntry {\n";
    fout << "\n";
    fout << "	   int _id;\n";
    fout << "	   Production _prod;\n";
    fout << "	   int _numSymbol;\n";
    fout << "\n";
    fout << "	   ProdEntry() {};\n";
    fout << "	   ProdEntry(int id) { _id = id; }\n";
    fout << "	   ProdEntry(int id, Production prod, int numSymbol)\n";
    fout << "      {\n";
    fout << "         _id = id;\n";
    fout << "         _prod = prod;\n";
    fout << "         _numSymbol = numSymbol;\n";
    fout << "      }\n";
    fout << "      public boolean equals(Object p)\n";
    fout << "      {\n";
    fout << "         if ( _id == ((ProdEntry)p)._id )\n";
    fout << "            return true;\n";
    fout << "         return false;\n";
    fout << "      };\n";

    fout << "\n";
    fout << "      public int getId() { return _id; }\n";
    fout << "      public Production getProd() { return _prod; }\n";
    fout << "      int getNumSymbol() { return _numSymbol; }\n";
    fout << "\n";
    fout << "   }\n";
    fout << "\n";
    fout << "   List<ProdEntry> _prodInfo;\n";
    fout << "\n";
    fout << "   boolean isSepIgnore(char c)\n";
    fout << "   {\n";
    
    Chain *pSep;
    
    pSep = _sepignoreList.First();
    
    while (pSep)
    {
	
	fout << "      if (c == " << *pSep << ") return true;\n";
	pSep = _sepignoreList.Next();
    }
    fout << "      return false;\n";
    fout << "   }\n";


    fout << "   boolean isSepSign(char c)\n";
    fout << "   {\n";
    
    pSep = _sepsignList.First();
    
    while (pSep)
    {
	
	fout << "   if (c == " << *pSep << ") return true;\n";
	pSep = _sepsignList.Next();
    }
    fout << "      return false;\n";
    fout << "   }\n";


    fout << "   boolean shiftToken() throws Exception\n";
    fout << "   {\n";    
    fout << "      int i=0;\n";
    fout << "      char c;\n";
    fout << "      while ( isSepIgnore(c = nextChar()) && ! _isReserved );\n";
    fout << "      if ( _isReserved )\n";
    fout << "      {\n";
    fout << "         _token = _reservedToken;\n";
    fout << "         _isReserved = false;\n";
    fout << "         return true;\n";
    fout << "      }\n";

    fout << "      if (c == 0)\n";
    fout << "      {\n";
    fout << "         _token = Token.ENDTOKEN;\n";
    fout << "         return true;\n";
    fout << "      }\n";
    
    fout << "      if (isSepSign(c))\n";
    fout << "      {\n";
    fout << "         _tokenVal[i]=c;\n";
    fout << "          i++;\n";
    fout << "      }\n";
    fout << "      else\n";
    fout << "      {\n";
    fout << "         while (c != 0 && ! isSepIgnore(c) && ! ( isSepSign(c) && i>0 ) )\n";
    fout << "         {\n";
    fout << "            _tokenVal[i]=c;\n";
    fout << "            i++;\n";
    fout << "            c = nextChar();\n";
    fout << "         }\n"; 
    fout << "         if (isSepSign(c)) backChar();\n";
    fout << "      }\n";
    fout << "      _tokenVal[i]=0;\n";
    fout << "      _tokenLen=i;\n";
    fout << "      int j=0;\n";
    fout << "      Scanner pS;\n";

    fout << "      while (j < _scannerList.size() )\n";
    fout << "      {\n";
    fout << "         pS=_scannerList.get(j);\n";
    fout << "         if (pS.checkPattern(new String(_tokenVal, 0, i)))\n";
    fout << "         {\n";
    fout << "            _token = pS.getToken();\n";
    fout << "            return true;\n";
    fout << "         }\n";
    fout << "         j++;\n";
    fout << "      }\n";
    fout << "      return false;\n";
    fout << "   }\n";

    fout << "   public void parse() throws Exception\n";
    fout << "   {\n";
    fout << "      Stack<StackEntry> s = new Stack<StackEntry>();\n";
    fout << "      StackEntry se = new StackEntry(Symbol.NONE, 0, 0, new String());\n";
    fout << "      s.push(se);    \n";
    fout << "      if ( shiftToken() == false )\n";
    fout << "      {\n";
    fout << "         throw new Exception(\"Invalid token <\" + new String(_tokenVal, 0, _tokenLen) + \">.\");\n";
    fout << "      }\n";
    fout << "      while ( true )\n";
    fout << "      {\n";
    fout << "         int num=0;\n";
    fout << "         if ( getAction(s.peek().getState(), _token) )\n";
    fout << "         {\n";
    fout << "            if (_actAction == Action.SHIFT )\n";
    fout << "            {\n";
    fout << "               StackEntry ste = new StackEntry(Symbol.TOKEN, _token.ordinal(), _actNum, new String(_tokenVal, 0, _tokenLen));\n";
    fout << "               s.push(ste);\n";

    fout << "               if ( shiftToken() == false )\n";
    fout << "               {\n";    
    fout << "                  throw new Exception(\"Invalid token <\" + new String(_tokenVal, 0, _tokenLen) + \">.\");\n";
    fout << "               }\n";
    fout << "            }\n";
    fout << "            else if ( _actAction == Action.REDUCE)\n";
    fout << "            {\n";
    fout << "               _tokenList.clear();\n";
   
    fout << "               ProdEntry pPE = null;\n";
    fout << "               if (  _prodInfo.contains( new ProdEntry(_actNum) ) )\n";
    fout << "               {\n";
    fout << "                  pPE = _prodInfo.get( _prodInfo.indexOf( new ProdEntry(_actNum) ) );\n";
    fout << "               }\n";

    fout << "               for (int i=0; i<pPE.getNumSymbol();i++)\n";
    fout << "               {\n";
    fout << "                  StackEntry ste = s.pop();\n";
    fout << "                  if (ste.getSymbol() == Symbol.TOKEN)\n";
    fout << "                     _tokenList.add(ste.getTval());\n";
    fout << "               }\n";
    fout << "               if (getJump(s.peek().getState(), pPE.getProd()))\n";
    fout << "               {\n";
    fout << "                  StackEntry ste = new StackEntry(Symbol.PROD, pPE.getId(), _actFState, new String(_tokenVal, 0, _tokenLen));\n";
    fout << "                  s.push(ste);\n";
    fout << "               }\n";
    fout << "               else\n";
    fout << "               {\n";
    fout << "                  throw new Exception(\"Cannot reduce after token <\" + new String(_tokenVal, 0, _tokenLen) + \">.\");\n";
    fout << "               }\n";
    fout << "               switch (_actNum)\n";
    fout << "               {\n";

    Production *pP;

    pP = _productionSet.First();
    while (pP)
    {
	if ( pP->getId() != 0 && pP->getAction() )
	{
	    fout << "                  case " << pP->getId() << ":\n" 
		 << "                     " << pP->getAction() << "();\n"
		 << "                     break;\n";	
	}
	    pP = _productionSet.Next();

    }

    fout << "               }\n";
    fout << "               _tokenList.clear();\n";
    fout << "            }\n";
    fout << "            else if ( _actAction ==  Action.ACCEPT )\n";
    fout << "            {\n";

    pP = _productionSet.First();
    while (pP)
    {
	if ( pP->getId() == 0 && pP->getAction() )
	{ 
	    fout << "                  " << pP->getAction() << "();\n";
	}
	pP = _productionSet.Next();
    }


    fout << "               return;\n";
    fout << "            }\n";
    fout << "         }\n";
    fout << "         else\n";
    fout << "         {\n";
    fout << "            throw new Exception(\"Parse error at token <\" + new String(_tokenVal, 0, _tokenLen) + \">.\");\n";
    fout << "         }\n";
    fout << "      }\n";
    fout << "   }\n";
    fout << "\n";
    fout << "   boolean getAction(int state, Token token)\n";
    fout << "   {\n";
    fout << "      ActionEntry pA = null;\n";
    fout << "      if (  _actionMap.contains( new ActionEntry(state, token)))\n";
    fout << "      {\n";
    fout << "         pA = _actionMap.get( _actionMap.indexOf( new  ActionEntry(state, token)));\n";
    fout << "      }\n";
    fout << "      if (pA != null )\n";
    fout << "      {\n";
    fout << "         _actAction = pA.getAction();\n";
    fout << "	      _actNum = pA.getNum();\n";
    fout << "	      return true;\n";
    fout << "      }\n";
    fout << "      else\n";
    fout << "      {\n";
    fout << "         return false;\n";
    fout << "      }\n";
    fout << "   }\n";
    fout << "\n";
    fout << "   boolean getJump(int state, Production prod)\n";
    fout << "   {\n";
    fout << "      JumpEntry pJ = null;\n";
    fout << "      if (  _jumpMap.contains( new JumpEntry(state, prod)))\n";
    fout << "      {\n";
    fout << "         pJ = _jumpMap.get( _jumpMap.indexOf( new JumpEntry(state, prod)));\n";
    fout << "      }\n";
    fout << "      if (pJ != null)\n";
    fout << "      {\n";
    fout << "         _actFState = pJ.getFState();\n";
    fout << "	      return true;\n";
    fout << "      }\n";
    fout << "      else\n";
    fout << "      {\n";
    fout << "	      return false;\n";
    fout << "      }\n";
    fout << "   }\n";
    fout << "\n";


    fout << "   void loadScanner()\n";
    fout << "   {\n";
    fout << "\n";



    int sid=0;    

    for (int i = 1; i<=_terminalSet.Size(); i++)
    {

	Terminal *pTerm = _terminalSet.First();
	while (pTerm && pTerm->getNum() != i)
	{
	    pTerm = _terminalSet.Next();
	}
	if (pTerm)
	{

	    Worm w(pTerm->getRegExp(), pTerm->getName());
	 
	    w.makeOptimalDEA();
	    
	    Chain scanner = "s" + Chain(sid);
	    
	    fout << "      Scanner " << scanner << " = new Scanner(Token." << pTerm->getName() << ");\n";
	    
	    FSMState *pS = w.getStateTable().First();	
	    while (pS)
	    {   
		
		fout << "      " << scanner << ".addState(new ScannerStateEntry("
		     << pS->Num() << " ,";
		
		switch (pS->Type())
		{
		case START:
		    fout << "ScannerStateType.START));\n";
		    break;
		case FINAL:
		    fout << "ScannerStateType.FINAL));\n";	
		    break;
		case ANY:
		    fout << "ScannerStateType.ANY));\n";	
		    break;
		case NONE:
		    fout << "ScannerStateType.INTERMEDIATE));\n";
		    break;
		}
		
		pS = w.getStateTable().Next();
	    }
	    
	    FSMTransition *pT = w.getTransitionTable().First();
	    
	    while (pT)
	    {
		
		fout << "      " << scanner << ".addTransition(new ScannerTransEntry("
		     << pT->Source() << " ,'" << pT->Sign() << "' ," << pT->Target() << "));\n";
		
		pT = w.getTransitionTable().Next();
	    }
	    
	    fout << "      _scannerList.add(" << scanner << ");\n";
	    fout << "\n";	
	    
	    sid++;
	}
	
	
    }

    fout << "   }\n";


    int mcount = 0;
    fout << "   void loadParser" + Chain(mcount) + "()\n";
    fout << "   {\n";
    int lcount=0;

    ParseTableEntry *pPTE = _parseTable.First();
    while (pPTE)
    {
	Chain token = pPTE->getToken();
	if ( token == Chain("$") )
	    token = Chain("ENDTOKEN");
	
	switch (pPTE->getAction())
	{
	case ParseTableEntry::SHIFT:
	    fout << "      _actionMap.add(new ActionEntry("
		 << pPTE->getState() << ", Token." << token 
		 << ", Action.SHIFT, " << pPTE->getArg() << "));\n";
	    break;
	case ParseTableEntry::REDUCE:
	    fout << "      _actionMap.add(new ActionEntry("
		 << pPTE->getState() << ", Token." << token
		 << ", Action.REDUCE, " << pPTE->getArg() << "));\n";
	    break;
	case ParseTableEntry::JUMP:
	    fout << "      _jumpMap.add(new JumpEntry("
		 << pPTE->getState() << ", Production." << token
		 << ", " << pPTE->getArg() << "));\n";
	    break;
	case ParseTableEntry::ACCEPT:
	    fout << "      _actionMap.add(new ActionEntry("
		 << pPTE->getState() << ", Token." << token
		 << ", Action.ACCEPT, " << pPTE->getArg() << "));\n";
	    break;
	}
	lcount++;
	pPTE = _parseTable.Next();

	if ( pPTE && lcount == LOADCOUNT )
	{
	    mcount++;
	    lcount=0;
	    fout << "   }\n";
	    fout << "   void loadParser" + Chain(mcount) + "()\n";
	    fout << "   {\n";
	}
    }
    fout << "   }\n";

    fout << "   " <<  _parserName << "()\n";
    fout << "   {\n";
    fout << "      _prodInfo = new ArrayList<ProdEntry>();\n";
    fout << "      _scannerList = new ArrayList<Scanner>();\n";
    fout << "      _actionMap = new ArrayList<ActionEntry>();\n";
    fout << "      _jumpMap = new ArrayList<JumpEntry>();\n";

    fout << "      loadScanner();\n";

    for ( int i=0; i<=mcount; i++)
    {
	fout << "      loadParser" + Chain(i) + "();\n";	
    }

    pP = _productionSet.First();
    while (pP)
    {

	fout << "      _prodInfo.add(new ProdEntry("
	     << pP->getId() << ", Production." << pP->getName() << ", "
	     << pP->getMaxPos() << "));\n";	

	pP = _productionSet.Next();
    }
    
    fout << "      _isReserved = false;\n";

    fout << "   }\n";
    fout << "};\n";

    fout.close();
}

void Dragon::rotate()
{
    
    if ( _rot % 8 == 0)
	cout << "|\r";
    else if ( _rot % 8 == 1)    
	cout << "/\r";
    else if ( _rot % 8 == 2)    
	cout << "-\r";
    else if ( _rot % 8 == 3)    
	cout << "\\\r";
    else if ( _rot % 8 == 4)    
	cout << "|\r";
    else if ( _rot % 8 == 5)    
	cout << "/\r";
    else if ( _rot % 8 == 6)    
	cout << "-\r";
    else if ( _rot % 8 == 7)    
	cout << "\\\r";
    cout.flush();
    _rot++;

}



