Click here to Skip to main content
15,885,875 members
Articles / Programming Languages / C++

Tokenizer and analyzer package supporting precedence prioritized rules

Rate me:
Please Sign up or sign in to vote.
5.00/5 (4 votes)
1 Jan 20023 min read 181.5K   2.8K   54  
A library allowing you to conveniently build a custom tokenizer and analyzer supporting precedence priorized rules
/*********************************************************************
	Copyright 2001 Alexander Berthold, alexander-berthold@web.de.

    -- This file is part of ctkCommon --

    "ctkCommon" 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.

    "ctkCommon" 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 "ctkCommon"; 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.
    ---------------------------------------------------------------

Class:      ctkMisc
Author:     Alexander Berthold
Copyright:  Alexander Berthold
Date:       2001/06/05
Version:	0.1.01
Purpose:    Provides some helper methods used by cxTokenizer
			and cxAnalyzer.


Version history:

	-	2001/06/05
		Current source labeled version 0.1.01
		
*********************************************************************/

// ctkMisc.h: interface for the ctkMisc class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_CTKMISC_H__02DB3E9E_00AB_4FC7_9F58_E01EECC31A91__INCLUDED_)
#define AFX_CTKMISC_H__02DB3E9E_00AB_4FC7_9F58_E01EECC31A91__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "tkCommon.h"

class ctkMisc  
{
// Purely static helper class
public:
	static bool			fStripOffBraces(std::tstring& strTarget)
		{
		int		nLen = (int)strTarget.length();
		
		if(nLen<2)
			return false;

		if(nLen==2)
			return false;

		if(strTarget[0]!='{' || strTarget[nLen-1]!='}')
			return false;

		strTarget	=strTarget.substr(1,strTarget.length()-2);
		return true;
		}

	static std::tstring strStripOffSpaces(const std::tstring& strTarget)
		{
		std::tstring::const_iterator sit;
		std::tstring::const_reverse_iterator eit;
		std::tstring res;
		int		nPos = 0;
		for(sit=strTarget.begin();sit!=strTarget.end();sit++)
			if( (*sit)!=' ' && (*sit)!='\t' && (*sit)!='\n' && (*sit)!='\r') break;
		if(sit==strTarget.end()) return std::tstring();
		for(eit=strTarget.rbegin();eit!=strTarget.rend();eit++)
			if( (*eit)!=' ' && (*eit)!='\t' && (*eit)!='\n' && (*eit)!='\r')
				{ eit--; break; }
		res.insert(res.begin(),&(*sit),&(*eit));
		return res;
		}

	static std::tstring	strParseEscapeCharacters(const std::tstring& strSource)
		{
		std::tstring	strDest;
		int				nLen = (int)strSource.length();
		int				i;
		bool			fEscapeNext = false;

		for(i=0;i<nLen;i++)
			{
			TCHAR		tcTemp = strSource[i];

			if(fEscapeNext)
				{
				bool	fOk = false;
				if(tcTemp==_T('n'))
					fOk = true, strDest+="\n";
				if(tcTemp==_T('r'))
					fOk = true, strDest+="\r";
				if(tcTemp==_T('\\'))
					fOk = true, strDest+="\\";
				if(tcTemp==_T('x') && ((i+2)<nLen))
					{
					TCHAR		szHex[3];
					szHex[0]	=strSource[i+1];
					szHex[1]	=strSource[i+2];
					szHex[2]	='\0';
					strDest+=(TCHAR)(_tcstoul(szHex,NULL,16));
					fOk = true;
					}
				if(!fOk)
					strDest+=tcTemp;
				
				fEscapeNext = false;
				continue;
				}

			if(tcTemp=='\\')
				{
				fEscapeNext = true;
				continue;
				}

			strDest+=tcTemp;
			}

		return strDest;
		}

	static std::tstring	strEscapeBraces(const std::tstring& strSource)
		{
		std::tstring	strDest;
		int				nLen = (int)strSource.length();
		int				i;
		TCHAR			tcBefore,tcTemp;
		bool			fSkip;

		if(nLen==0)
			return strSource;

		tcBefore	=_T('\0');
		for(i=0;i<nLen;i++)
			{
			fSkip		=false;
			tcTemp		=strSource[i];

			if(tcBefore!=_T('\\') && tcTemp==_T('{'))
				strDest+=_T("{{"), fSkip=true;

			if(tcBefore!=_T('\\') && tcTemp==_T('}'))
				strDest+=_T("}}"), fSkip=true;

			if(!fSkip)
				strDest+=tcTemp;

			tcBefore	=tcTemp;
			}

		return strDest;
		}

