tcalclex.cpp

来自「在手机操作系统symbina上使用的一个脚本扩展语言的代码实现,可以参考用于自己」· C++ 代码 · 共 399 行

CPP
399
字号
// TCALCLEX.CPP
//
// Copyright (c) 1997-1999 Symbian Ltd.  All rights reserved.
//

// Test COplLineLex
//
//

#include <e32test.h>
#include <opllex.h>

LOCAL_D RTest test(_L("TCALCLEX"));


class TLineLexerError
	{
public:
	const TText *iText;
	TInt iError;
	TInt iOffset;
	};

class TTestLineLexer
	{
public:
	inline TTestLineLexer() : iLex(NULL) {};
	void RunTests();	
private:
	void Test1(); // Interface
	void Test2(); // Constructor alloc heaven
	void Test3(); // Constants 
	void Test4(); // Operators and punctuation 
	void Test5(); // Identifiers
	void Test7(); // Functions
private:	
	COplLineLexer *GetLex();
	void DestroyLex();
	void CheckLine(const TText * const aLine, TUint aCount, TOplToken aToken, TOplToken::TType aType);
	void CheckErrors(const TLineLexerError *errors);
	TOplToken MarkLex(); // Wraps iLex.Lex() in __UHEAP_MARK/__UHEAP_MARKEND
	TInt MarkError(TOplToken &aToken); // Lea is expected to leave with an error - checks start end stuff
private:
	COplLineLexer *iLex;
	};



COplLineLexer *TTestLineLexer::GetLex()
//
// gets a lexer 
//
	{
	
	TRAPD(r,iLex=COplLineLexer::NewL());
	test(r==KErrNone);
	return iLex;
	}

void TTestLineLexer::DestroyLex()
//
// Chucks away the lexer
//
	{
	
	delete iLex;
	iLex=NULL;
	}


TOplToken TTestLineLexer::MarkLex()
//
// Wraps successful lex __UHEAP_MARK/__UHEAP_MARKEND
//
	{
	__UHEAP_MARK;
	TOplToken token;
	TRAPD(r,token=iLex->LexL());
	test(r==KErrNone);
	__UHEAP_MARKEND;
	return token;
	}

TInt TTestLineLexer::MarkError(TOplToken &aToken)
//
// Wraps failed lex __UHEAP_MARK/__UHEAP_MARKEND
//
	{
	
	__UHEAP_MARK;
	TRAPD(err,aToken=iLex->LexL());
	__UHEAP_MARKEND;
	return err;	
	}

void TTestLineLexer::CheckErrors(const TLineLexerError *errors)
//
// Trucks through an array of errors checking we get teh right error in the right place
//
	{
	
	while (errors->iText!=NULL)
		{
		iLex->SetExpression(TPtrC(errors->iText));

		TInt err;
		TOplToken token;
		do
			{
			err=MarkError(token);
			} while (err==KErrNone && token!=TOplToken::EEos);

		test(err==errors->iError);
		test(iLex->TokenOffset()==errors->iOffset); // Check the rror occured in the right place
		errors++;
		}	
	}

void TTestLineLexer::CheckLine(const TText * const aLine,TUint aCount,TOplToken aToken,TOplToken::TType aType)
//
// Line should contain aCount tokens aToken.
//	
	{

	
	__UHEAP_MARK;
	iLex->SetExpression(TPtrC(aLine));
	while (aCount--)
		{
		test(MarkLex()==aToken);
		test(iLex->Type()==aType);
		}
	test(MarkLex()==TOplToken::EEos);
	__UHEAP_MARKEND;
	}


void TTestLineLexer::Test1()
//
// All public funcitons
//
	{

	__UHEAP_MARK;
	
	test.Start(_L("New"));
	GetLex();
	
	test.Next(_L("Set expression"));
	iLex->SetExpression(_L("1"));

	test.Next(_L("Error offset"));
	test(iLex->TokenOffset()==0);
	
	test.Next(_L("Lex"));
	test(MarkLex()==TOplToken::EConstant);
	
	test.Next(_L("Type"));
	test(iLex->Type()==TOplToken::EReal);

	test.Next(_L("UnLex"));
	iLex->UnLex();
	test(iLex->TokenOffset()==0);

	test(MarkLex()==TOplToken::EConstant);
	test(iLex->Type()==TOplToken::EReal);

	test.Next(_L("Set Target"));
	iLex->SetTarget(EOplTargetOpl1993);

	DestroyLex();
	test.End();
	__UHEAP_MARKEND;
	}


