diff -r f345bda72bc4 -r 43e37759235e Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/_lexer_8cpp_source.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/_lexer_8cpp_source.html Tue Mar 30 16:16:55 2010 +0100 @@ -0,0 +1,554 @@ + + + + +TB9.2 Example Applications: examples/Base/BufsAndStrings/Lexer/Lexer.cpp Source File + + + + + +

examples/Base/BufsAndStrings/Lexer/Lexer.cpp

00001 // Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
+00002 // All rights reserved.
+00003 // This component and the accompanying materials are made available
+00004 // under the terms of "Eclipse Public License v1.0"
+00005 // which accompanies this distribution, and is available
+00006 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
+00007 //
+00008 // Initial Contributors:
+00009 // Nokia Corporation - initial contribution.
+00010 //
+00011 // Contributors:
+00012 //
+00013 // Description:
+00014 //
+00015 
+00016 #include <e32std.h>
+00017 #include <e32cons.h>
+00018 
+00019 const TInt KMaxCalcCommandBuffer=80;
+00020 
+00021 //Common literal text
+00022  
+00023 
+00024 _LIT(KTxtErrInExpress,"    Error in expression, cannot evaluate. ");
+00025 
+00026 
+00027 CConsoleBase* console;
+00028 
+00029 
+00031 // Stack classes
+00033 
+00034 //
+00035 // Stack element class - linked list of TReals
+00036 //
+00037 
+00038 class CRpnStackElement : public CBase
+00039         {
+00040         friend class CRpnStack ;
+00041 
+00042         private:
+00043                 CRpnStackElement* iNext ;
+00044                 TReal iValue ;
+00045 
+00046         public:
+00047                 static CRpnStackElement* NewL ( const TReal& aReal, CRpnStackElement* aStackElement) ;
+00048                 void   ConstructL (const TReal& aReal, CRpnStackElement* aStackElement) ;
+00049 
+00050         public:
+00051                 CRpnStackElement() {} ;
+00052         }  ;
+00053 
+00054 
+00055 //
+00056 // Stack class - just constructor, destructor, push, pop & empty-test.
+00057 //
+00058 
+00059 class CRpnStack : public CBase
+00060         {
+00061         private: 
+00062                 CRpnStackElement* iTop ;  // pointer to top of stack element
+00063 
+00064         public:
+00065                 static CRpnStack* NewL () ;
+00066                 void   ConstructL () ;
+00067 
+00068                 ~CRpnStack() ;
+00069                 TReal Pop () ;
+00070                 void Push (TReal aReal) ;
+00071                 TBool IsEmpty () ;
+00072         } ;
+00073 
+00074 
+00076 // Stack class implementations
+00078 
+00079 // stack element construction (2-part)
+00080 CRpnStackElement* CRpnStackElement::NewL(const TReal& aReal, CRpnStackElement* aStackElement)
+00081         {
+00082         CRpnStackElement* self = new (ELeave) CRpnStackElement ;
+00083         CleanupStack::PushL(self);
+00084         self->ConstructL(aReal, aStackElement);
+00085         CleanupStack::Pop();
+00086         return self;
+00087         }
+00088 
+00089 
+00090 void CRpnStackElement::ConstructL(const TReal& aReal, CRpnStackElement* aStackElement)
+00091         {
+00092         iValue = aReal;
+00093         iNext = aStackElement ;
+00094         }
+00095 
+00096 
+00097 // stack construction
+00098 CRpnStack* CRpnStack::NewL()
+00099         {
+00100         CRpnStack* self = new (ELeave) CRpnStack ;
+00101         CleanupStack::PushL(self);
+00102         self->ConstructL();
+00103         CleanupStack::Pop();
+00104         return self;
+00105         }
+00106 
+00107 
+00108 void CRpnStack::ConstructL()
+00109         {
+00110         iTop = 0 ;
+00111         }
+00112 
+00113 
+00114 // stack destructor
+00115 CRpnStack::~CRpnStack()
+00116         {
+00117         while (!IsEmpty())   
+00118                 Pop() ;
+00119         }
+00120 
+00121 
+00122 // stack pop & delete top element
+00123 TReal CRpnStack::Pop ()
+00124         {
+00125         TReal value = iTop->iValue ;  // get return value
+00126         CRpnStackElement* old = iTop ;  // keep old top of stack pointer
+00127         iTop = iTop->iNext;  // move top of stack pointer to next element
+00128         delete old ;  // delete old top of stack element
+00129         old = 0 ;  // don't want old used again
+00130         return value ;  // return the value
+00131         } 
+00132 
+00133 
+00134 // stack push new element
+00135 void CRpnStack::Push (TReal aReal)
+00136         {
+00137         TRAPD(err,iTop = CRpnStackElement::NewL(aReal, iTop)) ; 
+00138         if(err)
+00139                 {
+00140                         _LIT(KFormat2,"Push failed: leave code=%d");
+00141                         console->Printf(KFormat2,err);  
+00142                 }
+00143         } 
+00144 
+00145 
+00146 // stack empty test
+00147 TBool CRpnStack::IsEmpty ()
+00148         {
+00149         return (iTop == 0) ;
+00150         }
+00151 
+00152 
+00154 //  RPN calculator engine class
+00156 
+00157 class CRpnCalculator
+00158         {
+00159         private:
+00160                 static TReal GetIntegerPart(TLex& aInput) ;
+00161                 static TReal GetFractionalPart(TLex& aInput) ;
+00162                 static TInt  DealWithNum(CRpnStack* aStack, TLex& aInput) ;
+00163                 static TInt  RPNCalcEngineL(const TDesC& aCommand, TReal& aReturnValue) ;
+00164                 static TInt  doRPNCalcEngine(TLex& aInput,CRpnStack* stack,TReal& aReturnValue);
+00165                 static void  DisplayAnswer(TReal aValue) ;
+00166                 static TBool TextInput(TDes& aBuf) ;
+00167         public:
+00168                 static void RunRPNCalculatorL() ;
+00169         } ;
+00170 
+00171 
+00173 //  RPN calculator engine : numeric routines
+00175 
+00176 TReal CRpnCalculator::GetIntegerPart(TLex& aInput) 
+00177 // Finds a UInt. Also used before decimal point for RPN TReal processing
+00178         {
+00179         TReal accumulator =  0 ;
+00180 
+00181         while ((aInput.Peek()).IsDigit())
+00182                 {
+00183                 accumulator = (accumulator * 10) + ( (TReal)aInput.Get() - (TReal)'0' ) ;
+00184                 }
+00185         return accumulator ;
+00186         }
+00187 
+00188 
+00189 TReal CRpnCalculator::GetFractionalPart(TLex& aInput) 
+00190 // Finds a UInt. Used after decimal point for RPN TReal processing
+00191         {
+00192         TReal accumulator =  0 ;
+00193         TReal multiplier = 0.1 ;
+00194 
+00195         while ((aInput.Peek()).IsDigit())
+00196                 {
+00197                 accumulator +=  ( (TReal)aInput.Get() - (TReal)'0' ) * multiplier ;
+00198                 multiplier /= 10 ;
+00199                 }
+00200         return accumulator ;
+00201         } 
+00202 
+00203 
+00204 TInt CRpnCalculator::DealWithNum(CRpnStack* aStack, TLex& aInput) 
+00205 // VERY basic scanning to extract and push a (Uint or real) number.
+00206         {
+00207         TBool negative = EFalse ;
+00208         TReal answer =  0 ;
+00209         TLexMark startMark ;
+00210 
+00211         // need something to parse
+00212         if (aInput.Eos())
+00213                 return KErrNotFound ;
+00214         if (!(aInput.Peek().IsDigit() || (aInput.Peek() == '.') ) )
+00215                 return KErrNotFound ;
+00216         
+00217         // mark where we are, so can unwind
+00218         aInput.Mark(startMark) ;
+00219 
+00220         // deal with sign
+00221         if (aInput.Peek() == '+') 
+00222                 aInput.Inc() ;
+00223         if (aInput.Peek() == '-') 
+00224                 {
+00225                 aInput.Inc() ;
+00226                 negative = ETrue ;
+00227                 }
+00228 
+00229         // check there's something to parse
+00230         if (aInput.Eos()) 
+00231                 return KErrNotFound ;
+00232 
+00233         // get number (may be complete integer or first part of a real)
+00234         if ((aInput.Peek()).IsDigit())
+00235                 answer = CRpnCalculator::GetIntegerPart(aInput)  ;
+00236 
+00237         // negate if necessary
+00238         if (negative) 
+00239                 answer *= -1 ;
+00240 
+00241         // look for decimal point - if found, parse real number
+00242         if (aInput.Peek() == '.')
+00243                 {  // may be dealing with real number.
+00244                 aInput.Inc() ;
+00245                 if (!(aInput.Peek()).IsDigit()) 
+00246                         {       // found non-digit after decimal point. Error, so rewind & exit
+00247                         aInput.UnGetToMark(startMark) ;
+00248                         return KErrCancel ;
+00249                         }
+00250                 // now must parse digit(s) after decimal point
+00251                 answer += CRpnCalculator::GetFractionalPart(aInput) ;
+00252                 aStack->Push(answer) ;
+00253                 return KErrNone ;
+00254                 }
+00255         else
+00256                 {  // dealing with integer 
+00257                 aStack->Push(answer) ;
+00258                 return KErrNone ;
+00259                 }
+00260         }
+00261 
+00262 
+00264 //  Main body of the RPN calculator engine : calculator
+00266 
+00267 TInt CRpnCalculator::doRPNCalcEngine(TLex& aInput,CRpnStack* stack,TReal& aReturnValue)
+00268         {
+00269         //              extract a number if possible & push
+00270         //              extract token, perform operation & push result
+00271         //              if token is '=' or at end of string, pop & print value
+00272         TInt Err       = KErrNone;
+00273         TReal operand1 = 0;
+00274         TReal operand2 = 0 ;
+00275         TReal memory   = 0 ;
+00276 
+00277         do 
+00278                 {
+00279                 aInput.SkipSpace() ;
+00280 
+00281                 if (CRpnCalculator::DealWithNum(stack, aInput)== KErrNone) ;  // parse for number 
+00282 
+00283     /*  above line can be replaced by the following equivalent code:
+00284                         
+00285                         if (aInput.Val(extractReal) == KErrNone)
+00286                                 stack->Push(extractReal) ;
+00287                         else if (aInput.Val(extractUint) == KErrNone)
+00288                                 stack->Push(TReal(extractUint)) ;
+00289         */
+00290 
+00291                 else switch ( aInput.Get() )
+00292                         {
+00293                         case'+' :
+00294                                 if (!stack->IsEmpty()) operand2 = stack->Pop() ; else Err = KErrGeneral ;
+00295                                 if (!stack->IsEmpty()) operand1 = stack->Pop() ; else Err = KErrGeneral;
+00296                                 if (Err==KErrNone) stack->Push (operand1 + operand2) ;
+00297                                 break ;
+00298 
+00299                         case'-' :
+00300                                 if (!stack->IsEmpty()) operand2 = stack->Pop() ; else Err = KErrGeneral ;
+00301                                 if (!stack->IsEmpty()) operand1 = stack->Pop() ; else Err = KErrGeneral;
+00302                                 if (Err==KErrNone) stack->Push (operand1 - operand2) ;
+00303                                 break ;
+00304 
+00305                         case '*' :
+00306                                 if (!stack->IsEmpty()) operand2 = stack->Pop() ; else Err = KErrGeneral ;
+00307                                 if (!stack->IsEmpty()) operand1 = stack->Pop() ; else Err = KErrGeneral;
+00308                                 if (Err==KErrNone) stack->Push (operand1 * operand2) ;
+00309                                 break ;
+00310 
+00311                         case'/' :
+00312                                 if (!stack->IsEmpty()) operand2 = stack->Pop() ; else Err = KErrGeneral ;
+00313                                 if (!stack->IsEmpty()) operand1 = stack->Pop() ; else Err = KErrGeneral;
+00314                                 if (Err==KErrNone) stack->Push (operand1 / operand2) ;
+00315                                 break ; 
+00316                                                 
+00317                         case '=' :
+00318                                 if ( !(stack->IsEmpty() ) )
+00319                                 {       aReturnValue = stack->Pop() ;
+00320                                         return KErrNone ;
+00321                                 }
+00322                                 else return KErrArgument ;
+00323 
+00324                         // not found a valid one-character symbol, try key words...
+00325                         default :                       
+00326                                 if (aInput.Offset() > 0)  // if not at start of line
+00327                                         aInput.UnGet() ;  // restore 'got' character
+00328 
+00329                                 aInput.Mark() ;  // remember where we are
+00330                                 aInput.SkipCharacters() ;  // move to end of character token
+00331 
+00332 
+00333                                 if ( aInput.TokenLength() != 0 )  // if valid potential token
+00334                                         {
+00335                                         _LIT(KTxtMEMSET,"MEMSET");
+00336                                         _LIT(KTxtMEMGET,"MEMGET");
+00337                                         TPtrC token = aInput.MarkedToken() ;  // extract token
+00338                                         if ( token.CompareF(KTxtMEMSET) == 0)
+00339                                                 {
+00340                                                 if ( !(stack->IsEmpty()) )  // MEMSET - store top stack element
+00341                                                         memory = stack->Pop() ;
+00342                                                 if ( stack->IsEmpty() )  // valid command, but empty stack will cause error, so
+00343                                                         stack->Push(memory) ;
+00344                                                 }
+00345                                         else if ( token.CompareF(KTxtMEMGET) == 0)
+00346                                                 stack->Push (memory) ;  // MEMGET - push memory value
+00347                                         else 
+00348                                                 return KErrNotSupported ;  // unrecognised token
+00349                                         }
+00350                                 else  // exit - can't be anything else
+00351                                         {
+00352                                         return KErrGeneral ;
+00353                                         }
+00354                         } ;  // end switch
+00355                 if (Err == KErrGeneral) 
+00356                         // error in expression (usually as there aren't 2 stack elements for token to operate on)
+00357                         return KErrArgument ;
+00358                 
+00359                 }       while (!aInput.Eos())  ;
+00360 
+00361         if ( !(stack->IsEmpty() ) )
+00362                 {
+00363                 aReturnValue = stack->Pop() ;
+00364                 return KErrNone ;
+00365                 }
+00366         else return KErrArgument ;
+00367         }       
+00368 
+00369 
+00370 
+00372 //  RPN calculator engine : calculator
+00374 
+00375 TInt CRpnCalculator::RPNCalcEngineL(const TDesC& aCommand, TReal& aReturnValue)
+00376         {
+00377         TInt ret;
+00378         TLex input(aCommand);
+00379         
+00380         CRpnStack* stack = CRpnStack::NewL();
+00381         CleanupStack::PushL(stack);
+00382         ret = CRpnCalculator::doRPNCalcEngine(input,stack,aReturnValue);
+00383         CleanupStack::PopAndDestroy(); 
+00384         return ret;
+00385         }
+00386 
+00387 
+00388 
+00390 //  RPN calculator UI : display routines
+00392 
+00393 void CRpnCalculator::DisplayAnswer(TReal aValue)
+00394         {
+00395         TRealFormat format ;
+00396         TBuf<0x100> convertRealToString;
+00397 
+00398         // want a TLex from the value
+00399 
+00400         if (convertRealToString.Num(aValue,format) < KErrNone )  // if -ve, is an error, not a string length 
+00401                 console->Printf(KTxtErrInExpress);
+00402         else
+00403                 {
+00404                 convertRealToString.ZeroTerminate();
+00405 
+00406                 TLex string(convertRealToString) ;
+00407                 // got a TLex
+00408         
+00409                 TLexMark start ;
+00410                 string.Mark (start) ;  // remember start of string position
+00411 
+00412                 // run through string, setting 'end' to last digit found
+00413                 while (!string.Eos() )
+00414                         {
+00415                         if ( !(string.Get() == '0') ) string.Mark() ;
+00416                         }
+00417 
+00418                 string.UnGetToMark() ;  // reset next character pointer to last digit
+00419                 // if Mark points to decimal point and not at Eos (i.e. a zero follows), include the zero
+00420                 if ( string.Get() == '.' && !string.Eos() )
+00421                         string.Mark() ;
+00422 
+00423                 // display spaces after entered line
+00424                 _LIT(KTxtSpaces,"  ");
+00425                 console->Write(KTxtSpaces) ;
+00426                 // set Mark to start of string and display answer
+00427                 console->Write( string.MarkedToken(start)  ) ;
+00428                 }
+00429         }
+00430 
+00431 
+00433 //  RPN calculator UI : line input  routine (adapted from tuiedit)
+00435 
+00436 _LIT(KTxtBackSlashSeven,"\7");
+00437 _LIT(KTxtCursor,"_");
+00438 
+00439 TBool CRpnCalculator::TextInput(TDes& aBuf)
+00440     {
+00441         TInt  pos;
+00442         
+00443         pos  = 0;
+00444         aBuf.Zero();
+00445         console->SetPos(0);
+00446         console->Write(KTxtCursor) ;  // "cursor"
+00447         console->SetPos(0);
+00448 
+00449         FOREVER
+00450                 {
+00451                 TChar gChar=console->Getch();
+00452                 switch (gChar)
+00453                         {
+00454                         case EKeyEscape:
+00455                                 return (EFalse);
+00456                         case EKeyEnter:
+00457                                 return (ETrue);
+00458                         case EKeyBackspace:     
+00459                                 if (pos)
+00460                                         {
+00461                                         pos--;
+00462                                         aBuf.Delete(pos,1);
+00463                                         }
+00464                                 break;
+00465                         default:
+00466                                 if (!gChar.IsPrint())
+00467                                         break;
+00468                                 else
+00469                                         if ((aBuf.Length()<KMaxCalcCommandBuffer)&&(pos<KDefaultConsWidth-3))
+00470                                                 {
+00471                                                 TBuf<0x02> b;
+00472                                                 b.Append(gChar);
+00473                                                 aBuf.Insert(pos++,b);
+00474                                                 }
+00475                                         else
+00476                                                 {
+00477                                                 console->Write(KTxtBackSlashSeven);
+00478                                                 break;
+00479                                                 }
+00480                         }
+00481                         console->SetPos(pos) ;
+00482                         console->ClearToEndOfLine();
+00483                         console->SetPos(0);
+00484                         console->Write(aBuf);
+00485                         console->Write(KTxtCursor) ;  // "cursor"
+00486                         console->SetPos(pos);
+00487                 }
+00488         }
+00489 
+00490 
+00492 //  finally the RPN calculator's driver code
+00494 
+00495 _LIT(KTxtStartingRPNCalc,"Starting RPN Calculator\n\n");
+00496 _LIT(KTxtNewLine," \n");
+00497 _LIT(KTxtInvite,"Type in a Reverse Polish\nexpression.\nPress ENTER to evaluate it\nPress ESC to end\n");
+00498 
+00499 
+00500 
+00501 void CRpnCalculator::RunRPNCalculatorL()
+00502         {
+00503         TBuf<KMaxCalcCommandBuffer> command;    
+00504         
+00505         console->Printf(KTxtStartingRPNCalc);
+00506         console->Printf(KTxtInvite);
+00507 
+00508         while (CRpnCalculator::TextInput(command) ) 
+00509                 {
+00510                 TReal answer;
+00511 
+00512                 if (CRpnCalculator::RPNCalcEngineL(command, answer) == KErrNone ) 
+00513                         CRpnCalculator::DisplayAnswer(answer) ;
+00514                 else
+00515                         console->Printf(KTxtErrInExpress) ;
+00516                                 
+00517                 console->Printf(KTxtNewLine) ;
+00518                 console->Printf(KTxtInvite);
+00519                 }
+00520         }
+00521 
+00522 
+00524 // This section deals with Symbian platform initialisation and ensuring we have a console active
+00526 
+00527 
+00528 void SetupConsoleL();
+00529 
+00530 _LIT(KTxtRPNCalcErr,"RPN Calculator example error");
+00531 
+00532 GLDEF_C TInt E32Main()  // main function called by E32
+00533     {
+00534         CTrapCleanup* cleanup=CTrapCleanup::New();  // get clean-up stack
+00535         TRAPD(error,SetupConsoleL());  // more initialization, then do example
+00536         __ASSERT_ALWAYS(!error,User::Panic(KTxtRPNCalcErr,error));
+00537         delete cleanup;  // destroy clean-up stack
+00538         return 0;  // and return
+00539     }
+00540 
+00541 
+00542 void SetupConsoleL()  // initialize and call example code under cleanup stack
+00543     {
+00544         _LIT(KTxtIntro,"eulexrpn - RPN Calculator");
+00545         _LIT(KFormat1,"failed: leave code=%d");
+00546         _LIT(KTxtPressAnyKey,"[Press any key to exit]");
+00547 
+00548         console=Console::NewL(KTxtIntro,TSize(KConsFullScreen,KConsFullScreen));
+00549         CleanupStack::PushL(console);
+00550         TRAPD(error, CRpnCalculator::RunRPNCalculatorL());  // perform example function
+00551         if (error)
+00552                 console->Printf(KFormat1, error);
+00553         console->Printf(KTxtPressAnyKey);
+00554         console->Getch();  // get and ignore character
+00555         CleanupStack::PopAndDestroy();  // close console
+00556     }
+00557 
+00558         
+
+
Generated by  + +doxygen 1.6.2
+ +