ot_parse.cpp

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

CPP
1,028
字号
// OT_PARSE.CPP
//
// Copyright (c) 1997-2000 Symbian Ltd. All rights reserved.

// Assorted classes for the OPL translator language parser
//
#include "ot_std.h"
#include "opl16.h"

//////////////////////////////////////////////
//
// COplParseOpx
//
//////////////////////////////////////////////
COplParseOpx *COplParseOpx::NewLC()
//
// Class for storing informatiomn from DECLARE OPX, END DECLARE 
// block.
//
   {
   COplParseOpx *pOpx=new(ELeave) COplParseOpx();
   CleanupStack::PushL(pOpx);
   return pOpx;
   }

COplParseOpx::~COplParseOpx()
//
// Do a bit of tidying up
//
   {
   delete iName;
   }

void COplParseOpx::SetNameL(const TDesC& aName)
//
// Just gets a copy of the name
//
	{
	__ASSERT_DEBUG(iName==NULL,Panic(EOpltParseOpxNameSet));
	iName=aName.AllocL();
	}

COplParseOpx::COplParseOpx()
	{
	}

//////////////////////////////////////////////////////
//
// COplParseProc - Internal model of a procedure
//
//////////////////////////////////////////////////////
COplProcHeader *COplProcHeader::NewLC(TOplToken::TType aType)
//
// 
//
   {

	COplProcHeader *pPh=new(ELeave) COplProcHeader(aType);
	CleanupStack::PushL(pPh);
	return pPh;
	}

void COplProcHeader::AddSymbolL(COplSymbol& aSymbol)
//
// A new symbol is being added to the symbol table.
// This gets to check to see if it wants to added it to a list
//

   {

   CArrayFixFlat<COplSymbol*>* list=NULL;
   switch (aSymbol.Class())
      {
	   case COplSymbol::EArgument:
         list=&iArguments;
         break;
	   case COplSymbol::EExternalRef:
         list=&iExternals;
         break;
	   case COplSymbol::EProcRef:
         list=&iProcCalls;
         break;
	   case COplSymbol::EGlobal:
         list=&iGlobals;
         break;
	   case COplSymbol::ELocal:
         list=&iLocals;
         break;
	   case COplSymbol::ELabel:
         list=&iLabels;
         break;
	   case COplSymbol::EConstant:
	   case COplSymbol::EExternalDecl:
	   case COplSymbol::EProcDecl:
	   case COplSymbol::EOpxFunction:
         break;
      }
   	if (list!=NULL)
		list->AppendL(&aSymbol);
	}

COplProcHeader::COplProcHeader(TOplToken::TType aType)
	:
	iType(aType),
	iArguments(KOplParseProcArrayGran),
	iExternals(KOplParseProcArrayGran),
	iGlobals(KOplParseProcArrayGran),
	iLocals(KOplParseProcArrayGran),
	iProcCalls(KOplParseProcArrayGran),
	iLabels(KOplParseProcArrayGran)
//
// 
//
	{
	}

////////////////////////////////////////////////////////
//
// COplParserBase
//
////////////////////////////////////////////////////////
void COplParserBase::SetTarget(TOplTranTarget aTarget)
//
//
//
	{
	CheckReset();
	iTarget=aTarget;
	}

void COplParserBase::Start(COplLexerBase& aLexer,TTranslateError& anError)
//
//
//
   {

   iLexer=&aLexer;
   iError=&anError;
   }

void COplParserBase::Reset()
//
//
//
	{

	iExplicitDefines=EFalse;	
	if (iSymbols)
		iSymbols->Reset();
	}

COplDeclarationSymbol* COplParserBase::NewSymbolL(COplSymbol::TClass aClass)
//
// Generates and adds a new symbol from the currently lexed token
//
	{
	
	COplDeclarationSymbol *pDecl=COplDeclarationSymbol::NewLC(aClass,Lexer().Token(),Lexer().Type(),Lexer().Name());
	AddSymbolL(*pDecl);
	CleanupStack::Pop(); // Safe now
	return pDecl;
	}


void COplParserBase::AddSymbolL(COplSymbol& aSymbol)
//
// Just Sticks it in the symbol table
//
	{
	
	iSymbols->AddL(aSymbol);
	}


COplReferenceSymbol* COplParserBase::ReferenceL(COplSymbol& aSymbol)
//
// Generates a refernce to the declaration symbol we've been passed
//
	{
	COplReferenceSymbol *pRef=((COplDeclarationSymbol&)aSymbol).NewReferenceLC();
	AddSymbolL(*pRef);
	CleanupStack::Pop();
	return pRef;
	}

