ot_lex.cpp

来自「在手机操作系统symbina上使用的一个脚本扩展语言的代码实现,可以参考用于自己」· C++ 代码 · 共 861 行 · 第 1/2 页

CPP
861
字号
// OT_LEX.CPP
//
// Copyright (c) 1997-2000 Symbian Ltd. All rights reserved.

// Lexer for OPL
//
// Classes: COplLexerBase - The base class for OPL lexers
//          COplCalcLex - The lexer for the OPL based calculator   
//          COplModuleLexer - The lexer for the OPL module translator

#include "ot_std.h"
#include <f32file.h> // for TParse

////////////////////////////////////////////////////////
//
// TOplField
//
///////////////////////////////////////////////////////
TOplField::TOplField(TDevice aDevice, const TDesC& aName)
	: iDevice(aDevice), iName(aName)
//
// Sets up the members.
//
	{
	
	__ASSERT_ALWAYS(aDevice!=EBadDevice,Panic(EOpltBadLogicalDevice));
	}

/////////////////////////////////////////////////////////////////////////
//
// COplLexerBase - The base class for OPL lexers
//
/////////////////////////////////////////////////////////////////////////

EXPORT_C TOplToken COplLexerBase::LexL()
//
// Returns the next token from the input - the heart of it 
//
   {

   iToken=TOplToken::EBadToken;
   iType=TOplToken::EBadType;

   iLex.SkipSpaceAndMark(); // mark the start of the current token
   if (iError!=NULL) // Keep track of error position
	   iError->SetPosition(TokenOffset());

   if (iLex.Eos())
      iToken=TOplToken::EEos;
   else
      {
      TChar next=iLex.Peek();
      if (next.IsDigit() || next==iDecimalSeparator)
         DecNumberL(next);
      else if (next=='&' || next=='$')
         HexNumberL();
      else if (next=='\"')
         LexStringL();
      else if (next.IsAlpha() || next=='_')
         AlphaL();
      else if (next=='@')
         ProcByNameL();
      else
         CharacterL();
      }
   return iToken;
   }

EXPORT_C void COplLexerBase::LexL(TOplToken aToken)
//
// Does a lex ensureing that the next token is as expected
//
	{
	if (LexL()!=aToken)
		SyntaxErrorL();
	}

EXPORT_C void COplLexerBase::UnLex()
//
// Puts back the last token returned.
//
   {

   iLex.UnGetToMark();
   }


EXPORT_C TChar COplLexerBase::NextChar()
//
// Needed by the % operator
//
	{
	if (iLex.Eos())
		User::Leave(EErrBadCharacter);
	return iLex.Get();
	}

EXPORT_C TPtrC COplLexerBase::MarkedToken()
//
// Returns the iLex marked token for cases where you 
// want the raw unadulterated input.
//
	{
	return iLex.MarkedToken();
	}

EXPORT_C void COplLexerBase::Mark()
//
// Marks the current position. Used to sniff a couple of 
// tokens ahead when the parser isn't sure what to do.
//
	{
	iLex.Mark(iMark);
	}

EXPORT_C void COplLexerBase::UnGetToMark()
//
// Restores where we were in the line
//
	{
	iLex.UnGetToMark(iMark);
	}


EXPORT_C void COplLexerBase::Reset()
//
//
//
	{
	}


EXPORT_C void  COplLexerBase::SetTarget(TOplTranTarget aTarget)
//
//
//
	{
	iTarget=aTarget;
	iMaxIdent=(aTarget==EOplTargetER1 ? KOplMaxIdentifierLength : KOplOpl1993MaxIdentLength);
	}

void COplLexerBase::SetSymbolTable(COplSymbolTable *aTable)
//
// Sets the symbol table. NOTE this is deliberately not inline & not EXPORT_C.
// It's public:, but only within the DLL.
//
	{
	
	iSymbols=aTable;
	}
						

#pragma warning(disable : 4705) // "Code has no effect". Due to some un-initialized members 
								// See "strnge warning from Compiler - Graham Darnell
							    // In programing (Harcourt) notes database
