home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 November / Chip_2002-11_cd1.bin / zkuste / delphi / kompon / d456 / CAJSCRPT.ZIP / ifps3 / ifps3utl.pas < prev    next >
Pascal/Delphi Source File  |  2002-08-26  |  26KB  |  1,038 lines

  1. {This unit contains types and functions used by the compiler and executer}
  2. unit ifps3utl;
  3. {$I ifps3_def.inc}
  4. {
  5.  
  6. Innerfuse Pascal Script III
  7. Copyright (C) 2000-2002 by Carlo Kok (ck@carlo-kok.com)
  8.  
  9. }
  10.  
  11. interface
  12.  
  13. const
  14.   {Maximum number of items in a list}
  15.   MaxListSize = Maxint div 16;
  16.  
  17. type
  18.   {PPointerList is pointing to an array of pointers}
  19.   PPointerList = ^TPointerList;
  20.   {An array of pointers}
  21.   TPointerList = array[0..MaxListSize - 1] of Pointer;
  22.  
  23.   {TIfList is the list class used in IFPS}
  24.   TIfList = class(TObject)
  25.   private
  26.     FCapacity: Cardinal;
  27.     FCount: Cardinal;
  28.     FData: PPointerList;
  29.     {$IFNDEF NOSMARTLIST}
  30.     FCheckCount: Cardinal;
  31.     {$ENDIF}
  32.   public
  33.     {$IFNDEF NOSMARTLIST}
  34.     {Recreate the list}
  35.     procedure Recreate;
  36.     {$ENDIF}
  37.     {create}
  38.     constructor Create;
  39.     {destroy}
  40.     destructor Destroy; override;
  41.     {Contains the number of items in the list}
  42.     property Count: Cardinal read FCount;
  43.     {Return item no Nr} 
  44.     function GetItem(Nr: Cardinal): Pointer;
  45.     {Set item no NR}
  46.     procedure SetItem(Nr: Cardinal; P: Pointer);
  47.     {Add an item}
  48.     procedure Add(P: Pointer);
  49.     {Add a block of items}
  50.     procedure AddBlock(List: PPointerList; Count: Longint);
  51.     {Remove an item}
  52.     procedure Remove(P: Pointer);
  53.     {Remove an item}
  54.     procedure Delete(Nr: Cardinal);
  55.     {Clear the list}
  56.     procedure Clear; virtual;
  57.   end;
  58.  
  59.   TIfStringList = class(TObject)
  60.   private
  61.     List: TIfList;
  62.   public
  63.     {Returns the number of items in the list}
  64.     function Count: LongInt;
  65.     {Return item no nr}
  66.     function GetItem(Nr: LongInt): string;
  67.     {Set item no nr}
  68.     procedure SetItem(Nr: LongInt; const s: string);
  69.     {Add an item to the list}
  70.     procedure Add(const P: string);
  71.     {Delete item no NR}
  72.     procedure Delete(NR: LongInt);
  73.     {Clear the list}
  74.     procedure Clear;
  75.     {create} 
  76.     constructor Create;
  77.     {destroy}
  78.     destructor Destroy; override;
  79.   end;
  80.  
  81.   
  82. type
  83.   {TIFPasToken is used to store the type of the current token}
  84.   TIfPasToken = (
  85.     CSTI_EOF,
  86.   {Items that are used internally}
  87.     CSTIINT_Comment,
  88.     CSTIINT_WhiteSpace,
  89.   {Tokens}
  90.     CSTI_Identifier,
  91.     CSTI_SemiColon,
  92.     CSTI_Comma,
  93.     CSTI_Period,
  94.     CSTI_Colon,
  95.     CSTI_OpenRound,
  96.     CSTI_CloseRound,
  97.     CSTI_OpenBlock,
  98.     CSTI_CloseBlock,
  99.     CSTI_Assignment,
  100.     CSTI_Equal,
  101.     CSTI_NotEqual,
  102.     CSTI_Greater,
  103.     CSTI_GreaterEqual,
  104.     CSTI_Less,
  105.     CSTI_LessEqual,
  106.     CSTI_Plus,
  107.     CSTI_Minus,
  108.     CSTI_Divide,
  109.     CSTI_Multiply,
  110.     CSTI_Integer,
  111.     CSTI_Real,
  112.     CSTI_String,
  113.     CSTI_Char,
  114.     CSTI_HexInt,
  115.     CSTI_AddressOf,
  116.     CSTI_Dereference,
  117.   {Identifiers}
  118.     CSTII_and,
  119.     CSTII_array,
  120.     CSTII_begin,
  121.     CSTII_case,
  122.     CSTII_const,
  123.     CSTII_div,
  124.     CSTII_do,
  125.     CSTII_downto,
  126.     CSTII_else,
  127.     CSTII_end,
  128.     CSTII_for,
  129.     CSTII_function,
  130.     CSTII_if,
  131.     CSTII_in,
  132.     CSTII_mod,
  133.     CSTII_not,
  134.     CSTII_of,
  135.     CSTII_or,
  136.     CSTII_procedure,
  137.     CSTII_program,
  138.     CSTII_repeat,
  139.     CSTII_record,
  140.     CSTII_set,
  141.     CSTII_shl,
  142.     CSTII_shr,
  143.     CSTII_then,
  144.     CSTII_to,
  145.     CSTII_type,
  146.     CSTII_until,
  147.     CSTII_uses,
  148.     CSTII_var,
  149.     CSTII_while,
  150.     CSTII_with,
  151.     CSTII_xor,
  152.     CSTII_exit,
  153.     CSTII_break,
  154.     CSTII_class,
  155.     CSTII_constructor,
  156.     CSTII_destructor,
  157.     CSTII_inherited,
  158.     CSTII_private,
  159.     CSTII_public,
  160.     CSTII_published,
  161.     CSTII_protected,
  162.     CSTII_property,
  163.     CSTII_virtual,
  164.     CSTII_override,
  165.     CSTII_As,
  166.     CSTII_Is,
  167.     CSTII_Unit,
  168.     CSTII_Continue,
  169.     CSTII_Try,
  170.     CSTII_Except,
  171.     CSTII_Finally,
  172.     CSTII_External,
  173.     CSTII_Forward,
  174.     CSTII_Export,
  175.     CSTII_Label,
  176.     CSTII_Goto,
  177.     CSTII_Chr,
  178.     CSTII_Ord,
  179.     CSTII_Interface,
  180.     CSTII_Implementation
  181.     );
  182.   {TIFParserErrorKind is used to store the parser error}
  183.   TIFParserErrorKind = (iNoError, iCommentError, iStringError, iCharError, iSyntaxError);
  184.   TIFParserErrorEvent = procedure (Parser: TObject; Kind: TIFParserErrorKind; Position: Cardinal) of object;
  185.  
  186.   {TIfPacalParser is the parser used to parse the current script}
  187.   TIfPascalParser = class(TObject)
  188.   private
  189.     FData: string;
  190.     FText: PChar;
  191.     FRealPosition, FTokenLength: Cardinal;
  192.     FTokenId: TIfPasToken;
  193.     FToken: string;
  194.     FOriginalToken: string;
  195.     FParserError: TIFParserErrorEvent;
  196.     // only applicable when Token in [CSTI_Identifier, CSTI_Integer, CSTI_Real, CSTI_String, CSTI_Char, CSTI_HexInt]
  197.   public
  198.     {Go to the next token}
  199.     procedure Next;
  200.     {Return the token in case it is a string, char, integer, number or identifier}
  201.     property GetToken: string read FToken;
  202.     {Return the token but do not uppercase it}
  203.     property OriginalToken: string read FOriginalToken;
  204.     {The current token position}
  205.     property CurrTokenPos: Cardinal read FRealPosition;
  206.     {The current token ID}
  207.     property CurrTokenID: TIFPasToken read FTokenId;
  208.     {Load a script}
  209.     procedure SetText(const Data: string);
  210.     {Parser error event will be called on (syntax) errors in the script}
  211.     property OnParserError: TIFParserErrorEvent read FParserError write FParserError;
  212.   end;
  213. {Convert a float to a string}
  214. function FloatToStr(E: Extended): string;
  215. {Fast lowercase}
  216. function FastLowerCase(const s: String): string;
  217. {Return the first word of a string}
  218. function Fw(const S: string): string;
  219. {Integer to string conversion}
  220. function IntToStr(I: LongInt): string;
  221. {String to integer}
  222. function StrToIntDef(const S: string; Def: LongInt): LongInt;
  223. {String to integer}
  224. function StrToInt(const S: string): LongInt;
  225. {Fast uppercase}
  226. function FastUpperCase(const s: String): string;
  227. {Get the first word and remove it}
  228. function GRFW(var s: string): string;
  229.  
  230. implementation
  231.  
  232. function GRFW(var s: string): string;
  233. var
  234.   l: Longint;
  235. begin
  236.   l := 1;
  237.   while l <= Length(s) do
  238.   begin
  239.     if s[l] = ' ' then
  240.     begin
  241.       Result := copy(s, 1, l - 1);
  242.       Delete(s, 1, l);
  243.       exit;
  244.     end;
  245.     l := l + 1;
  246.   end;
  247.   Result := s;
  248.   s := '';
  249. end;
  250. //-------------------------------------------------------------------
  251.  
  252. function IntToStr(I: LongInt): string;
  253. var
  254.   s: string;
  255. begin
  256.   Str(i, s);
  257.   IntToStr := s;
  258. end;
  259. //-------------------------------------------------------------------
  260.  
  261. function FloatToStr(E: Extended): string;
  262. var
  263.   s: string;
  264. begin
  265.   Str(e:0:12, s);
  266.   result := s;
  267. end;
  268.  
  269. function StrToInt(const S: string): LongInt;
  270. var
  271.   e: Integer;
  272.   Res: LongInt;
  273. begin
  274.   Val(S, Res, e);
  275.   if e <> 0 then
  276.     StrToInt := -1
  277.   else
  278.     StrToInt := Res;
  279. end;
  280. //-------------------------------------------------------------------
  281.  
  282. function StrToIntDef(const S: string; Def: LongInt): LongInt;
  283. var
  284.   e: Integer;
  285.   Res: LongInt;
  286. begin
  287.   Val(S, Res, e);
  288.   if e <> 0 then
  289.     StrToIntDef := Def
  290.   else
  291.     StrToIntDef := Res;
  292. end;
  293. //-------------------------------------------------------------------
  294.  
  295. constructor TIfList.Create;
  296. begin
  297.   inherited Create;
  298.   FCount := 0;
  299.   FCapacity := 16;
  300.   {$IFNDEF NOSMARTLIST}
  301.   FCheckCount := 0;
  302.   {$ENDIF}
  303.   GetMem(FData, 64);
  304. end;
  305.  
  306. const
  307.   FCapacityInc = 32;
  308. {$IFNDEF NOSMARTLIST}
  309.   FMaxCheckCount = (FCapacityInc div 4) * 16;
  310. {$ENDIF}
  311.  
  312. function MM(i1,i2: Integer): Integer;
  313. begin
  314.   if ((i1 div i2) * i2) < i1 then
  315.     mm := (i1 div i2 + 1) * i2
  316.   else
  317.     mm := (i1 div i2) * i2;
  318. end;
  319.  
  320. {$IFNDEF NOSMARTLIST}
  321. procedure TIfList.Recreate;
  322. var
  323.   NewData: PPointerList;
  324.   NewCapacity: Cardinal;
  325.   I: Longint;
  326.  
  327. begin
  328.  
  329.   FCheckCount := 0;
  330.   NewCapacity := mm(FCount, FCapacityInc);
  331.   if NewCapacity < 64 then NewCapacity := 64;
  332.   GetMem(NewData, NewCapacity * 4);
  333.   for I := 0 to Longint(FCount) -1 do
  334.   begin
  335.     NewData^[i] := FData^[I];
  336.   end;
  337.   FreeMem(FData, FCapacity * 4);
  338.   FData := NewData;
  339.   FCapacity := NewCapacity;
  340. end;
  341. {$ENDIF}
  342.  
  343. //-------------------------------------------------------------------
  344.  
  345. procedure TIfList.Add(P: Pointer);
  346. begin
  347.   if FCount >= FCapacity then
  348.   begin
  349.     Inc(FCapacity, FCapacityInc);// := FCount + 1;
  350.     ReAllocMem(FData, FCapacity shl 2);
  351.   end;
  352.   FData[FCount] := P; // Instead of SetItem
  353.   Inc(FCount);
  354.   Inc(FCheckCount);
  355. {$IFNDEF NOSMARTLIST}
  356.   if FCheckCount > FMaxCheckCount then Recreate;
  357. {$ENDIF}
  358. end;
  359.  
  360. procedure TIfList.AddBlock(List: PPointerList; Count: Longint);
  361. var
  362.   L: Longint;
  363.  
  364. begin
  365.   if Longint(FCount) + Count > Longint(FCapacity) then
  366.   begin
  367.     Inc(FCapacity, mm(Count, FCapacityInc));
  368.     ReAllocMem(FData, FCapacity shl 2);
  369.   end;
  370.   for L := 0 to Count -1 do
  371.   begin
  372.     FData^[FCount] := List^[L];
  373.     Inc(FCount);
  374.   end;
  375. {$IFNDEF NOSMARTLIST}
  376.   Inc(FCheckCount);
  377.   if FCheckCount > FMaxCheckCount then Recreate;
  378. {$ENDIF}
  379. end;
  380.  
  381.  
  382. //-------------------------------------------------------------------
  383.  
  384. procedure TIfList.Delete(Nr: Cardinal);
  385. begin
  386.   if FCount = 0 then Exit;
  387.   if Nr < FCount then
  388.   begin
  389.     Move(FData[Nr + 1], FData[Nr], (FCount - Nr) * 4);
  390.     Dec(FCount);
  391. {$IFNDEF NOSMARTLIST}
  392.     Inc(FCheckCount);
  393.     if FCheckCount > FMaxCheckCount then Recreate;
  394. {$ENDIF}
  395.   end;
  396. end;
  397. //-------------------------------------------------------------------
  398.  
  399. procedure TIfList.Remove(P: Pointer);
  400. var
  401.   I: Cardinal;
  402. begin
  403.   if FCount = 0 then Exit;
  404.   I := 0;
  405.   while I < FCount do
  406.   begin
  407.     if FData[I] = P then
  408.     begin
  409.       Delete(I);
  410.       Exit;
  411.     end;
  412.     Inc(I);
  413.   end;
  414. end;
  415. //-------------------------------------------------------------------
  416.  
  417. procedure TIfList.Clear;
  418. begin
  419.   FCount := 0;
  420. {$IFNDEF NOSMARTLIST}
  421.   Recreate;
  422. {$ENDIF}
  423. end;
  424. //-------------------------------------------------------------------
  425.  
  426. destructor TIfList.Destroy;
  427. begin
  428.   FreeMem(FData, FCapacity * 4);
  429.   inherited Destroy;
  430. end;
  431. //-------------------------------------------------------------------
  432.  
  433. procedure TIfList.SetItem(Nr: Cardinal; P: Pointer);
  434. begin
  435.   if (FCount = 0) or (Nr >= FCount) then
  436.     Exit;
  437.   FData[Nr] := P;
  438. end;
  439. //-------------------------------------------------------------------
  440.  
  441. function TifList.GetItem(Nr: Cardinal): Pointer;  {12}
  442. begin
  443.   if Nr < FCount then
  444.     GetItem := FData[Nr]
  445.   else
  446.     GetItem := nil;
  447. end;
  448. //-------------------------------------------------------------------
  449.  
  450. function TIfStringList.Count: LongInt;
  451. begin
  452.   count := List.count;
  453. end;
  454. type pStr = ^string;
  455.  
  456. //-------------------------------------------------------------------
  457.  
  458. function TifStringList.GetItem(Nr: LongInt): string;
  459. var
  460.   S: PStr;
  461. begin
  462.   s := List.GetItem(Nr);
  463.   if s = nil then
  464.     Result := ''
  465.   else
  466.  
  467.     Result := s^;
  468. end;
  469. //-------------------------------------------------------------------
  470.  
  471. procedure TifStringList.SetItem(Nr: LongInt; const s: string);
  472. var
  473.   p: PStr;
  474. begin
  475.   p := List.GetItem(Nr);
  476.   if p = nil
  477.     then
  478.     Exit;
  479.   p^ := s;
  480. end;
  481. //-------------------------------------------------------------------
  482.  
  483. procedure TifStringList.Add(const P: string);
  484. var
  485.   w: PStr;
  486. begin
  487.   new(w);
  488.   w^ := p;
  489.   List.Add(w);
  490. end;
  491. //-------------------------------------------------------------------
  492.  
  493. procedure TifStringList.Delete(NR: LongInt);
  494. var
  495.   W: PStr;
  496. begin
  497.   W := list.getitem(nr);
  498.   if w<>nil then
  499.   begin
  500.     dispose(w);
  501.   end;
  502.   list.Delete(Nr);
  503. end;
  504.  
  505. procedure TifStringList.Clear;
  506. begin
  507.   while List.Count > 0 do Delete(0);
  508. end;
  509.  
  510. constructor TifStringList.Create;
  511. begin
  512.   inherited Create;
  513.   List := TIfList.Create;
  514. end;
  515.  
  516. destructor TifStringList.Destroy;
  517. begin
  518.   while List.Count > 0 do
  519.     Delete(0);
  520.   List.Destroy;
  521.   inherited Destroy;
  522. end;
  523.  
  524. //-------------------------------------------------------------------
  525.  
  526.  
  527. function Fw(const S: string): string; //  First word
  528. var
  529.   x: integer;
  530. begin
  531.   x := pos(' ', s);
  532.   if x > 0
  533.     then Fw := Copy(S, 1, x - 1)
  534.   else Fw := S;
  535. end;
  536. //-------------------------------------------------------------------
  537. function FastUpperCase(const s: String): string;
  538. {Fast uppercase}
  539. var
  540.   I: Integer;
  541.   C: Char;
  542. begin
  543.   Result := S;
  544.   I := Length(Result);
  545.   while I > 0 do
  546.   begin
  547.     C := Result[I];
  548.     if C in [#97..#122] then
  549.       Dec(Byte(Result[I]), 32);
  550.     Dec(I);
  551.   end;
  552. end;
  553. function FastLowerCase(const s: String): string;
  554. {Fast lowercase}
  555. var
  556.   I: Integer;
  557.   C: Char;
  558. begin
  559.   Result := S;
  560.   I := Length(Result);
  561.   while I > 0 do
  562.   begin
  563.     C := Result[I];
  564.     if C in [#65..#90] then
  565.       Inc(Byte(Result[I]), 32);
  566.     Dec(I);
  567.   end;
  568. end;
  569. //-------------------------------------------------------------------
  570.  
  571. type
  572.   TRTab = record
  573.     name: string;
  574.     c: TIfPasToken;
  575.   end;
  576.  
  577.  
  578. const
  579.   KEYWORD_COUNT = 63;
  580.   LookupTable: array[0..KEYWORD_COUNT - 1] of TRTab = (
  581.       (name: 'AND'; c: CSTII_and),
  582.       (name: 'ARRAY'; c: CSTII_array),
  583.       (name: 'AS'; c: CSTII_as),
  584.       (name: 'BEGIN'; c: CSTII_begin),
  585.       (name: 'BREAK'; c: CSTII_break),
  586.       (name: 'CASE'; c: CSTII_case),
  587.       (name: 'CHR'; c: CSTII_chr),
  588.       (name: 'CLASS'; c: CSTII_class),
  589.       (name: 'CONST'; c: CSTII_const),
  590.       (name: 'CONSTRUCTOR'; c: CSTII_constructor),
  591.       (name: 'CONTINUE'; c: CSTII_Continue),
  592.       (name: 'DESTRUCTOR'; c: CSTII_destructor),
  593.       (name: 'DIV'; c: CSTII_div),
  594.       (name: 'DO'; c: CSTII_do),
  595.       (name: 'DOWNTO'; c: CSTII_downto),
  596.       (name: 'ELSE'; c: CSTII_else),
  597.       (name: 'END'; c: CSTII_end),
  598.       (name: 'EXCEPT'; c: CSTII_except),
  599.       (name: 'EXIT'; c: CSTII_exit),
  600.       (name: 'EXPORT'; c: CSTII_Export),
  601.       (name: 'EXTERNAL'; c: CSTII_External),
  602.       (name: 'FINALLY'; c: CSTII_finally),
  603.       (name: 'FOR'; c: CSTII_for),
  604.       (name: 'FORWARD'; c: CSTII_Forward),
  605.       (name: 'FUNCTION'; c: CSTII_function),
  606.       (name: 'GOTO'; c: CSTII_Goto),
  607.       (name: 'IF'; c: CSTII_if),
  608.       (name: 'IMPLEMENTATION'; c: CSTII_Implementation),
  609.       (name: 'IN'; c: CSTII_in),
  610.       (name: 'INHERITED'; c: CSTII_inherited),
  611.       (name: 'INTERFACE'; c: CSTII_Interface),
  612.       (name: 'IS'; c: CSTII_is),
  613.       (name: 'LABEL'; c: CSTII_Label),
  614.       (name: 'MOD'; c: CSTII_mod),
  615.       (name: 'NOT'; c: CSTII_not),
  616.       (name: 'OF'; c: CSTII_of),
  617.       (name: 'OR'; c: CSTII_or),
  618.       (name: 'ORD'; c: CSTII_ord),
  619.       (name: 'OVERRIDE'; c: CSTII_override),
  620.       (name: 'PRIVATE'; c: CSTII_private),
  621.       (name: 'PROCEDURE'; c: CSTII_procedure),
  622.       (name: 'PROGRAM'; c: CSTII_program),
  623.       (name: 'PROPERTY'; c: CSTII_property),
  624.       (name: 'PROTECTED'; c: CSTII_protected),
  625.       (name: 'PUBLIC'; c: CSTII_public),
  626.       (name: 'PUBLISHED'; c: CSTII_published),
  627.       (name: 'RECORD'; c: CSTII_record),
  628.       (name: 'REPEAT'; c: CSTII_repeat),
  629.       (name: 'SET'; c: CSTII_set),
  630.       (name: 'SHL'; c: CSTII_shl),
  631.       (name: 'SHR'; c: CSTII_shr),
  632.       (name: 'THEN'; c: CSTII_then),
  633.       (name: 'TO'; c: CSTII_to),
  634.       (name: 'TRY'; c: CSTII_try),
  635.       (name: 'TYPE'; c: CSTII_type),
  636.       (name: 'UNIT'; c: CSTII_Unit),
  637.       (name: 'UNTIL'; c: CSTII_until),
  638.       (name: 'USES'; c: CSTII_uses),
  639.       (name: 'VAR'; c: CSTII_var),
  640.       (name: 'VIRTUAL'; c: CSTII_virtual),
  641.       (name: 'WHILE'; c: CSTII_while),
  642.       (name: 'WITH'; c: CSTII_with),
  643.       (name: 'XOR'; c: CSTII_xor));
  644.  
  645. procedure TIfPascalParser.Next;
  646. var
  647.   Err: TIFParserErrorKind;
  648.   function CheckReserved(Const S: ShortString; var CurrTokenId: TIfPasToken): Boolean;
  649.   var
  650.     L, H, I: LongInt;
  651.     J: Char;
  652.     SName: ShortString;
  653.   begin
  654.     L := 0;
  655.     J := S[0];
  656.     H := KEYWORD_COUNT-1;
  657.     while L <= H do
  658.     begin
  659.       I := (L + H) shr 1;
  660.       SName := LookupTable[i].Name;
  661.       if J = SName[0] then
  662.       begin
  663.         if S = SName then
  664.         begin
  665.           CheckReserved := True;
  666.           CurrTokenId := LookupTable[I].c;
  667.           Exit;
  668.         end;
  669.         if S > SName then
  670.           L := I + 1
  671.         else
  672.           H := I - 1;
  673.       end else
  674.         if S > SName then
  675.           L := I + 1
  676.         else
  677.           H := I - 1;
  678.     end;
  679.     CheckReserved := False;
  680.   end;
  681.   //-------------------------------------------------------------------
  682.  
  683.   function GetToken(CurrTokenPos, CurrTokenLen: Cardinal): string;
  684.   var
  685.     s: string;
  686.   begin
  687.     SetLength(s, CurrTokenLen);
  688.     Move(FText[CurrTokenPos], S[1], CurrtokenLen);
  689.     GetToken := s;
  690.   end;
  691.  
  692.   function ParseToken(var CurrTokenPos, CurrTokenLen: Cardinal; var CurrTokenId: TIfPasToken): TIFParserErrorKind;
  693.   {Parse the token}
  694.   var
  695.     ct, ci: Cardinal;
  696.     hs: Boolean;
  697.   begin
  698.     ParseToken := iNoError;
  699.     ct := CurrTokenPos;
  700.     case FText[ct] of
  701.       #0:
  702.         begin
  703.           CurrTokenId := CSTI_EOF;
  704.           CurrTokenLen := 0;
  705.         end;
  706.       'A'..'Z', 'a'..'z', '_':
  707.         begin
  708.           ci := ct + 1;
  709.           while (FText[ci] in ['_', '0'..'9', 'a'..'z', 'A'..'Z']) do begin
  710.             Inc(ci);
  711.           end;
  712.           CurrTokenLen := ci - ct;
  713.           if not CheckReserved(FastUppercase(GetToken(CurrTokenPos, CurrtokenLen)), CurrTokenId) then
  714.           begin
  715.             CurrTokenId := CSTI_Identifier;
  716.           end;
  717.         end;
  718.       '$':
  719.         begin
  720.           ci := ct + 1;
  721.  
  722.           while (FText[ci] in ['0'..'9', 'a'..'f', 'A'..'F'])
  723.             do Inc(ci);
  724.  
  725.           CurrTokenId := CSTI_HexInt;
  726.           CurrTokenLen := ci - ct;
  727.         end;
  728.  
  729.       '0'..'9':
  730.         begin
  731.           hs := False;
  732.           ci := ct;
  733.           while (FText[ci] in ['0'..'9']) do
  734.           begin
  735.             Inc(ci);
  736.             if (FText[ci] = '.') and (not hs) then
  737.             begin
  738.               if FText[ci+1] = '.' then break;
  739.               hs := True;
  740.               Inc(ci);
  741.             end;
  742.           end;
  743.  
  744.           if hs
  745.             then CurrTokenId := CSTI_Real
  746.           else CurrTokenId := CSTI_Integer;
  747.  
  748.           CurrTokenLen := ci - ct;
  749.         end;
  750.  
  751.  
  752.       #39:
  753.         begin
  754.           ci := ct + 1;
  755.           while (FText[ci] <> #0) and (FText[ci] <> #13) and
  756.             (FText[ci] <> #10) and (FText[ci] <> #39)
  757.             do begin
  758.             Inc(ci);
  759.           end;
  760.           if FText[ci] = #39 then
  761.             CurrTokenId := CSTI_String
  762.           else
  763.           begin
  764.             CurrTokenId := CSTI_String;
  765.             ParseToken := iStringError;
  766.           end;
  767.           CurrTokenLen := ci - ct + 1;
  768.         end;
  769.       '#':
  770.         begin
  771.           ci := ct + 1;
  772.           if FText[ci] = '$' then
  773.           begin
  774.             inc(ci);
  775.             while (FText[ci] in ['A'..'F', 'a'..'f', '0'..'9']) do begin
  776.               Inc(ci);
  777.             end;
  778.             CurrTokenId := CSTI_Char;
  779.             CurrTokenLen := ci - ct;
  780.           end else
  781.           begin
  782.             while (FText[ci] in ['0'..'9']) do begin
  783.               Inc(ci);
  784.             end;
  785.             if FText[ci] in ['A'..'Z', 'a'..'z', '_'] then
  786.             begin
  787.               ParseToken := iCharError;
  788.               CurrTokenId := CSTI_Char;
  789.             end else
  790.               CurrTokenId := CSTI_Char;
  791.             CurrTokenLen := ci - ct;
  792.           end;
  793.         end;
  794.       '=':
  795.         begin
  796.           CurrTokenId := CSTI_Equal;
  797.           CurrTokenLen := 1;
  798.         end;
  799.       '>':
  800.         begin
  801.           if FText[ct + 1] = '=' then
  802.           begin
  803.             CurrTokenid := CSTI_GreaterEqual;
  804.             CurrTokenLen := 2;
  805.           end else
  806.           begin
  807.             CurrTokenid := CSTI_Greater;
  808.             CurrTokenLen := 1;
  809.           end;
  810.         end;
  811.       '<':
  812.         begin
  813.           if FText[ct + 1] = '=' then
  814.           begin
  815.             CurrTokenId := CSTI_LessEqual;
  816.             CurrTokenLen := 2;
  817.           end else
  818.             if FText[ct + 1] = '>' then
  819.             begin
  820.               CurrTokenId := CSTI_NotEqual;
  821.               CurrTokenLen := 2;
  822.             end else
  823.             begin
  824.               CurrTokenId := CSTI_Less;
  825.               CurrTokenLen := 1;
  826.             end;
  827.         end;
  828.       ')':
  829.         begin
  830.           CurrTokenId := CSTI_CloseRound;
  831.           CurrTokenLen := 1;
  832.         end;
  833.       '(':
  834.         begin
  835.           if FText[ct + 1] = '*' then
  836.           begin
  837.             ci := ct + 1;
  838.             while (FText[ci] <> #0) do begin
  839.               if (FText[ci] = '*') and (FText[ci + 1] = ')') then
  840.                 Break;
  841.               Inc(ci);
  842.             end;
  843.             if (FText[ci] = #0) then
  844.             begin
  845.               CurrTokenId := CSTIINT_Comment;
  846.               ParseToken := iCommentError;
  847.             end else
  848.             begin
  849.               CurrTokenId := CSTIINT_Comment;
  850.               Inc(ci, 2);
  851.             end;
  852.             CurrTokenLen := ci - ct;
  853.           end
  854.           else
  855.           begin
  856.             CurrTokenId := CSTI_OpenRound;
  857.             CurrTokenLen := 1;
  858.           end;
  859.         end;
  860.       '[':
  861.         begin
  862.           CurrTokenId := CSTI_OpenBlock;
  863.           CurrTokenLen := 1;
  864.         end;
  865.       ']':
  866.         begin
  867.           CurrTokenId := CSTI_CloseBlock;
  868.           CurrTokenLen := 1;
  869.         end;
  870.       ',':
  871.         begin
  872.           CurrTokenId := CSTI_Comma;
  873.           CurrTokenLen := 1;
  874.         end;
  875.       '.':
  876.         begin
  877.           CurrTokenId := CSTI_Period;
  878.           CurrTokenLen := 1;
  879.         end;
  880.       '@':
  881.         begin
  882.           CurrTokenId := CSTI_AddressOf;
  883.           CurrTokenLen := 1;
  884.         end;
  885.       '^':
  886.         begin
  887.           CurrTokenId := CSTI_Dereference;
  888.           CurrTokenLen := 1;
  889.         end;
  890.       ';':
  891.         begin
  892.           CurrTokenId := CSTI_Semicolon;
  893.           CurrTokenLen := 1;
  894.         end;
  895.       ':':
  896.         begin
  897.           if FText[ct + 1] = '=' then
  898.           begin
  899.             CurrTokenId := CSTI_Assignment;
  900.             CurrTokenLen := 2;
  901.           end else
  902.           begin
  903.             CurrTokenId := CSTI_Colon;
  904.             CurrTokenLen := 1;
  905.           end;
  906.         end;
  907.       '+':
  908.         begin
  909.           CurrTokenId := CSTI_Plus;
  910.           CurrTokenLen := 1;
  911.         end;
  912.       '-':
  913.         begin
  914.           CurrTokenId := CSTI_Minus;
  915.           CurrTokenLen := 1;
  916.         end;
  917.       '*':
  918.         begin
  919.           CurrTokenId := CSTI_Multiply;
  920.           CurrTokenLen := 1;
  921.         end;
  922.       '/':
  923.         begin
  924.           if FText[ct + 1] = '/' then
  925.           begin
  926.             ci := ct + 1;
  927.             while (FText[ci] <> #0) and (FText[ci] <> #13) and
  928.               (FText[ci] <> #10) do begin
  929.               Inc(ci);
  930.             end;
  931.             if (FText[ci] = #0) then
  932.             begin
  933.               CurrTokenId := CSTIINT_Comment;
  934.               ParseToken := iCommentError;
  935.             end else
  936.             begin
  937.               if FText[ci + 1] = #10 then
  938.                 Inc(ci) else
  939.  
  940.                 if FText[ci + 1] = #13 then
  941.                   Inc(ci);
  942.               CurrTokenId := CSTIINT_Comment;
  943.             end;
  944.             CurrTokenLen := ci - ct + 1;
  945.           end else
  946.           begin
  947.             CurrTokenId := CSTI_Divide;
  948.             CurrTokenLen := 1;
  949.           end;
  950.         end;
  951.       #32, #9, #13, #10:
  952.         begin
  953.           ci := ct + 1;
  954.           while (FText[ci] in [#32, #9, #13, #10]) do begin
  955.             Inc(ci);
  956.           end;
  957.           CurrTokenId := CSTIINT_WhiteSpace;
  958.           CurrTokenLen := ci - ct;
  959.         end;
  960.       '{':
  961.         begin
  962.           ci := ct + 1;
  963.           while (FText[ci] <> #0) and (FText[ci] <> '}') do begin
  964.             Inc(ci);
  965.           end;
  966.           if (FText[ci] = #0) then
  967.           begin
  968.             CurrTokenId := CSTIINT_Comment;
  969.             ParseToken := iCommentError;
  970.           end else
  971.             CurrTokenId := CSTIINT_Comment;
  972.           CurrTokenLen := ci - ct + 1;
  973.         end;
  974.     else
  975.       begin
  976.         ParseToken := iSyntaxError;
  977.         CurrTokenId := CSTIINT_Comment;
  978.         CurrTokenLen := 1;
  979.       end;
  980.     end;
  981.   end;
  982.   //-------------------------------------------------------------------
  983. begin
  984.   if FText = nil then
  985.   begin
  986.     FTokenLength := 0;
  987.     FRealPosition := 0;
  988.     FTokenId := CSTI_EOF;
  989.     Exit;
  990.   end;
  991.   repeat
  992.     FRealPosition := FRealPosition + FTokenLength;
  993.     Err := ParseToken(FRealPosition, FTokenLength, FTokenID);
  994.     if Err <> iNoError then
  995.     begin
  996.       FTokenLength := 0;
  997.       FTokenId := CSTI_EOF;
  998.       FToken := '';
  999.       FOriginalToken := '';
  1000.       if @FParserError <> nil then FParserError(Self, Err, FRealPosition);
  1001.       exit;
  1002.     end;
  1003.     case FTokenID of
  1004.       CSTIINT_Comment, CSTIINT_WhiteSpace: Continue;
  1005.       CSTI_Integer, CSTI_Real, CSTI_String, CSTI_Char, CSTI_HexInt:
  1006.         begin
  1007.           FOriginalToken := GetToken(FRealPosition, FTokenLength);
  1008.           FToken := FOriginalToken;
  1009.         end;
  1010.       CSTI_Identifier:
  1011.         begin
  1012.           FOriginalToken := GetToken(FRealPosition, FTokenLength);
  1013.           FToken := FastUppercase(FOriginalToken);
  1014.         end;
  1015.     else
  1016.       begin
  1017.         FOriginalToken := '';
  1018.         FToken := '';
  1019.       end;
  1020.     end;
  1021.     Break;
  1022.   until False;
  1023. end;
  1024.  
  1025. procedure TIfPascalParser.SetText(const Data: string);
  1026. begin
  1027.   FData := Data;
  1028.   FText := Pointer(FData);
  1029.   FTokenLength := 0;
  1030.   FRealPosition := 0;
  1031.   FTokenId := CSTI_EOF;
  1032.   Next;
  1033. end;
  1034.  
  1035. end.
  1036.  
  1037.  
  1038.