123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- unit utcExprParsScanner;
- {$mode objfpc}{$H+}
- interface
- uses
- Classes, SysUtils, punit, math, fpexprpars;
- procedure RegisterTests(aTop : PSuite);
- implementation
- uses typinfo;
- var
- FP: TFPExpressionScanner;
- FInvalidString: String;
- function TestExpressionScanner_SetUp : string;
- begin
- Result:='';
- FP := TFPExpressionScanner.Create;
- end;
- function TestExpressionScanner_TearDown : string;
- begin
- Result:='';
- FreeAndNil(FP);
- end;
- procedure AssertEqualsToken(Msg: String; AExpected, AActual: TTokenType);
- var
- S1, S2: String;
- begin
- S1 := TokenName(AExpected);
- S2 := GetEnumName(TypeInfo(TTokenType), Ord(AActual));
- AssertEquals(Msg, S1, S2);
- end;
- procedure TestString(const AString: String; AToken: TTokenType);
- begin
- FP.Source := AString;
- AssertEqualsToken('String "' + AString + '" results in token ' + TokenName(AToken), AToken, FP.GetToken);
- if not (FP.TokenType in [ttString, ttEOF]) then
- AssertEquals('String "' + AString + '" results in token string ' + TokenName(AToken), AString, FP.Token)
- else if FP.TokenType = ttString then
- AssertEquals('String "' + AString + '" results in token string ' + TokenName(AToken),
- StringReplace(AString, '''''', '''', [rfReplaceAll]),
- '''' + FP.Token + '''');
- end;
- function TestExpressionScanner_TestCreate: TTestString;
- begin
- Result := '';
- AssertEquals('Empty source', '', FP.Source);
- AssertEquals('Pos is zero', 0, FP.Pos);
- AssertEquals('CurrentChar is zero', #0, FP.CurrentChar);
- AssertEqualsToken('Current token type is EOF', ttEOF, FP.TokenType);
- AssertEquals('Current token is empty', '', FP.Token);
- end;
- function TestExpressionScanner_TestSetSource: TTestString;
- begin
- Result := '';
- FP.Source := 'Abc';
- FP.Source := '';
- AssertEquals('Empty source', '', FP.Source);
- AssertEquals('Pos is zero', 0, FP.Pos);
- AssertEquals('CurrentChar is zero', #0, FP.CurrentChar);
- AssertEqualsToken('Current token type is EOF', ttEOF, FP.TokenType);
- AssertEquals('Current token is empty', '', FP.Token);
- end;
- function TestExpressionScanner_TestWhiteSpace: TTestString;
- begin
- Result := '';
- TestString(' ', ttEOF);
- end;
- function TestExpressionScanner_TestTokens: TTestString;
- const
- TestStrings: array[TTokenType] of String =
- ('+', '-', '<', '>', '=', '/',
- 'mod', '*', '(', ')', '<=',
- '>=', '<>', '1', '''abc''', 'abc',
- ',', 'and', 'or', 'xor', 'true', 'false', 'not',
- 'if', 'case', '^', '');
- var
- t: TTokenType;
- begin
- Result := '';
- for t := Low(TTokenType) to High(TTokenType) do
- TestString(TestStrings[t], t);
- end;
- procedure DoInvalidNumber(AString: String);
- begin
- FInvalidString := AString;
- raise EExprScanner.Create('Invalid number');
- end;
- var
- TestProcToRun: TTestRunProc;
- function RunTestProc: TTestString;
- begin
- Result := '';
- if Assigned(TestProcToRun) then
- TestProcToRun;
- end;
- procedure DoTestInvalidNumberGG;
- begin
- DoInvalidNumber('$GG');
- end;
- procedure DoTestInvalidNumber88;
- begin
- DoInvalidNumber('&88');
- end;
- procedure DoTestInvalidNumber22;
- begin
- DoInvalidNumber('%22');
- end;
- procedure DoTestInvalidNumber11;
- begin
- DoInvalidNumber('1..1');
- end;
- procedure DoTestInvalidNumber1E;
- begin
- DoInvalidNumber('1.E--1');
- end;
- function TestExpressionScanner_TestNumber: TTestString;
- begin
- Result := '';
- TestString('123', ttNumber);
- TestString('$FF', ttNumber);
- TestString('&77', ttNumber);
- TestString('%11111111', ttNumber);
- TestString('123.4', ttNumber);
- TestString('123.E4', ttNumber);
- TestString('1.E4', ttNumber);
- TestString('1e-2', ttNumber);
- TestProcToRun := @DoTestInvalidNumberGG;
- AssertException('Invalid number "$GG"', EExprScanner, @RunTestProc);
- TestProcToRun := @DoTestInvalidNumber88;
- AssertException('Invalid number "&88"', EExprScanner, @RunTestProc);
- TestProcToRun := @DoTestInvalidNumber22;
- AssertException('Invalid number "%22"', EExprScanner, @RunTestProc);
- TestProcToRun := @DoTestInvalidNumber11;
- AssertException('Invalid number "1..1"', EExprScanner, @RunTestProc);
- TestProcToRun := @DoTestInvalidNumber1E;
- AssertException('Invalid number "1.E--1"', EExprScanner, @RunTestProc);
- end;
- procedure DoTestInvalidCharTilde;
- begin
- DoInvalidNumber('~');
- end;
- procedure DoTestInvalidCharHash;
- begin
- DoInvalidNumber('#');
- end;
- procedure DoTestInvalidCharDollar;
- begin
- DoInvalidNumber('$');
- end;
- function TestExpressionScanner_TestInvalidCharacter: TTestString;
- begin
- Result := '';
- TestProcToRun := @DoTestInvalidCharTilde;
- AssertException('Invalid character "~"', EExprScanner, @RunTestProc);
- TestProcToRun := @DoTestInvalidCharHash;
- AssertException('Invalid character "#"', EExprScanner, @RunTestProc);
- TestProcToRun := @DoTestInvalidCharDollar;
- AssertException('Invalid character "$"', EExprScanner, @RunTestProc);
- end;
- procedure DoTestUnterminatedString;
- begin
- DoInvalidNumber('''abc');
- end;
- function TestExpressionScanner_TestUnterminatedString: TTestString;
- begin
- Result := '';
- TestProcToRun := @DoTestUnterminatedString;
- AssertException('Unterminated string', EExprScanner, @RunTestProc);
- end;
- function TestExpressionScanner_TestQuotesInString: TTestString;
- begin
- Result := '';
- TestString('''That''''s it''', ttString);
- TestString('''''''s it''', ttString);
- TestString('''s it''''''', ttString);
- end;
- procedure TestIdentifier(const ASource, ATokenName: String);
- begin
- FP.Source := ASource;
- AssertEqualsToken('Token type', ttIdentifier, FP.GetToken);
- AssertEquals('Token name', ATokenName, FP.Token);
- end;
- function TestExpressionScanner_TestIdentifiers: TTestString;
- begin
- Result := '';
- TestIdentifier('a', 'a');
- TestIdentifier(' a', 'a');
- TestIdentifier('a ', 'a');
- TestIdentifier('a^b', 'a');
- TestIdentifier('a-b', 'a');
- TestIdentifier('a.b', 'a.b');
- TestIdentifier('"a b"', 'a b');
- TestIdentifier('c."a b"', 'c.a b');
- TestIdentifier('c."ab"', 'c.ab');
- end;
- procedure RegisterTests(aTop : PSuite);
- begin
- AddSuite('TExpressionScannerTests', @TestExpressionScanner_SetUp, @TestExpressionScanner_TearDown, aTop, True);
- AddTest('TestCreate', @TestExpressionScanner_TestCreate, 'TExpressionScannerTests');
- AddTest('TestSetSource', @TestExpressionScanner_TestSetSource, 'TExpressionScannerTests');
- AddTest('TestWhiteSpace', @TestExpressionScanner_TestWhiteSpace, 'TExpressionScannerTests');
- AddTest('TestTokens', @TestExpressionScanner_TestTokens, 'TExpressionScannerTests');
- AddTest('TestNumber', @TestExpressionScanner_TestNumber, 'TExpressionScannerTests');
- AddTest('TestInvalidCharacter', @TestExpressionScanner_TestInvalidCharacter, 'TExpressionScannerTests');
- AddTest('TestUnterminatedString', @TestExpressionScanner_TestUnterminatedString, 'TExpressionScannerTests');
- AddTest('TestQuotesInString', @TestExpressionScanner_TestQuotesInString, 'TExpressionScannerTests');
- AddTest('TestIdentifiers', @TestExpressionScanner_TestIdentifiers, 'TExpressionScannerTests');
- end;
- end.
|