void TTestLineLexer::Test2()
//
// Alloc heaven in construction
// Fails each alloc in turn.
//
	{
	
	test.Start(_L("Constructors"));
	
	iLex=NULL; // Just to be sure 
   TUint failNum=1;
   FOREVER
		{		
		__UHEAP_MARK;
		
		__UHEAP_SETFAIL(RHeap::EDeterministic,failNum);
		TRAPD(ret,iLex=COplLineLexer::NewL());
		__UHEAP_RESET;
		
		if (ret==0)
			{
			test(iLex!=NULL);
			break;
			}
			
		__UHEAP_MARKEND;
       failNum++; 
      }
#if defined(_DEBUG)
//	test(failNum!=1); // Check that we allocate at least one cell fo rthe lexer (it is CBase after all)
#endif
	test.Next(_L("Destructor"));
	DestroyLex();
	__UHEAP_MARKEND;
	
	test.End();
	}


LOCAL_D TLineLexerError badDecimals[]=
	{
	{_S("1 ."),EErrBadNumber,2},
	{_S("1 1.2e"),EErrBadNumber,2},
	{_S("33  1.2e"),EErrBadNumber,4},
	{_S("1e1000"),EErrBadNumber,0},
	{_S("1e-1000"),EErrBadNumber,0},
	{NULL,0,0}
	};

LOCAL_D TLineLexerError badHexadecimals[]= // FOR NOW - note these are all one too big because of the Mark bugs
	{
	{_S("$"),EErrBadNumber,0},
	{_S("1 &"),EErrBadNumber,2},
	{_S("$1 $g"),EErrBadNumber,3},
	{_S("&1 &g"),EErrBadNumber,3},
	{_S("$ffff $10000"),EErrBadNumber,6},
	{_S("&ffffffff &100000000"),EErrBadNumber,10},
	{NULL,0,0}
	};

LOCAL_D TLineLexerError badStrings[]=
	{
	{_S("\""),EErrMissingQuote,0},
	{_S("12 \"abcd"),EErrMissingQuote,3},
	{_S("\"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\
0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\
0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\
0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\""),EErrBadStringLength,0},
	{NULL,0,0}
	};

void TTestLineLexer::Test3()
//
// Numeric constants
//
	{
	__UHEAP_MARK;
	GetLex();
	
	test.Start(_L("Decimal"));

	CheckLine(_S("0 1 127 128 32767"),5,TOplToken::EConstant,TOplToken::EReal);
	CheckLine(_S("32768 65535 65536 2147483647"),4,TOplToken::EConstant,TOplToken::EReal);
	CheckLine(_S("1.0 .1 32767.0 32768.0 217483647.0 214783648 1e1 1E+1 1e-1"),9,TOplToken::EConstant,TOplToken::EReal);

	test.Next(_L("Decimal Errors"));
	CheckErrors(badDecimals);

	test.Next(_L("Hex"));	
	CheckLine(_S("$0 $1 $7f $80 $7fff $ffff $ff81 $ff80 $8000"),9,TOplToken::EConstant,TOplToken::EWord);
	CheckLine(_S("&8000 &7fffffff &ffffffff &ffffff81 &ffffff80 &ffff8001 &ffff8000"),7,TOplToken::EConstant,TOplToken::ELong);

	test.Next(_L("Hex errors"));
	CheckErrors(badHexadecimals);
	
	test.Next(_L("Strings"));
	CheckLine(_S("\"\" \"abcd\" \"1234\" \"\"\"\""),4,TOplToken::EConstant, TOplToken::EString);
	
	test.Next(_L("String errors"));
	CheckErrors(badStrings);

	test.End();
	DestroyLex();
	__UHEAP_MARKEND;
	}

 
LOCAL_D TLineLexerError badCharacters[]=
	{
	{_S("~"),EErrBadCharacter,0},
	{_S("`"),EErrBadCharacter,0},
	{_S("!"),EErrBadCharacter,0},
	{_S("^"),EErrBadCharacter,0},
	{_S("["),EErrBadCharacter,0},
	{_S("]"),EErrBadCharacter,0},
	{_S("|"),EErrBadCharacter,0},
	{_S("\\"),EErrBadCharacter,0},
	{_S("'"),EErrBadCharacter,0},
	{_S("?"),EErrBadCharacter,0},
	{NULL,0,0}
	};

