sl@0: // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // SQL parser tokeniser sl@0: // sl@0: // sl@0: sl@0: #include "UQ_STD.H" sl@0: sl@0: // optimised tables for ASCII character set sl@0: sl@0: const TUint8 KAlpha=0x1; sl@0: const TUint8 KDigitOr_=0x2; sl@0: sl@0: const TUint8 KCharAttrib[]= sl@0: { sl@0: KDigitOr_,KDigitOr_,KDigitOr_,KDigitOr_,KDigitOr_,KDigitOr_,KDigitOr_,KDigitOr_, sl@0: KDigitOr_,KDigitOr_,0,0,0,0,0,0, sl@0: 0,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha, sl@0: KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha, sl@0: KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha, sl@0: KAlpha,KAlpha,KAlpha,0,0,0,0,KDigitOr_, sl@0: 0,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha, sl@0: KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha, sl@0: KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha, sl@0: KAlpha,KAlpha,KAlpha sl@0: }; sl@0: sl@0: #define ISALPHA(aChar) (TUint(aChar-'0')<=TUint('z'-'0') && KCharAttrib[aChar-'0']&KAlpha) sl@0: #define ISALPHA_DIGIT_OR_(aChar) (TUint(aChar-'0')<=TUint('z'-'0') && KCharAttrib[aChar-'0']&(KAlpha|KDigitOr_)) sl@0: #define LCASE(aChar) (aChar|0x20) sl@0: sl@0: // The keywords sl@0: // These are always stored as ASCII because DBMS has its own sl@0: sl@0: const TInt KMaxKeywordLength=9; sl@0: sl@0: static const TText8 KSqlKeywords[][KMaxKeywordLength+1]= sl@0: { sl@0: #define KEYWORD(s) #s sl@0: #include "UQ_KEYWD.H" sl@0: #undef KEYWORD sl@0: }; sl@0: const TInt KSqlKeywordCount=sizeof(KSqlKeywords)/sizeof(*KSqlKeywords); sl@0: sl@0: #if defined(_ASSERTIONS) sl@0: TInt CheckKeywords() sl@0: // sl@0: // ensure that the keyword table is in alphabetical order sl@0: // sl@0: { sl@0: for (TInt ii=1;iil) sl@0: { sl@0: TInt m=(l+r)>>1; sl@0: TInt k=CompareKeyword(m,aToken.Literal()); sl@0: if (k>0) sl@0: r=m; sl@0: else if (k<0) sl@0: l=m+1; sl@0: else sl@0: return TSqlKeyword(m); // keyword sl@0: } sl@0: } sl@0: // identifier sl@0: return ESqlNotKeyword; sl@0: } sl@0: sl@0: TSqlLexer::TSqlLexer(const TDesC& aSql) sl@0: : iNext(aSql.Ptr()),iEnd(iNext+aSql.Length()) sl@0: { sl@0: __ASSERT(CheckKeywords()); sl@0: } sl@0: sl@0: TSqlTokenType TSqlLexer::GetIdentifier(TSqlToken& aToken) sl@0: // sl@0: // Get a keyword or identifier. Do not resolve a keyword at this stage sl@0: // sl@0: { sl@0: const TText* end=iEnd; sl@0: const TText* next=iNext-1; sl@0: while (++next=10u) sl@0: return KErrGeneral; // no digits at all sl@0: TUint val32=c; sl@0: while (++ptr=10u) sl@0: break; sl@0: if (val32>KPreMultiplyLimit32) sl@0: goto overflow64; // will not fit into 32 bit arithmetic sl@0: val32*=10; sl@0: val32+=c; sl@0: } sl@0: // we have result, just set the sign and finish sl@0: aVal=val32; sl@0: goto checksign; sl@0: // sl@0: // continue the accumulation with a 64-bit integer sl@0: overflow64: sl@0: aVal=val32; sl@0: for (;;) sl@0: { sl@0: I64MUL10(aVal); sl@0: aVal+=c; sl@0: if (++ptr==end) sl@0: break; sl@0: c=*ptr-'0'; sl@0: if (c>=10u) sl@0: break; sl@0: if (I64HIGH(aVal)>KPreMultiplyLimit64) sl@0: return KErrOverflow; // the value is certain to overflow sl@0: } sl@0: if (I64HIGH(aVal)&0x80000000u) sl@0: { // greater than the "half way mark" sl@0: if (!sign) sl@0: return KErrOverflow; sl@0: if (I64LOW(aVal)!=0) sl@0: return KErrOverflow; sl@0: } sl@0: checksign: sl@0: iNext=ptr; sl@0: if (sign) sl@0: aVal=-aVal; sl@0: return KErrNone; sl@0: } sl@0: sl@0: TSqlTokenType TSqlLexer::GetNumber(TSqlToken& aToken) sl@0: { sl@0: const TText* mark=--iNext; // rewind past initial character sl@0: // attempt to parse a integer sl@0: TInt r=GetInteger(aToken.iLiteral.SetInt()); sl@0: if (r==KErrNone) sl@0: { sl@0: if (iNext') sl@0: { sl@0: iNext=ptr; sl@0: return ESqlNotEqual; sl@0: } sl@0: return ESqlLess; sl@0: } sl@0: case '>': sl@0: { sl@0: ch=*ptr++; sl@0: if (ch=='=') sl@0: { sl@0: iNext=ptr; sl@0: return ESqlGreaterEqual; sl@0: } sl@0: return ESqlGreater; sl@0: } sl@0: default: sl@0: break; sl@0: } sl@0: if (ISALPHA(ch)) sl@0: return GetIdentifier(aToken); // keyword or identifier sl@0: TChar cc(ch); sl@0: if (cc.IsAlpha()) sl@0: return GetIdentifier(aToken); // keyword or identifier sl@0: if (!cc.IsSpace()) sl@0: return SqlError(); sl@0: } sl@0: } sl@0: sl@0: const TText* TSqlLexer::Next() const sl@0: { sl@0: return iNext; sl@0: } sl@0: void TSqlLexer::Set(const TText* aNext) sl@0: { sl@0: iNext = aNext ; sl@0: }