void COplParserBase::PCodeL(TPcode::TCode aCode)
//
// Puts out the PCODE assuming the current offset
//
	{
	iCode<<TPcode(aCode,iError->Position()); // Where an error would be reported now
	}

void COplParserBase::MustBeL(TOplToken aToken)
//
// Checks that the next token is what is expected
// 
	{

	Lexer().LexL(aToken);
	}

TOplToken COplParserBase::NextL()
//
//
//
	{
	return Lexer().LexL();
	}

TBool COplParserBase::NextIsL(TOplToken aToken)
//
// If the next token is the desired one, returns ETrue having lexed it
// Otherwise returns EFalse
//
   {

   TBool ret=ETrue;
   if (NextL()!=aToken)
      {
      ret=EFalse;
      Lexer().UnLex();
      }
   return ret;
   }

TBool COplParserBase::NextIsCommaL()
//
// Checks for a comma
//
	{
	
	return NextIsL(TOplToken::EComma);
	}

void COplParserBase::CommaL()
//
//
//
	{

	if (!NextIsL(TOplToken::EComma))
		User::Leave(EErrMissingComma);
	}

TBool COplParserBase::TargetIsOpl1993() const
	{
	return iTarget & (KOplTargetOpl1993);
	}

TOplToken::TType COplParserBase::NativeType() const
//
//
//
	{
	return (TargetIsOpl1993() ? TOplToken::EWord : TOplToken::ELong);
	}

TOplToken::TType COplParserBase::UnsignedNativeType() const 
//
// This is a horrible kludge since there is currently no support
// for a cast to unsigned longs in OPL so we just cast 32-bit
// unsigned arguments to 32-bit signed values. This has death lurking in it
// but time is short
//
	{
	return (TargetIsOpl1993() ? TOplToken::EUWord : TOplToken::ELong);
	}

COplParserBase::COplParserBase()
	: iTarget(KOplDefaultTarget), iOperatorStack(KOperatorStackGran)
	{
	}

void COplParserBase::ConstructL()
//
// Constructs the symbol table
//
   {
   
   iSymbols=COplSymbolTable::NewL();
   }

void COplParserBase::CheckReset()
//
// Base parser does not have a reset state
//
	{
	}

COplParserBase::~COplParserBase()
//
// Deletes the symbol table
//
   {

   delete iSymbols;
   }

////////////////////////////////////////////////////////
//
// COplModuleParser
//
///////////////////////////////////////////////////////////
COplModuleParser *COplModuleParser::NewL()
//
// Creates a new module parser
//
	{
	COplModuleParser *pP=new(ELeave) COplModuleParser;
	CleanupStack::PushL(pP);
	pP->ConstructL();
	CleanupStack::Pop();
	return pP;
	}

void COplModuleParser::Start(COplModuleLexer& aLexer,TSourceTranslateError& anError, COplModuleBackEnd& aBackEnd)
//
// Sets lexer & back end and sets up the code stream
//
   {
   CheckReset(); // Will panic if we're not
   COplParserBase::Start(aLexer,anError);
   iBackEnd=&aBackEnd;
   iState=EStarted;
   aLexer.SetSymbolTable(iSymbols);
   iLocatingError=EFalse;
   }

void COplModuleParser::SetErrorLocation(TInt aLineNumber, TInt aQcodeOffset)
//
// Sets things up to find a run-time error in the source
//	
	{

	iLineNumber=aLineNumber;
	iQcodeOffset=aQcodeOffset;
	iLocatingError=ETrue;
	}


void COplModuleParser::Reset()
//
//
//
	{
	
	iBackEnd=NULL;
	COplParserBase::Reset();
	iState=EReset;
	}