LOCAL_D TLineLexerError badPBN[]=
	{
	{_S("@"),EErrSyntax,0},
	{_S("@%"),EErrSyntax,0},
	{_S("@&"),EErrSyntax,0},
	{_S("@$"),EErrSyntax,0},
	{_S("@^("),EErrSyntax,0},
	{_S("@%( @"),EErrSyntax,4},
	{_S("@$( @%"),EErrSyntax,4},
	{_S("@( @&"),EErrSyntax,3},
	{_S("@$( @$"),EErrSyntax,4},
	{_S("@&( @^("),EErrSyntax,4},
	{NULL,0,0}
	};

void TTestLineLexer::Test4()
//
// Operators
//
	{
	
	__UHEAP_MARK;
	GetLex();
	
	test.Start(_L("Single character operators"));
	CheckLine(_S("<"),1,TOplToken::ELessThan,TOplToken::EBadType);
	CheckLine(_S(">"),1,TOplToken::EGreaterThan,TOplToken::EBadType);
	CheckLine(_S("="),1,TOplToken::EEqual,TOplToken::EBadType);
	CheckLine(_S("+"),1,TOplToken::EPlus,TOplToken::EBadType);
	CheckLine(_S("-"),1,TOplToken::EMinus,TOplToken::EBadType);
	CheckLine(_S("*"),1,TOplToken::EMultiply,TOplToken::EBadType);
	CheckLine(_S("/"),1,TOplToken::EDivide,TOplToken::EBadType);
	CheckLine(_S("%"),1,TOplToken::EPerc,TOplToken::EBadType);
	CheckLine(_S("("),1,TOplToken::EOpenBracket,TOplToken::EBadType);
	CheckLine(_S(")"),1,TOplToken::ECloseBracket,	TOplToken::EBadType);

	test.Next(_L("Double character operators"));
	CheckLine(_S("<="),1,TOplToken::ELessThanEq,TOplToken::EBadType);
	CheckLine(_S(">="),1,TOplToken::EGreaterThanEq,TOplToken::EBadType);
	CheckLine(_S("<>"),1,TOplToken::ENotEqual,TOplToken::EBadType);
	CheckLine(_S("**"),1,TOplToken::EPower,TOplToken::EBadType);
	
	test.Next(_L("Text operators"));
	CheckLine(_S("and AND aNd"),3,TOplToken::EAnd,TOplToken::EBadType);
	CheckLine(_S("or OR oR"),3,TOplToken::EOr,TOplToken::EBadType);
	CheckLine(_S("not NOT NoT"),3,TOplToken::ENot,TOplToken::EBadType);
	
	test.Next(_L("Punctuation"));
	CheckLine(_S(":"),1,TOplToken::EColon,TOplToken::EBadType);
	CheckLine(_S(";"),1,TOplToken::ESemiColon,TOplToken::EBadType);
	CheckLine(_S(","),1,TOplToken::EComma,TOplToken::EBadType);
	CheckLine(_S("#"),1,TOplToken::EHash,TOplToken::EBadType);
	

	test.Next(_L("Bad characters"));
	CheckErrors(badCharacters);
		

	test.Next(_L("Proc by name"));
	CheckLine(_S("@%("),1,TOplToken::EProcByName,TOplToken::EWord);
	CheckLine(_S("@&("),1,TOplToken::EProcByName,TOplToken::ELong);
	CheckLine(_S("@("),1,TOplToken::EProcByName,TOplToken::EReal);
	CheckLine(_S("@$("),1,TOplToken::EProcByName,TOplToken::EString);

	test.Next(_L("Bad PBN"));
	CheckErrors(badPBN);

	test.End();
	DestroyLex();
	__UHEAP_MARKEND;
	}


LOCAL_D TLineLexerError badProcs[]=
	{
	{_S("a%%:"),EErrBadSuffices,0},
	{_S("A%::"),EErrBadSuffices,0},
	{_S("fedcba9876543210fedcba9876543210%:"),EErrIdentifierTooLong,0},
	{_S("fedcba9876543210fedcba9876543210a:"),EErrIdentifierTooLong,0},
	{_S("a1234567890123456789012345678901%:"),EErrIdentifierTooLong,0},
	{_S("a12345678901234567890123456789012:"),EErrIdentifierTooLong,0},
	{_S("A%: a%%:"),EErrBadSuffices,4},
	{_S("a%: A%::"),EErrBadSuffices,4},
	{_S("FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210\
FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210\
FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210\
FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210"),EErrIdentifierTooLong,0},
	{NULL,0,0}
	};

void TTestLineLexer::Test5()
//
// Identifiers - mostly fail for the calculator.
// Allows memory names and procedure calls.
// 
	{
	__UHEAP_MARK;
	GetLex();

	test.Start(_L("Procedure Names"));
	CheckLine(_S("a%: a1%: abcdefg%: a234567%: 

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?