home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / pctchnqs / 1991 / number4 / tokenize.pas < prev    next >
Pascal/Delphi Source File  |  1991-06-03  |  5KB  |  159 lines

  1. UNIT Tokenizer; { Turbo Pascal 4.0-up; QuickPascal 1.0 }
  2.  
  3. INTERFACE
  4.   USES   Dos, FNameHax, Back1Hax;
  5.  
  6. TYPE   Tkind =
  7.          (newline,whitespace,symbol,number,
  8.           qstring,bracom,eolcom,special);
  9.  
  10. CONST  KindName:
  11.            ARRAY[Tkind] OF string[10] =
  12.              ('newline','whitespace','symbol','number',
  13.               'qstring','bracom','eolcom','special');
  14.  
  15. VAR    KindOfToken: Tkind;
  16.  
  17. PROCEDURE ReadToken(VAR f:text; VAR t:string);
  18. { - Reads a token from f into t, consuming
  19.       exactly the characters that make up the token.
  20.   - Sets global variable KindOfToken to the kind of token read.
  21.   - KindName[KindOfToken] is then a printable description
  22.       of the kind of token. }
  23.  
  24. IMPLEMENTATION
  25.  
  26. CONST  WhiteSpaces:   SET OF char = [#0..#9,#11..#12,#14..' '];
  27.        Alphabetics:   SET OF char = ['a'..'z','A'..'Z','_'];
  28.        Digits:        SET OF char = ['0'..'9'];
  29.  
  30. PROCEDURE ReadToken(VAR f:text; VAR t:string);
  31.  
  32. LABEL  OneTooMany, AllDone;
  33.  
  34. VAR    c, quote, prev: Char;
  35.  
  36. BEGIN
  37.   read(f,c); t:=c;                   { Get first char of token }
  38.  
  39.   IF (c=^M) THEN                            { NEWLINE - Type 1 }
  40.     BEGIN                                    { ^M^J or just ^M }
  41.       KindOfToken := newline;
  42.       read(f,c); t:=t+c;          { Look at the next character }
  43.       IF c=^J THEN      { If it's ^J, it belongs to this token }
  44.          GOTO AllDone                             { so keep it }
  45.       ELSE
  46.          GOTO OneTooMany   { Otherwise we've read one too many }
  47.     END
  48.  
  49.   ELSE IF (c=^J) THEN                       { NEWLINE - Type 2 }
  50.     BEGIN                                       { ^J by itself }
  51.       KindOfToken := newline;
  52.       GOTO AllDone
  53.     END
  54.  
  55.   ELSE IF c IN WhiteSpaces THEN                   { WHITESPACE }
  56.     BEGIN
  57.       KindOfToken := whitespace;
  58.       REPEAT
  59.         read(f,c); t:=t+c
  60.       UNTIL NOT (c IN WhiteSpaces);
  61.       GOTO OneTooMany
  62.     END
  63.  
  64.   ELSE IF c IN Alphabetics THEN                       { SYMBOL }
  65.     BEGIN
  66.       KindOfToken := symbol;
  67.       REPEAT
  68.         read(f,c); t:=t+c
  69.       UNTIL (NOT (c IN Alphabetics)) AND (NOT (c in Digits));
  70.       GOTO OneTooMany
  71.     END
  72.  
  73.   ELSE IF (c='''') OR (c='"') THEN             { QUOTED STRING }
  74.     BEGIN
  75.       KindOfToken := qstring;
  76.       quote := c;
  77.       REPEAT
  78.         read(f,c); t:=t+c;
  79.         IF (c=quote) THEN
  80.           IF NextChar(f) <> quote THEN   { found end of string }
  81.             GOTO AllDone
  82.           ELSE          { it's a quote written double; grab it }
  83.             BEGIN
  84.               read(f,c); t:=t+c
  85.             END
  86.       UNTIL eoln(f);
  87.       FileError(f,'Expecting '+quote+', found end of line')
  88.     END
  89.  
  90.   ELSE IF (c IN Digits) OR
  91.     ((c='.') AND (NextChar(f) IN Digits)) THEN        { NUMBER }
  92.     BEGIN
  93.       KindOfToken := number;
  94.       IF c<>'.' THEN
  95.         REPEAT
  96.           read(f,c); t:=t+c                   { Some digits... }
  97.         UNTIL NOT (c IN Digits);
  98.       IF c='.' THEN                         { Decimal point... }
  99.         REPEAT
  100.           read(f,c); t:=t+c                   { More digits... }
  101.         UNTIL NOT (c IN Digits);
  102.       IF (c='E') or (c='e') THEN           { E for exponent... }
  103.         BEGIN
  104.           read(f,c); t:=t+c;
  105.           IF (c IN Digits) OR
  106.                (c='+') OR (c='-') THEN        { +, -, or digit }
  107.             REPEAT
  108.               read(f,c); t:=t+c           { Digits of exponent }
  109.             UNTIL NOT (c IN Digits)
  110.         END;
  111.       GOTO OneTooMany
  112.     END
  113.  
  114.   ELSE IF c='{' THEN              { BRACKETED COMMENT - Type 1 }
  115.     BEGIN
  116.       KindOfToken := bracom;
  117.       t:=' ';          { Return a blank to the calling program }
  118.       REPEAT
  119.         read(f,c);
  120.         IF c='}' THEN GOTO AllDone
  121.       UNTIL eof(f);
  122.       FileError(f,'Expecting ''}'', found end of file')
  123.     END
  124.  
  125.   ELSE IF (c='(') AND
  126.          (NextChar(f)='*') THEN   { BRACKETED COMMENT - Type 2 }
  127.     BEGIN
  128.       KindOfToken := bracom;
  129.       t:=' ';          { Return a blank to the calling program }
  130.       REPEAT
  131.         prev:=c; read(f,c);
  132.         IF (c=')') AND (prev='*') THEN GOTO AllDone
  133.       UNTIL eof(f);
  134.       FileError(f,'Expecting ''*)'', found end of file')
  135.     END
  136.  
  137.   ELSE IF c='%' THEN                  { COMMENT TO END OF LINE }
  138.     BEGIN
  139.       KindOfToken := eolcom;
  140.       REPEAT
  141.         read(f,c); t:=t+c
  142.       UNTIL (c=^M) OR (c=^J);
  143.       GOTO OneTooMany
  144.     END
  145.  
  146.   ELSE                    { THE CHARACTER BY ITSELF IS A TOKEN }
  147.     BEGIN
  148.       KindOfToken := special;
  149.       GOTO AllDone
  150.     END;
  151.  
  152. OneTooMany:    { Jump here if an extra character has been read }
  153.   back1char(f);
  154.   delete(t,length(t),1);
  155.  
  156. AllDone:          { Jump here if nothing else needs to be done }
  157. END;
  158.  
  159. END. { Tokenizer }