home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 December / Chip_2001-12_cd1.bin / zkuste / delphi / kompon / d23456 / CAJSCRTP.ZIP / ifs_utl.pas < prev    next >
Pascal/Delphi Source File  |  2001-10-03  |  30KB  |  1,223 lines

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