void COplModuleParser::ParseChunkL()
//
// Does the next chunk of the module
// Module := [AppDefinition] [Proc|OpxDEclaration|ConstDeclaration|Declare External]+ EndOfFile
//
// A chunk is either an APP ENDA construct or a Procedure
// (By now we know that we're not in the EReset state)
	{

	__ASSERT_ALWAYS(iState!=EReset,Panic(EOpltParserReset));
	TInt declCount=KOplDeclarationsPerChunk;
	TBool doMore;
	do
		{
		doMore=EFalse;
		TOplToken peek=SkipBlankLinesL();
		switch (peek)
			{
			case TOplToken::EApp:	
				if (iState!=EStarted) // Can only get App right at the start
					SyntaxErrorL();
				AppL();
				iState=EAppSeen;
				break;
			case TOplToken::EDeclare: // DECLARE EXTERNAL or DECLARE OPX
				if (NextIsL(TOplToken::EExternal))
					{
					EosL();
					iExplicitDefines=ETrue;
					doMore=--declCount;
					break;
					}
				else // Better be DECLARE OPX
					OpxDeclareBlockL();
				break;
			case TOplToken::EExternal: // EXTERNAL procname:[(arglist)]
				ProcedureDeclarationL(COplSymbol::EProcDecl,EDeclaration);
				doMore=--declCount;
				break;
			case TOplToken::EProc:
				{
				if (!Lexer().InRootSource()) // Can only declare prcedures in the 'root' sourcce file
					User::Leave(EErrIncludeProcedure);
				ProcL();
				iState=EProcSeen;
				break;
				}
			case TOplToken::EInclude:
				{
				MustBeL(TOplToken::EConstant);
				if (Lexer().Type()!=TOplToken::EString)
					SyntaxErrorL();
				MustBeL(TOplToken::EEos);
				Lexer().IncludeL(Lexer().Name());
				doMore=ETrue;
				break;
				}
			case TOplToken::EConst: // Will never occur when doing OPL1993 stuff
				{
				ConstantDeclarationL();
				doMore=--declCount;
				break;
				}
			case TOplToken::EEof:
				if (iState==EProcSeen) // Must have at least one procedure
					{
					iBackEnd->EndOfFileL();
					User::Leave(EErrSuccess); // All worked out nicely
					}
			default:		// NB: Drop through from TOplToken::EEof is deliberate
				SyntaxErrorL();
			}
		} while (doMore);
	}

void COplModuleParser::CheckReset()
//
// ASSERTS That we're in teh Reset state
//
	{
	__ASSERT_ALWAYS(iState==EReset,Panic(EOpltParserNotReset));
	}

COplModuleParser::COplModuleParser()
//
//
//
	{
	}

void COplModuleParser::AddSymbolL(COplSymbol& aSymbol)
//
//
//
	{
	// hp: changed the order of these to avoid symbol being left queued on OOM
	if (iProcHeader!=NULL) // Parsing a procedure at the moment
		iProcHeader->AddSymbolL(aSymbol);
	COplParserBase::AddSymbolL(aSymbol);
	}



void COplModuleParser::AppL()
//
// Deals with parsing the APP/ENDA thing. Delegates this to
// a class created by the back end, following the rationale
// that APP/ENDA is target specific in a way that the rest of the
// language isn't
//
	{
	COplParseApp *app=iBackEnd->GetAppLC(iTarget,Lexer());
	if (!iLocatingError)
		STATIC_CAST(COpl16ModuleBackEnd*,iBackEnd)->OplTargetIsApp();		// backend must tell texted
															// now before doing ParseL() because
															// ICON keyword needs full target path
	app->ParseL(*STATIC_CAST(COpl16ModuleBackEnd*,iBackEnd),iLocatingError);
	iBackEnd->AppL(app); // Takes ownership of the App object if it succeeds
	CleanupStack::Pop();
	}

COplSymbol& COplModuleParser::ProcedureDeclarationL(COplSymbol::TClass aClass,TDeclarationFlag aFlag)
//
// Parses a proc or opx function declaration
// proc-name[( [arg-decl [, arg-decl]*)]
// Constructs the signature of the function/procedure
//
	{

		
	//proc-name
	MustBeL(TOplToken::EProcId);
	HBufC *name=Lexer().Name().AllocLC();

	// Record the signature - the return type is the type of the proc-name symbol
	TOplSignature signature;
	signature.Initialize(Lexer().Type());

	// [ ( [arg-decl [,arg-decl]*] ) ]
	TInt argCount=0;
	if (NextIsL(TOplToken::EOpenBracket))  // OPL HA-26 bug fix: allow no brackets in declaration
		{ // ( [arg-decl [,arg-decl]*] )
		if (!NextIsL(TOplToken::ECloseBracket))
			{ // arg-decl [,arg-decl] *
			do 
				{ // arg-decl := [BYREF] simple-id
				TOplSignature::TArgType typeBase=TOplSignature::EArgWord; // [BYREF]
				TBool isByRef=NextIsL(TOplToken::EByRef);
				if (isByRef)
					typeBase=TOplSignature::EArgWordRef;
				MustBeL(TOplToken::ESimple); // simple-id
				if (isByRef && Lexer().Type()==TOplToken::EString)
					SyntaxErrorL();
		
				signature.AddArgument(argCount,TOplSignature::TArgType(typeBase+Lexer().Type()-TOplToken::EWord));
				argCount++;
				} while (NextIsL(TOplToken::EComma));
			MustBeL(TOplToken::ECloseBracket);
			}
		}
	signature.SetArgumentCount(argCount);

⌨️ 快捷键说明

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