home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 September / Chip_2001-09_cd1.bin / zkuste / delphi / kompon / d23456 / CAJSCRPT.ZIP / ifpasscript / ifs_utl.pas < prev    next >
Pascal/Delphi Source File  |  2001-06-07  |  27KB  |  1,119 lines

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