	static std::tstring	strUnescapeBraces(const std::tstring& strSource)
		{
		std::tstring	strDest;
		int			nLen = (int)strSource.length();
		int			i;
		TCHAR		tcTemp;
		bool		fSkip;

		if(nLen==0)
			return strSource;

		for(i=0;i<nLen-1;i++)
			{
			fSkip		=false;
			tcTemp		=strSource[i];
			if(tcTemp=='\\' && strSource[i+1]=='{')
				{
				strDest	+=_T("\\{");
				fSkip=true;
				i++;
				}
			if(tcTemp=='\\' && strSource[i+1]=='}')
				{
				strDest	+=_T("\\}");
				fSkip=true;
				i++;
				}
			if(!fSkip)
				strDest	+=tcTemp;
			}

		if(i<nLen)
			strDest+=strSource[i];

		return strDest;
		}
};

class	ctkExceptionBase
{
// Construction/Destruction
public:
	ctkExceptionBase(HRESULT hr, LPCTSTR lpszCause=NULL, DWORD dwData = 0)
       	{	m_hr=hr; m_dwData=dwData;
			if(lpszCause) 
				{
				m_pszCause = new TCHAR[_tcslen(lpszCause)+1];
				_tcscpy(m_pszCause,lpszCause);
				}
			else
				m_pszCause = NULL;
		};

	ctkExceptionBase(const ctkExceptionBase& other)
		{
		m_hr	=other.m_hr;
		m_dwData=other.m_dwData;
		if(other.m_pszCause)
			{
			m_pszCause = new TCHAR[_tcslen(other.m_pszCause)+1];
			_tcscpy(m_pszCause, other.m_pszCause);
			}
		else
			m_pszCause = NULL;
		}

	virtual ~ctkExceptionBase()
        { delete[] m_pszCause; };

// Attributes
protected:
	HRESULT			m_hr;
	TCHAR			*m_pszCause;
	DWORD			m_dwData;

// Operatoins
public:
	HRESULT		Error() const
		{ return m_hr; };
	LPCTSTR		ErrorString() const
		{ return m_pszCause; };
    LPCTSTR     ErrorCode() const
        { return LookupError(m_hr)->lpszDesc; };
	void		SetErrorString(LPCTSTR lpszString)
		{ delete[] m_pszCause;
		  if(lpszString)
			  {
			  m_pszCause = new TCHAR[_tcslen(lpszString)+1];
			  _tcscpy(m_pszCause, lpszString);
			  }
		  else
			  m_pszCause = NULL;
		};
	DWORD		GetData() const 
		{ return m_dwData; };
	void		SetData(DWORD dwData)
		{ m_dwData = dwData; };
};

template<class _value_type, class _Pr >
class key_comp : public std::binary_function<const _value_type&,const _value_type::first_type&, bool>
	{
	public:
		typedef _value_type first_argument_type;
		typedef _value_type::first_type second_argument_type;
		_Pr		pred;

		bool	operator() (const _value_type& e1, const _value_type::first_type& e2) const
			{
			return pred(e1.first,e2 );
			}
	};

template<class _value_type, class _Pr >
class key_comp_rev : public std::binary_function<const _value_type::first_type&,const _value_type&, bool>
	{
	public:
		typedef _value_type::first_type first_argument_type;
		typedef _value_type second_argument_type;
		_Pr		pred;

		bool	operator() (const _value_type::first_type& e1, const _value_type& e2) const
			{
			return pred(e1,e2.first );
			}
	};

template<class _value_type, class _Pr >
class sort_comp : public std::binary_function<const _value_type&,const _value_type&, bool>
	{
	public:
		typedef _value_type first_argument_type;
		typedef _value_type second_argument_type;
		_Pr		pred;

		bool	operator() (const _value_type& e1, const _value_type& e2) const
			{
			return pred(e1.first, e2.first );
			}
	};

template<class _K, class _Ty, class _Pr = std::less<_K> >
class	ctkMultiMap : public std::vector< std::pair<_K,_Ty> >
{
// Construction/Destruction
public:
	ctkMultiMap() 
	: eState(state_initialization)
	  {};
	virtual ~ctkMultiMap() {};

// Typedefs
public:
	typedef std::pair<_K,_Ty>		value_type;
	typedef _K						key_type;
	typedef _Ty						data_type;
	typedef _Ty						mapped_type;
	typedef _Pr						key_compare;
	enum estate 
		{
		state_initialization,
		state_query
		};

// Attributes
protected:
	key_comp<value_type, _Pr>		k;
	key_comp_rev<value_type, _Pr>	kr;
	sort_comp<value_type, _Pr>		s;
	estate							eState;

// Operations
public:
	// Sets or resets status to initialization stage (clears all content)
	void	vSetInitStage()			{ clear(); eState = state_initialization; };
	// Sets status to query stage
	void	vSetQueryStage();

// "Multimap" operations multimap
public:
	void				insert(const value_type& _Val);
	void				insert(iterator /*where*/, const value_type& _Val) { insert(_Val); };

