/*********************************************************************
Copyright (C) 2001 by
Alexander Berthold, alexander-berthold@web.de.
Hoegestr. 54
79108 Freiburg i. Breisgau
Germany
-- This file is part of cxAnalyzer --
"cxAnalyzer" is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or any later version.
"cxAnalyzer" 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with "cxAnalyzer"; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
---------------------------------------------------------------
If you find any bugs or if you make other corrections/
enhancements, i'd appreciate if you'd let me know about
that. My email is
alexander-berthold@web.de
If you share this code, do not remove this text.
---------------------------------------------------------------
*********************************************************************/
// cxAnalyzerTree.cpp: implementation of the cxAnalyzerTree class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "cxAnalyzerException.h"
#include "cxaToken.h"
#include "cxAnalyzerTypeMap.h"
#include "cxAnalyzerExpression.h"
#include "cxAnalyzerTree.h"
#include "cxaParseTree.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#ifndef _DEBUG
#undef TRACE
#define TRACE printf
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
cxAnalyzerTree::cxAnalyzerTree()
{
m_nBeginTransCnt=0;
}
cxAnalyzerTree::~cxAnalyzerTree()
{
}
//////////////////////////////////////////////////////////////////////
// Operations
//////////////////////////////////////////////////////////////////////
void cxAnalyzerTree::vBeginTrans()
{
m_nBeginTransCnt++;
}
void cxAnalyzerTree::vCommitTrans()
{
if(m_nBeginTransCnt>0)
m_nBeginTransCnt--;
else
m_stkTrans.pop();
}
void cxAnalyzerTree::vRollbackTrans()
{
if(m_nBeginTransCnt>0)
m_nBeginTransCnt--;
else
{
int nRBPos = m_stkTrans.top();
log_vec_type::iterator it=m_vecLogElems.begin();
it +=nRBPos;
if(it!=m_vecLogElems.end())
m_vecLogElems.erase(it,m_vecLogElems.end());
m_stkTrans.pop();
}
}
void cxAnalyzerTree::vCleanUp()
{
// Replace le_end_rule,le_begin_rule(NULL),le_token,le_end_rule
// with le_token,le_end_rule
int nSize = m_vecLogElems.size();
int i;
for(i=0;i<(nSize-3);i++)
{
__log_elem &le0 = m_vecLogElems[i];
__log_elem &le1 = m_vecLogElems[i+1];
__log_elem &le2 = m_vecLogElems[i+2];
__log_elem &le3 = m_vecLogElems[i+3];
if(le0.nType==le_end_rule)
{
if(le1.nType==le_begin_rule)
{
if(le1.pLogData==NULL)
{
ASSERT(le2.nType==le_token);
ASSERT(le2.pLogData!=NULL);
ASSERT(le3.nType==le_end_rule);
le0.nType =le_token;
le0.pLogData=NULL;
le1.nType =le_token;
le1.pLogData=NULL;
i +=4;
continue;
}
else
{
i+=2;
continue;
}
}
}
}
}
void cxAnalyzerTree::vLog(int nType, int nAtmType, int nIDValue, const void *pLogData)
{
__log_elem le;
le.nType =nType;
le.nAtmType =nAtmType;
le.nIDValue =nIDValue;
le.pLogData =pLogData;
while(m_nBeginTransCnt>0)
{
m_stkTrans.push(m_vecLogElems.size());
m_nBeginTransCnt--;
}
m_vecLogElems.push_back(le);
}
void cxAnalyzerTree::vBeginRule(int nAtmType, int nIDValue, const cxAnalyzerExpression* pExpr)
{
vLog(le_begin_rule,nAtmType,nIDValue,pExpr);
}
void cxAnalyzerTree::vEndRule()
{
vLog(le_end_rule,ATM_ID_INVALID,-1,NULL);
}
void cxAnalyzerTree::vLogToken(const cxaToken* patToken)
{
/* if(patToken==NULL)
return;*/
vLog(le_token,ATM_ID_INVALID,-1,patToken);
}
void cxAnalyzerTree::vDumpLog()
{
// int nTemp = m_stkTrans.size();
ASSERT(m_stkTrans.empty());
log_vec_type::iterator it = m_vecLogElems.begin();
for(;it!=m_vecLogElems.end();it++)
{
__log_elem &el = (*it);
if(el.nType==le_begin_rule)
{
if(el.pLogData==NULL)
TRACE("<< RULE: NULL\n");
else
TRACE("<< RULE: %s\n",(*(*((const cxAnalyzerExpression*)el.pLogData)).m_pstrInitTemp).data());
}
if(el.nType==le_end_rule)
TRACE("RULE ENDS >>\n");
if(el.nType==le_token)
{
if(el.pLogData!=NULL)
TRACE("TOKEN: %s\n",((const cxaToken*)el.pLogData)->lpszTokenText);
else
TRACE("TOKEN: NULL\n");
}
}
}
cxaParseTree *cxAnalyzerTree::paptBuildTreeInternal()
{
ASSERT(m_stkTrans.empty());
cxaParseTree *papt = new cxaParseTree();
log_vec_type::iterator it = m_vecLogElems.begin();
// Clean up the structures
vCleanUp();
for(;it!=m_vecLogElems.end();it++)
{
__log_elem &el = (*it);
if(el.nType==le_begin_rule)
{
const cxAnalyzerExpression* paeTemp = ((const cxAnalyzerExpression*)el.pLogData);
int nPrecPrio = 32767, nIDValue = el.nIDValue;
bool fLB = false, fRB = false;
if(paeTemp!=NULL)
{
ASSERT(nIDValue==paeTemp->nGetIDValue());
nPrecPrio = paeTemp->nGetPrecPrio();
fLB = paeTemp->fIsLeftBound(paeTemp->nGetAtmType());
fRB = paeTemp->fIsRightBound(paeTemp->nGetAtmType());
}
papt->vBeginRule(el.nAtmType,nIDValue,nPrecPrio,fLB,fRB);
}
if(el.nType==le_end_rule)
papt->vEndRule();
if(el.nType==le_token)
{
papt->vToken((const cxaToken*)el.pLogData);
}
}
return papt;
}