home *** CD-ROM | disk | FTP | other *** search
/ PC Plus SuperCD (UK) 2000 March / pcp161b.iso / handson / archive / Issue160 / files / SyntaxEditor / syntax.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1999-10-18  |  10.3 KB  |  339 lines

  1. unit syntax;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  7.   StdCtrls, ComCtrls, ExtCtrls,
  8.   EditConsts;
  9.  
  10. const
  11.      // possible values of status parameter
  12.      SUCCESS = 1;
  13.      NOERROR = 2;
  14.      READERROR = 3;
  15.  
  16. type
  17.  
  18.   chararray = array[0..255] of char;
  19.      // ReadStatus defines type of the status parameter
  20.   ReadStatus = SUCCESS..READERROR;
  21.  
  22.     function KeyWord( token : string ) : boolean;
  23.     procedure WriteRTFHeader( ms : TMemoryStream );
  24.     procedure WriteRTFTerminator( ms : TMemoryStream );    
  25.     procedure HandleCR(c : char; msout : TMemoryStream);
  26.     procedure HandleSpecialChars( c : char; msout : TMemoryStream );
  27.     procedure processStream( msin, msout : TMemoryStream );
  28.     procedure ReadChar( var c : char; msin : TMemoryStream; var status : ReadStatus );
  29.     procedure ReadToken( var token : chararray; msin : TMemoryStream; var c : char; var status : ReadStatus );
  30.     procedure WriteToken( var token : chararray; msout : TMemoryStream; var status : ReadStatus );
  31.     procedure ReadWriteToken( msin, msout : TMemoryStream; var c : char; var status : ReadStatus );
  32.     procedure ReadWriteComment( msin, msout : TMemoryStream; var c : char; var status : ReadStatus );
  33.     procedure ReadWriteStarComment( msin, msout : TMemoryStream; var c : char; var status : ReadStatus );
  34.     procedure ReadWriteLineComment( msin, msout : TMemoryStream; var c : char; var status : ReadStatus );
  35.     procedure ReadWriteString( msin, msout : TMemoryStream; var c : char; var status : ReadStatus );
  36.     procedure WriteChar( c : char; msout : TMemoryStream );
  37.     procedure ReadWriteChar( var c : char; msin, msout : TMemoryStream; var status : ReadStatus );
  38.  
  39.  
  40. implementation
  41.  
  42. function KeyWord( token : string ) : boolean;
  43. // if token is a keyword, return true
  44. var
  45.    isKW : boolean;
  46.    i    : integer;
  47. begin
  48.    isKW := false;
  49.    i := 0;
  50.    while ((i <= NUMKEYWORDS) and (isKW = false )) do
  51.    begin
  52.    //!! Test is case-insensitive (OK for Pascal. Change this for C or Java)
  53.       if lowercase(token) = KeyWords[i] then
  54.          isKW := true
  55.       else
  56.          Inc(i);
  57.    end;
  58.    result := isKW;
  59. end;
  60.  
  61.  
  62. procedure WriteRTFHeader( ms : TMemoryStream );
  63. begin
  64.     try
  65.       ms.WriteBuffer( RTFHEADER, strlen(RTFHEADER) );
  66.       ms.WriteBuffer( RTFCTABLE, strlen(RTFCTABLE) );
  67.    except
  68.       on EWriteError do
  69.          ShowMessage( 'Failed to write header and ctable to stream!' );
  70.    end;
  71. end;
  72.  
  73. procedure WriteRTFTerminator( ms : TMemoryStream );
  74. begin
  75.    ms.WriteBuffer(TERMINATOR, sizeof(TERMINATOR)); // terminate RTF buffer
  76. end;
  77.  
  78. procedure HandleCR(c : char; msout : TMemoryStream);
  79. // deal with CR - write rtf '\para' code to stream
  80. begin
  81.    if c = CR then
  82.       msout.WriteBuffer( PARCODE, strlen( PARCODE ) );
  83. end;
  84.  
  85. procedure HandleSpecialChars( c : char; msout : TMemoryStream );
  86. // deal with special RTF chars - add '\'
  87. begin
  88.    if c in SPECIALRTFCHARS then
  89.        msout.WriteBuffer( SLASH, sizeof( SLASH ) )
  90.    else HandleCR( c, msout );
  91. end;
  92.  
  93. procedure WriteChar( c : char; msout : TMemoryStream );
  94. // Write both normal chars and special rtf chars
  95. begin  // deal with slashes and CRs
  96.       HandleSpecialChars(c, msout );
  97.        // then write the char
  98.       msout.WriteBuffer( c, sizeof( c ) );
  99. end;
  100.  
  101. procedure ReadWriteChar( var c : char; msin, msout : TMemoryStream;
  102.                                      var status : ReadStatus );
  103. // write any char that is not written as part of a token, string or comment
  104. begin
  105.    WriteChar( c, msout );
  106.    ReadChar( c, msin, status );
  107. end;
  108.  
  109. procedure ReadChar( var c : char; msin : TMemoryStream;
  110.                            var status : ReadStatus );
  111. begin
  112.   status := NOERROR;
  113.   try
  114.     if msin.position < msin.size then
  115.        msin.ReadBuffer( c, sizeof(c) );    // read one char at a time
  116.   except
  117.     on EReadError do
  118.        status := READERROR;
  119.   end;
  120. end;
  121.  
  122. procedure ReadToken( var token : chararray; msin : TMemoryStream;
  123.           var c : char; var status : ReadStatus );
  124. // try to read an alphanumeric token
  125. var
  126.    i : integer;
  127. begin
  128.   status := NOERROR;
  129.   i := 0;
  130.   token := '';
  131.   try
  132.     while (c in ALPHANUMERIC) do
  133.     begin
  134.        token[i] := c;
  135.        INC(i);
  136.        ReadChar( c, msin, status );     // read one char at a time
  137.     end;
  138.     if token <> '' then
  139.        status := SUCCESS;
  140.   except
  141.     on EReadError do
  142.        status := READERROR;
  143.   end;
  144. end;
  145.  
  146. procedure WriteToken( var token : chararray; msout : TMemoryStream; var status : ReadStatus );
  147. begin
  148.    status := NOERROR;
  149.    if KeyWord(token) then
  150.    begin
  151.       msout.WriteBuffer( KWCODE, length( KWCODE ) );
  152.       msout.WriteBuffer( token, length( token ) );
  153.       msout.WriteBuffer( PLAINCODE, length( PLAINCODE ) );
  154.    end
  155.    else
  156.       msout.WriteBuffer( token, length( token ) );
  157. end;
  158.  
  159.  
  160. procedure ReadWriteToken( msin, msout : TMemoryStream;
  161.           var c : char; var status : ReadStatus );
  162. var
  163.    token : chararray;
  164. begin
  165.    ReadToken(token,msin,c,status);
  166.    if status = SUCCESS then
  167.       WriteToken(token,msout,status);
  168. end;
  169.  
  170. procedure ReadWriteComment( msin, msout : TMemoryStream;
  171.           var c : char; var status : ReadStatus );
  172. // try to read and write a standard curly-brace { } comment
  173. begin
  174.   status := NOERROR;
  175. //   try           // !! add error handling here
  176.    if c = '{' then
  177.    begin
  178.      msout.WriteBuffer( COMMENTCODE, strlen( COMMENTCODE ) );
  179.      msout.WriteBuffer( SLASH, sizeof( SLASH ) );
  180.      msout.WriteBuffer( c, sizeof( c ) );
  181.      while (c <> '}') and (msin.position < msin.size) do
  182.      begin
  183.         msin.ReadBuffer( c, sizeof( c ) );
  184.         if c <> '}' then
  185.           WriteChar( c, msout );
  186.      end;
  187.      if msin.position < msin.size then
  188.      begin
  189.         msout.WriteBuffer( SLASH, sizeof( SLASH ) );
  190.         msout.WriteBuffer( c, sizeof( c ) );
  191.         msout.WriteBuffer(PLAINCODE, strlen(PLAINCODE));
  192.         msin.ReadBuffer( c, sizeof( c ) );
  193.         status := SUCCESS;
  194.      end;
  195.    end;
  196. end;
  197.  
  198. procedure ReadWriteStarComment( msin, msout : TMemoryStream;
  199.           var c : char; var status : ReadStatus );
  200. // try to read and write a brace-star (* *) comment
  201. var
  202.    c2 : char;
  203.    CommentEnd, StarFound : boolean;
  204. begin
  205.   status := NOERROR;
  206.   c2 := '#';
  207.   CommentEnd := false;
  208.   StarFound := false;
  209. //   try           // !! add error handling- set status
  210.    if c = '(' then
  211.    begin
  212.       ReadChar(c2,msin,status);
  213.       if c2 <> '*' then
  214.       begin        // if not a comment then
  215.           WriteChar( c, msout );
  216.           c := c2; // return c2
  217.       end
  218.       else
  219.       begin       // if this is a comment
  220.         msout.WriteBuffer( COMMENTCODE, strlen( COMMENTCODE ) );
  221.         msout.WriteBuffer( c, sizeof( c ) );
  222.         msout.WriteBuffer( c2, sizeof( c2 ) );
  223.         while not (CommentEnd) and (msin.position < msin.size) do
  224.         begin
  225.            ReadChar( c, msin, status );
  226.            if (c = ')') and StarFound then
  227.               CommentEnd := true
  228.            else
  229.            if c = '*' then
  230.               StarFound := true
  231.            else StarFound := false;
  232.            WriteChar( c, msout );
  233.         end;  // while not (CommentEnd) and (msin.position < msin.size)
  234.         if msin.position < msin.size then
  235.         begin
  236.            msout.WriteBuffer(PLAINCODE, strlen(PLAINCODE));
  237.            msin.ReadBuffer( c, sizeof( c ) );
  238.         end;
  239.       end;  // if this is a comment
  240.       status := SUCCESS; // set this since c was handled even if no comment
  241.    end;     // if c = '('
  242. end;
  243.  
  244. procedure ReadWriteLineComment( msin, msout : TMemoryStream;
  245.           var c : char; var status : ReadStatus );
  246. // try to read and write a single-line // comment
  247. var
  248.    c2 : char;
  249. begin
  250.   status := NOERROR;
  251.   c2 := '#';
  252. //   try           // !! add error handling
  253.    if c = '/' then
  254.    begin
  255.       ReadChar(c2,msin,status);
  256.       if c2 <> '/' then
  257.       begin        // if not a comment then
  258.           WriteChar( c, msout );
  259.           c := c2; // return c2
  260.       end
  261.       else
  262.       begin       // if this is a comment
  263.         msout.WriteBuffer( COMMENTCODE, strlen( COMMENTCODE ) );
  264.         msout.WriteBuffer( c, sizeof( c ) );
  265.         msout.WriteBuffer( c2, sizeof( c2 ) );
  266.         while not (c = CR) and (msin.position < msin.size) do
  267.         begin
  268.            ReadChar( c, msin, status );
  269.            WriteChar( c, msout );
  270.         end;
  271.         if msin.position < msin.size then
  272.         begin
  273.            msout.WriteBuffer(PLAINCODE, strlen(PLAINCODE));
  274.            msin.ReadBuffer( c, sizeof( c ) );
  275.         end;
  276.       end;
  277.        status := SUCCESS;
  278.    end;
  279. end;
  280.  
  281.  
  282. procedure ReadWriteString( msin, msout : TMemoryStream;
  283.           var c : char; var status : ReadStatus );
  284. begin
  285.   status := NOERROR;
  286. //   try           // !! add error handling
  287.    if c = '''' then
  288.    begin
  289.      msout.WriteBuffer( STRINGCODE, strlen( STRINGCODE ) );
  290.      msout.WriteBuffer( c, sizeof( c ) );
  291.      c := '#';
  292.      while (c <> '''') and (msin.position < msin.size) do
  293.      begin
  294.         msin.ReadBuffer( c, sizeof( c ) );
  295.         WriteChar( c, msout );
  296.      end;
  297.      if msin.position < msin.size then
  298.      begin
  299.         msout.WriteBuffer(PLAINCODE, strlen(PLAINCODE));
  300.         msin.ReadBuffer( c, sizeof( c ) );
  301.         status := SUCCESS;
  302.      end;
  303.    end;
  304. end;
  305.  
  306. procedure processStream( msin, msout : TMemoryStream );
  307. var
  308.    c : char;
  309.    status : ReadStatus;
  310. begin
  311.    Screen.Cursor := crHourglass;       // Show hourglass cursor
  312.    c := '#';
  313.    // start by reading 1st char
  314.    if msin.position < msin.size then
  315.       ReadChar(c,msin,status);
  316.    try
  317.       while msin.position < msin.size do     // iterate through input stream
  318.       begin
  319.          ReadWriteToken( msin,msout,c,status);
  320.          if status <> SUCCESS then
  321.            ReadWriteString( msin,msout,c,status);
  322.          if status <> SUCCESS then
  323.            ReadWriteComment( msin,msout,c,status);
  324.          if status <> SUCCESS then
  325.            ReadWriteStarComment( msin,msout,c,status);
  326.          if status <> SUCCESS then
  327.            ReadWriteLineComment( msin,msout,c,status);
  328.          if status <> SUCCESS then
  329.             ReadWriteChar(c, msin, msout, status );
  330.       end; // while msin.position < msin.size
  331.    finally
  332.      Screen.Cursor := crDefault;    // restore normal cursor
  333.    end;
  334. end;
  335.  
  336.  
  337.  
  338. end.
  339.