www.pudn.com > calc5.zip > Parse.cpp


//------------------------------------ 
//	parse.cpp 
//	(c) Bartosz Milewski, 1994, 98 
//------------------------------------ 
 
#include "parse.h" 
#include "scan.h" 
#include "tree.h" 
#include "symtab.h" 
#include "funtab.h" 
#include "store.h" 
#include "params.h" 
 
#include  
#include  
#include  
#include  
using std::cerr; 
using std::endl; 
 
class Syntax {}; 
 
Parser::Parser (Scanner & scanner,  
		Store & store, 
		Function::Table & funTab, 
		SymbolTable & symTab ) 
: _scanner (scanner),  
  _pTree (0),  
  _status (stOk),  
  _funTab (funTab), 
  _store (store), 
  _symTab (symTab) 
{ 
} 
 
Status Parser::Parse () 
{ 
	try 
	{ 
		// Everything is an expression 
		_pTree = Expr (); 
		if (!_scanner.IsDone ()) 
			_status = stError; 
	} 
	catch (Syntax) 
	{ 
		_status = stError; 
	} 
	return _status; 
} 
 
double Parser::Calculate () const 
{ 
	assert (_status == stOk); 
	assert (_pTree.get () != 0); 
	return _pTree->Calc (); 
} 
 
auto_ptr Parser::Expr () 
{ 
	// Parse a term 
	auto_ptr pNode = Term (); 
 
	EToken token = _scanner.Token (); 
	if (token == tPlus || token == tMinus) 
	{ 
		// Expr := Term { ('+' | '-') Term } 
		auto_ptr pMultiNode (new SumNode (pNode)); 
		do 
		{ 
			_scanner.Accept (); 
			auto_ptr pRight = Term (); 
			pMultiNode->AddChild (pRight, (token == tPlus)); 
			token = _scanner.Token (); 
		} while (token == tPlus || token == tMinus); 
		// with member template support 
		// pNode = pMultiNode; 
		pNode = up_cast (pMultiNode); 
	} 
	else if (token == tAssign) 
	{ 
		_scanner.Accept (); 
		// Expr := Term = Expr 
		auto_ptr pRight = Expr (); 
		// provided the Term is an lvalue 
		if (pNode->IsLvalue ()) 
		{ 
			// Assignment node 
			pNode = auto_ptr (new AssignNode (pNode, pRight)); 
		} 
		else 
		{ 
			_status = stError; 
			pNode = Expr (); 
		} 
	} 
	// otherwise Expr := Term 
	return pNode; 
} 
 
auto_ptr Parser::Term () 
{ 
	auto_ptr pNode = Factor (); 
 
	EToken token = _scanner.Token (); 
	if (token == tMult || token == tDivide) 
	{ 
		// Term := Factor { ('*' | '/') Factor } 
		auto_ptr pMultiNode (new ProductNode (pNode)); 
		do 
		{ 
			_scanner.Accept (); 
			auto_ptr pRight = Factor (); 
			pMultiNode->AddChild (pRight, (token == tMult)); 
			token = _scanner.Token (); 
		} while (token == tMult || token == tDivide); 
		// with member template support 
		// pNode = pMultiNode; 
		pNode = up_cast (pMultiNode); 
	} 
	// otherwise Term := Factor 
	return pNode; 
} 
 
auto_ptr Parser::Factor () 
{ 
	auto_ptr pNode; 
	EToken token = _scanner.Token (); 
 
	if (token == tLParen) 
	{ 
		_scanner.Accept (); // accept '(' 
		pNode = Expr (); 
 
		if (_scanner.Token () == tRParen) 
			_scanner.Accept (); // accept ')' 
		else 
			throw Syntax (); 
	} 
	else if (token == tNumber) 
	{ 
		pNode = auto_ptr (new NumNode (_scanner.Number ())); 
		_scanner.Accept (); 
	} 
	else if (token == tIdent) 
	{ 
		char strSymbol [maxSymLen + 1]; 
		// copy the symbol into strSymbol 
		int lenSym = _scanner.GetSymbolName (strSymbol, maxSymLen + 1); 
		int id = _symTab.Find (strSymbol); 
		_scanner.Accept (); 
		if (_scanner.Token () == tLParen) // function call 
		{ 
			_scanner.Accept (); // accept '(' 
			pNode = Expr (); 
			if (_scanner.Token () == tRParen) 
				_scanner.Accept (); // accept ')' 
			else 
				throw Syntax (); 
			if (id != SymbolTable::idNotFound && id < _funTab.Size ()) 
			{ 
				pNode = auto_ptr ( 
					new FunNode (_funTab.GetFun (id), pNode)); 
			} 
			else 
			{ 
				cerr << "Unknown function \""; 
				cerr << strSymbol << "\"" << endl; 
				throw Syntax (); 
			} 
		} 
		else 
		{ 
			// Factor := Ident 
			if (id == SymbolTable::idNotFound) 
			{ 
				id = _symTab.ForceAdd (strSymbol); 
			} 
			pNode = auto_ptr (new VarNode (id, _store)); 
		} 
	} 
	else if (token == tMinus) // unary minus 
	{ 
		_scanner.Accept (); // accept minus 
		pNode = auto_ptr (new UMinusNode (Factor ())); 
	} 
	else 
	{ 
		_scanner.Accept (); 
		throw Syntax (); 
	} 
	return pNode; 
}