	void				erase(iterator) { ASSERT(FALSE); };
	void				erase(iterator,iterator) { ASSERT(FALSE); };
	void				erase(const key_type& key) { ASSERT(FALSE); };

	iterator			find(const key_type& key);
	const_iterator		find(const key_type& key) const;
};

template<class _K, class _Ty, class _Pr>
void ctkMultiMap<_K,_Ty,_Pr>::vSetQueryStage()
	{
	eState = state_query;
	if(empty()) return;
	std::stable_sort(begin(),end(),s);
	}

template<class _K, class _Ty, class _Pr>
void ctkMultiMap<_K,_Ty,_Pr>::insert(const value_type& _Val)
	{
	ASSERT(eState==state_initialization);
	push_back(_Val);
	}

template<class _K, class _Ty, class _Pr>
ctkMultiMap<_K,_Ty,_Pr>::iterator ctkMultiMap<_K,_Ty,_Pr>::find(const key_type& key)
	{
	if(eState==state_initialization)
		{
		if(empty()) return end();
		for(iterator it=begin();it!=end();it++)
			{
			if( !k( (*it), key ) && !kr( key, (*it) ) )
				return it;
			}
		return end();
		}
	else
		{
		if(empty()) return end();
		ASSERT(eState==state_query);
		iterator it = std::lower_bound(begin(),end(),key,k );
		if(it!=end() && it->first!=key)
			return end();
		else
			return it;
		}
	}

template<class _K, class _Ty, class _Pr>
ctkMultiMap<_K,_Ty,_Pr>::const_iterator ctkMultiMap<_K,_Ty,_Pr>::find(const key_type& key) const
	{
	if(eState==state_initialization)
		{
		if(empty()) return end();
		for(const_iterator it=begin();it!=end();it++)
			{
			if( !k( (*it), key ) && !kr( key, (*it) ) )
				return it;
			}
		return end();
		}
	else
		{
		ASSERT(eState==state_query);
		if(empty()) return end();
		return std::lower_bound(begin(),end(),key,k );
		}
	}

template<class _K, class _Ty>
class	ctkTableMap : public std::vector< std::pair<_K,_Ty> >
{
// Construction/Destruction
public:
	ctkTableMap()
		{
		ASSERT(sizeof(_K)==1);
		vSetInitStage();
		};
	virtual ~ctkTableMap() {};

// Typedefs
public:
	typedef std::pair<_K,_Ty>		value_type;
	typedef _K						key_type;
	typedef _Ty						data_type;
	typedef _Ty						mapped_type;

// Operations
public:
	// Sets or resets status to initialization stage (clears all content)
	void	vSetInitStage();
	// Sets status to query stage
	void	vSetQueryStage()		{};

// "Multimap" operations multimap
public:
	void				insert(const value_type& _Val);
	void				insert(iterator /*where*/, const value_type& _Val) { insert(_Val); };

	void				erase(iterator) { ASSERT(FALSE); };
	void				erase(iterator,iterator) { ASSERT(FALSE); };
	void				erase(const key_type& key) { ASSERT(FALSE); };

	iterator			find(const key_type& key);
	const_iterator		find(const key_type& key) const;
};

template<class _K, class _Ty>
void ctkTableMap<_K,_Ty>::vSetInitStage()
	{ 
	int bound = 1<<(sizeof(_K)*8);
	clear(); 
	resize(bound); 
	for(iterator it=begin();it!=end();it++) it->first = bound-1;
	}

template<class _K, class _Ty>
void ctkTableMap<_K,_Ty>::insert(const value_type& val)
	{
	if(val.first==0)
		push_back(val);
	else
		{
		ASSERT(at(val.first).first==-1 );
		at(val.first) = val;
		}
	}

template<class _K, class _Ty>
ctkTableMap<_K,_Ty>::iterator ctkTableMap<_K,_Ty>::find(const key_type& key)
	{
	if( key==0 )
		return begin()+(1<<(sizeof(_K)*8));

	if( at(key).first==-1 )
		return end();
	return begin()+key;
	}

template<class _K, class _Ty>
ctkTableMap<_K,_Ty>::const_iterator ctkTableMap<_K,_Ty>::find(const key_type& key) const
	{
	if( at(key).first==-1 )
		return end();
	return begin()+key;
	}

#endif // !defined(AFX_CTKMISC_H__02DB3E9E_00AB_4FC7_9F58_E01EECC31A91__INCLUDED_)

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions