home *** CD-ROM | disk | FTP | other *** search
/ POINT Software Programming / PPROG1.ISO / pascal / swag / textfile.swg / 0004_LISTER.PAS.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1993-05-28  |  7.9 KB  |  253 lines

  1. {     Right now I'm writing an interpreter For a language that I
  2. developed, called "Isaac".  (It's Physics oriented).  I'd be very
  3. interested in you publishing this inFormation regarding Pascal
  4. Compilers, though I would likely not have time to do the excercises
  5. right away.
  6.  
  7.    Ok, Gavin. I'll post the lister (not Really anything exceptional,
  8.    but it'll get this thing going in Case anyone joins in late.)
  9.  
  10.    Here's the lister Program:
  11. }
  12. {$I-}
  13. Program Lister;
  14.  
  15. Uses Dos;
  16.  
  17. {$I PTypeS.inC}
  18. {Loacted in the SOURCE\MISC Directory.}
  19.  
  20. Function LeadingZero(w:Word): String;{convert Word to String With 0's}
  21.    Var s :String;
  22.    begin
  23.       Str(w:0,s);
  24.       if Length(s) < 2 then s := '0'+s;
  25.       LeadingZero := s;
  26.       if Length(s) > 2 then Delete(s,1,Length(s)-2);
  27.    end;
  28.  
  29.  
  30. Function FormatDate :String; { get system date and pretty it up }
  31.    Const
  32.       months : Array[1..12] of String[9] =
  33.       ('January', 'February', 'March', 'April', 'May', 'June', 'July',
  34.        'August', 'September', 'October', 'November', 'December');
  35.    Var s1,fn : String; y,m,d,dow : Word;
  36.    begin
  37.       GetDate(y,m,d,dow);
  38.       s1 := leadingZero(y);
  39.       fn := LeadingZero(d);
  40.       s1 := fn+' '+s1;
  41.       fn := months[m];
  42.       s1 := fn+' '+s1;
  43.       FormatDate := s1;
  44.    end;
  45.  
  46. Function FormatTime :String; { get system time and pretty it up }
  47.    Var s1, fn : String; h,m,s,s100 : Word;
  48.    begin
  49.       GetTime(h,m,s,s100);
  50.       fn := LeadingZero(h);
  51.       s1 := fn+':';
  52.       fn := LeadingZero(m);
  53.       FormatTime := s1+fn;
  54.    end;
  55.  
  56. Procedure Init(name:String);
  57.    Var t,d        :String;
  58.    begin
  59.       line_num := 0; page_num := 0; level := 0;
  60.       line_count := MAX_LinES_PER_PAGE;
  61.       source_name := name;
  62.       Assign(F1, name);      { open sourceFile - terminate if error }
  63.       Reset(F1);
  64.       if Ioresult>0 then
  65.       begin
  66.          Writeln('File error!');
  67.          Halt(1);
  68.       end;
  69.       { set date/time String }
  70.       d := FormatDate;
  71.       t := FormatTime;
  72.       date := d+'  '+t;
  73.    end;
  74.  
  75. Procedure Print_Header;
  76.    Var s, s1 :String;
  77.    begin
  78.       Writeln(F_FEED);
  79.       Inc(page_num);
  80.       Str(page_num, s1);
  81.       s := 'Page '+s1+'   '+source_name+'  '+date;
  82.       Writeln(s);
  83.    end;
  84.  
  85. Procedure PrintLine(line :String);
  86.    begin
  87.       Inc(line_count);
  88.       if line_count>MAX_LinES_PER_PAGE then
  89.       begin
  90.          print_header;
  91.          line_count := 1;
  92.       end;
  93.       if ord(line[0])>MAX_PRinTLinE_LEN then
  94.          line[0] := Chr(MAX_PRinTLinE_LEN);
  95.       Writeln(line);
  96.    end;
  97.  
  98.  
  99. Function GetSourceLine :Boolean;
  100.    Var print_buffer :String[MAX_SOURCELinE_LEN+9];
  101.        s            :String;
  102.    begin
  103.       if not(Eof(F1)) then begin
  104.          Readln(F1, source_buffer);
  105.          Inc(line_num);
  106.          Str(line_num:4, s);
  107.          print_buffer := s+' ';
  108.          Str(level, s);
  109.          print_buffer := print_buffer+s+': '+source_buffer;
  110.          PrintLine(print_buffer);
  111.          GetSourceLine := True;
  112.       end else GetSourceLine := False;
  113.    end;
  114.  
  115.  
  116. begin  { main }
  117.    if ParamCount=0 then begin
  118.       Writeln('Syntax: LISTER <Filename>');
  119.       Halt(2);
  120.    end;
  121.    init(ParamStr(1));
  122.    While GetSourceLine do;
  123. end.
  124.  
  125. {
  126.    Now that the task of producing a source listing is taken care of,
  127.    we can tackle the scanners main business: scanning. Our next job
  128.    is to produce a scanner that, With minor changes, will serve us
  129.    For the rest of this "course".
  130.  
  131.    The SCANNER will do the following tasks:
  132.  
  133.    ° scan Words, numbers, Strings and special Characters.
  134.    ° determine the value of a number.
  135.    ° recognize RESERVED WordS.
  136.  
  137.    LOOKinG For toKENS
  138.  
  139.    SCANNinG is reading the sourceFile and breaking up the Text of a
  140.    Program into it's language Components; such as Words, numbers,
  141.    and special symbols. These Components are called toKENS.
  142.  
  143.    You want to extract each each token, in turn, from the source
  144.    buffer and place it's Characters into an empty Array, eg.
  145.    token_String.
  146.  
  147.    At the start of a Word token, you fetch it's first Character and
  148.    each subsequent Character from the source buffer, appending each
  149.    Character to the contents of token_String. As soon as you fetch a
  150.    Character that is not a LETTER, you stop. All the letters in
  151.    token_String make up the Word token.
  152.  
  153.    Similarly, at the start of a NUMBER token, you fetch the first
  154.    digit and each subsequent digit from the source buffer. You
  155.    append each digit to the contents of token_String. As soon as you
  156.    fetch a Character that is not a DIGIT, you stop. All digits
  157.    within token_String make up the number token.
  158.  
  159.    Once you are done extracting a token, you have the first
  160.    Character after a token. This Character tells you that you have
  161.    finished extracting the token. if the Character is blank, you
  162.    skip it and any subsequent blanks Until you are again looking at
  163.    a nonblank Character. This Character is the start of the next
  164.    token.
  165.  
  166.    You extract the next token in the same way you extracted the
  167.    previous one. This process continues Until all the tokens have
  168.    been extracted from the source buffer. Between extracting tokens,
  169.    you must reset token_String to null String to prepare it For the
  170.    next token.
  171.  
  172.    PASCAL toKENS
  173.  
  174.    A scanner For a pascal Compiler must, of course, recognize Pascal
  175.    tokens. The Pascal language contains several Types of tokens:
  176.    identifiers, reserved Words, numbers, Strings, and special
  177.    symbols.
  178.  
  179.    This next exercise is a toKENIZER that recognizes a limited
  180.    subset of Pascal tokens. The Program will read a source File and
  181.    list all the tokens it finds. This first version will recognize
  182.    only Words, numbers, and the Pascal "end-of-File" period - but it
  183.    provides the foundation upon which we will build a full Pascal
  184.    scanner in the second version.
  185.  
  186.    Word: A Pascal Word is made up of a LETTER followed by any number
  187.    of LETTERS and DIGITS (including 0).
  188.  
  189.    NUMBER: For now, we'll restrict a number token to a Pascal
  190.    unsigned Integer, which is one or more consecutive digits. (We'll
  191.    handle signs, decimals, fractions, and exponents later) and,
  192.    we'll use the rule that an input File *must* have a period as
  193.    it's last token.
  194.  
  195.    The tokenizer will print it's output in the source listing.
  196.  
  197.    EXERCISE #2
  198.  
  199.    Use the following TypeS and ConstANTS to create a SCANNER as
  200.    described above:
  201.  
  202. -------------------------------------------------------------------
  203.  
  204. Type
  205.    Char_code    = (LETTER, DIGIT, SPECIAL, Eof_CODE);
  206.    token_code   = (NO_toKEN, Word, NUMBER, PERIOD,
  207.                    end_of_File, ERRor);
  208.    symb_Strings :Array[token_code] of String[13] =
  209.                   ('<no token>','<Word>','<NUMBER>','<PERIOD>',
  210.                    '<end of File>','<ERRor>');
  211.  
  212.    literal_Type = (Integer_LIT, String_LIT);
  213.  
  214.    litrec = Record
  215.       l :LITERAL_Type;
  216.       Case l of
  217.  
  218.          Integer_LIT: value :Integer;
  219.          String_LIT:  value :String;
  220.       end;
  221.    end;
  222.  
  223. Const
  224.    Eof_Char = #$7F;
  225.  
  226. Var
  227.    ch             :Char;        {current input Char}
  228.    token          :token_code;  {code of current token}
  229.    literal        :litrec;      {value of current literal}
  230.    digit_count    :Integer;     {number of digits in number}
  231.    count_error    :Boolean;     {too many digits in number?}
  232.    Char_table     :Array[0..255] of Char_code;{ascii Character map}
  233.  
  234.  
  235. The following code initializes the Character map table:
  236.  
  237. For c := 0 to 255 do
  238.    Char_table[c] := SPECIAL;
  239. For c := ord('0') to ord('9') do
  240.    Char_table[c] := DIGIT;
  241. For c := ord('A') to ord('Z') do
  242.    Char_table[c] := LETTER;
  243. For c:= ord('a') ro ord('z') do
  244.    Char_table[c] := LETTER;
  245. Char_table[ord(Eof_Char)] := Eof_CODE;
  246.  
  247. -------------------------------------------------------------------
  248.  
  249.    You can (and should) use the code from your source listing
  250.    Program to start your scanner. if you have just arrived, use my
  251.    own code posted just previously.
  252.  
  253.