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