COplLexerBase::COplLexerBase()
	: iDecimalSeparator('.'),iTarget(KOplDefaultTarget),iMaxIdent(KDefaultIdentifierLength)
//
// Set default target and decimal separator
// 
	{
	}
#pragma warning(default : 4705)


void COplLexerBase::GetRealL()
//
// Where all numbers end up - the default for a decimal number
//
	{
	TReal64 realVal;
	if (iLex.Val(realVal,iDecimalSeparator)!=KErrNone)
		User::Leave(EErrBadNumber);
	new(iConstant) TOplConstant(realVal);
	ConstantToken();
	}

void COplLexerBase::ConstantToken()
//
// Sets
//
	{
	iType=Constant().Type();
	iToken=TOplToken::EConstant;
	}

	
void COplLexerBase::DecNumberL(TChar aStart)
//
// Gets a number starting with a decimal separator or a digit
// Always try for the smallest possible size.
//
   {

	TInt err=KErrGeneral;
	if (aStart!=iDecimalSeparator) // Can try for an integer
		{
	  
		TInt16 wordVal;
		err=iLex.Val(wordVal);
		new (iConstant) TOplConstant(wordVal);
		if (err!=KErrNone)
			{
			TInt32 longVal;
			err=iLex.Val(longVal);
			new (iConstant) TOplConstant(longVal);
			}

		ConstantToken(); // Can do no harm if there was an error 
	
		if (err==KErrNone) // Looked like an integer, but ...
			{
			TCharUC next=iLex.Peek(); // .. check if it's really a TReal
			if (next=='.' || next=='E') // e.g. 1.2 or 1E2
				{
				err=KErrGeneral; // force using float
				iLex.UnGetToMark();
				}
			}
		}

	if (err!=KErrNone) // Not an integer - or looks like a TReal
		GetRealL();
	}

void COplLexerBase::HexNumberL()
//
// Gets something that starts with either $ or &
//
	{

	TInt err;
	if (iLex.Get()=='&')
		{
		TUint32 longVal;
		err=iLex.Val(longVal,EHex);
		new (iConstant) TOplConstant(TInt32(longVal));
		}
	else
		{
		TUint16 wordVal;
		err=iLex.Val(wordVal,EHex);
		new (iConstant) TOplConstant(TInt16(wordVal));
		}					
	if (err!=KErrNone)
		User::Leave(EErrBadNumber);	
	ConstantToken();
	}


void COplLexerBase::LexStringL()
//
// Deals with a string constant
//
   {

   iText.Zero();
   TChar next=iLex.Get();
   FOREVER
      {
      if (iLex.Eos())
         User::Leave(EErrMissingQuote);
      next=iLex.Get();
      if (next=='\"') // end or embedded quote
         {
         if (iLex.Eos()) // Must have been the end
		 	break;
         if (iLex.Get()!='\"') // also the end
            {
            iLex.UnGet(); // so put it back
            break;
            }
         }
      if (iText.Length()==KOplMaxStringLength)
         User::Leave(EErrBadStringLength);
      iText.Append(next);
      }
   new (iConstant) TOplConstant(iText);
   ConstantToken();
   }

//
// Used to map suffices onto tokens and token types.
//
struct TOplSuffixMap
   {
   TUint32 iSuffices;
   TOplToken::TType iType;
   TOplToken::TValue iToken;
   };

LOCAL_D const TOplSuffixMap suffixMap[]=
   {
   {0,            TOplToken::EReal,TOplToken::ESimple},
   {':',          TOplToken::EReal,TOplToken::EProcId},
   {'%',          TOplToken::EWord,TOplToken::ESimple},
   {('%'<<16)+':',TOplToken::EWord,TOplToken::EProcId},
   {'&',          TOplToken::ELong,TOplToken::ESimple},
   {('&'<<16)+':',TOplToken::ELong,TOplToken::EProcId},
   {'$',          TOplToken::EString,TOplToken::ESimple},
   {('$'<<16)+':',TOplToken::EString,TOplToken::EProcId},
   {(':'<<16)+':',TOplToken::EWord,TOplToken::ELabel},
   {'.',          TOplToken::EWord,TOplToken::EField}
   };


