diff -r f345bda72bc4 -r 43e37759235e Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/_lexer_8cpp-source.html --- a/Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/_lexer_8cpp-source.html Tue Mar 30 11:56:28 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,550 +0,0 @@ - -
-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 -