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 + -
显示快捷键?