void COplLexerBase::AlphaL()
//
// Something that starts with an IsAlpha()
// FOR NOW - needs fixing so error occurs in the right place ??
// 
	{

	TOplField::TDevice logicalDevice=TOplField::EBadDevice;
	FOREVER // Loop - done if doing logical device/field e.g. A.B$ is done as 
		{	  // two trips round the loop 
		// Use up all alpha-numerics
		TLexMark start;
		iLex.Mark(start);
		FOREVER
			{
			TChar peek=iLex.Peek();
			if (!peek.IsAlphaDigit() && peek!='_')
				break;
			iLex.Inc();
			}

		// Gather up the suffices
		TLexMark suffices;
		iLex.Mark(suffices);
		TUint32 suffVal=0;
		FOREVER
			{
			TChar next=iLex.Peek();
			if (next!='%' && next!='&' && next!='$' && next != ':' && next!='.')
				break;
			suffVal=(suffVal<<16)+next;
			iLex.Inc();
			}

		// Check that we've got no more than two, then include them in the token
		TUint suffixCount=iLex.TokenLength(suffices);
		if (suffixCount>2)
			User::Leave(EErrBadSuffices);

		// Quick check to make sure that the token will fit in the string buffer
		// Just in case we make the line length much bigger than max length
		// for a string constant. Assumes that string length
		// is bigger than ident length. Can't just check against KOplMaxIdentLen
		// as some function names are bigger than short identifiers 

		if (iLex.TokenLength(start)>KOplMaxStringLength) 
			User::Leave(EErrIdentifierTooLong);

		// Store the token in upper case.
		iText.CopyUC(iLex.MarkedToken(start));

		// Now - and only now, have a quick sniff and see if it's a reserved
		// word like PROC.
		if (!IsReserved())
			{
			
			// Check the suffices to work out what it is we might have.
			const TOplSuffixMap *pMap=suffixMap;
			const TOplSuffixMap *pEnd=pMap+sizeof(suffixMap)/sizeof(TOplSuffixMap);
			while (pMap<pEnd)
				{
				if (pMap->iSuffices==suffVal)
					break;
				pMap++;
				}
			if (pMap==pEnd) // It's not a legal combination of suffices.
				User::Leave(EErrBadSuffices);

			// Looks good so far;
			iToken=pMap->iToken;
			iType=pMap->iType;

			// Now drop any ':'s as they have served their purpose.
			TUint dropLen=0;
			if (iToken==TOplToken::EProcId)
				dropLen=1;
			else if (iToken==TOplToken::ELabel)
				dropLen=2;
			iText.SetLength(iText.Length()-dropLen); //?? No better way to do this iText::DecLen(2);

			// Finally we can check the length
			if (iText.Length()>iMaxIdent)
				User::Leave(EErrIdentifierTooLong);


			if (iToken==TOplToken::ESimple) // Check now for Arrays and memories
				{
				if (iLex.Peek()=='(')
					{
					iLex.Inc();
					iToken=TOplToken::EArray;
					}
				}
			}
		
		// Things that don't look like a logical device
		if (iToken!=TOplToken::EField)
			{
			if (logicalDevice!=TOplField::EBadDevice) // Already seen one so we're now looking for the field name
				{
				if (iToken!=TOplToken::ESimple) // Field names must be simple variables
					User::Leave(EErrBadFieldName);
				new (&iField[0]) TOplField(logicalDevice,iText);
				iToken=TOplToken::EField;
				}
			if (iSymbols!=NULL) // Might be an Opx Call or Constant
				{
				COplSymbol *pSym=iSymbols->Find(iText,iToken);
				if (pSym!=NULL)
					{
					if (pSym->Class()==COplSymbol::EOpxFunction) // Looks that war
						{
						iToken=TOplToken::EOpxFunction;
						iOpxSymbol=STATIC_CAST(COplCallSymbol *,pSym);
						}
					else if (pSym->Class()==COplSymbol::EConstant) // Actually a constant
						{
						new (iConstant) TOplConstant(STATIC_CAST(COplConstantSymbol *,pSym)->Value());
						ConstantToken();
						}
					}
				}
			break; // All done
			}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?