⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 plscan.pas

📁 简单编译器的源代码,是大学课程设计内容,附简单测试用例
💻 PAS
字号:
{   Pass1  :  THE PL SCANNER  --  PLSCANNER.PAS   }
unit plscan;

interface

uses pcommon;

const
  MaxChar = 5000;
  MaxKey = 631;
  MaxInt = 32767;

type
   SymbolType = (And1{&}, Array1,arrow1{->},Asterisk1{*}, Becomes1{:=}, Begin1,
                 Boolean1, Bracket1{[]}, Call1, Comma1{,},Const1, Div1{/}, Do1, End1,
                 EndText1,Equal1{=}, False1,Fi1,Greater1{>},If1, Integer1, LeftBracket1{[},
                 LeftParenthesis1{(},Less1{<},Minus1{-}, Mod1{\}, Name1, Newline1,
                 Not1{~}, Numeral1,od1, Or1{|},Period1{.},Plus1{+},Proc1,Read1,
                 RightBracket1{]},RightParenthesis1{)},Semicolon1{;},skip1,
                 True1,Unknown1,Write1);         //按字母顺序排列

procedure Pass1;

implementation
 procedure Pass1;
  const
      ETX = chr(3);
      NL = chr(10);
      SP = chr(32);
      Dollor = chr(36);
      LastStandardName = Write1;
   type
      CharSet = set of char;
      SpellingTable = array [1..MaxChar] of char;
      WordPointer = ^ WordRecord;
      WordRecord = record
                 NextWord: WordPointer;
                 IsName: Boolean;
                 Index, Length, LastChar: integer
               end;
      HashTable = array [1..MaxKey] of WordPointer;

   var
        AlphaNumeric, Digits,
        EndComment, Invisible,
        Letters, Separators,
        SmallLetters,CapitalLetters  :  CharSet;
        ch: char;
        Characters: integer;
        Spelling: SpellingTable;
        Hash: HashTable;  Names: integer;

        { OUTPUT }
        procedure Emit1(Symbol: SymbolType);
        begin
           Emit(ord(Symbol))
        end;

       procedure Emit2(Symbol: SymbolType; Argument: integer);
       begin
           Emit(ord(Symbol));
           Emit(Argument)
       end;

        { PROCESSING EOLN }
       procedure BeginLine(Number: integer);
       begin
           LineNo := Number;
           NewLine(LineNo);
           Emit2(NewLine1, LineNo)
       end;

      procedure EndLine;
      begin
          BeginLine(LineNo + 1)
      end;

        { INPUT }
      procedure NextChar;
      begin
         if EOF(Input1) then  ch := ETX
           else
             if EOLN(Input1) then
                  begin
                      ch := NL;
                      Readln(Input1)
                  end
              else
                 begin
                     Read(Input1, ch);
                     if ch in Invisible then
                            NextChar
                 end
       end;

       { WORD SYMBOLS AND NAMES }
       function Key(Text1: String; Length: integer): integer;
         const
             W = 32641 { 32768 - 127 };
             N = MaxKey;
         var
            Sum, i: integer;
       begin
           Sum := 0;
           for i := 1 to Length do
              Sum := (Sum + ord(Text1[i])) mod W;
          Key := Sum mod N + 1
      end;

     procedure Insert(IsName: Boolean; Text1: String; 
                             Length,Index,KeyNo: integer);
        var
           Pointer: WordPointer;
           M, N: integer;
       begin { Insert the word in the spelling table }
            N := Characters;
            Characters := Characters + Length;
            TestLimit(Characters, MaxChar);
            for M := 1 to Length do
                Spelling[N + M] := Text1[M];
            { Insert the word in a word list }
            New(Pointer);
            Pointer^.NextWord := Hash[KeyNo];
            Pointer^.IsName := IsName;
            Pointer^.Index := Index;
            Pointer^.Length := Length;
            Pointer^.LastChar := Characters;
            Hash[KeyNo] := Pointer
        end;

       function Found(Text1: String; Length: integer; 
                                Pointer: WordPointer): Boolean;

         var
            Same: Boolean;
            M, N: integer;
       begin
           if Pointer^.Length <> Length then
                 Same := false
            else
               begin
                  Same := true;
                  M := Length;
                  N := Pointer^.LastChar - M;
                  while Same and (M > 0) do
                       begin
                           Same := Text1[M] = Spelling[M + N];
                           M := M -1
                        end
               end;
         Found := Same
      end;

      procedure Define(IsName: Boolean; Text1: String;
                 Length, Index: integer);
      begin
         Insert(IsName, Text1, Length, Index, Key(Text1, Length))
      end;

      procedure Search(Text1: String; Length: integer;
                           var Isname: Boolean;var Index: integer);
       var
           KeyNo: integer;  Pointer: WordPointer;  Done: Boolean;
      begin
         KeyNo := Key(Text1, Length);
         Pointer := Hash[KeyNo];
         Done := false;
         while not Done do
            if Pointer = nil then
                begin
                    IsName := true;
                    Names := Names + 1;  Index := Names;
                    Insert(true, Text1, Length, Index, KeyNo);
                    Done := True
                end
            else
              if Found(Text1, Length, Pointer) then
                   begin
                       IsName := Pointer^.IsName;
                       Index := Pointer^.Index;
                       Done := true
                   end
                else
                   Pointer := Pointer^.NextWord
       end;

       procedure Initialize;
         var
            KeyNo: integer;
       begin
            Digits := ['0'..'9'];
            CapitalLetters := ['A'..'Z'];
            SmallLetters := ['a'..'z'];
            Letters := CapitalLetters + SmallLetters;
            AlphaNumeric := Letters + Digits + ['_'];
            EndComment := [ETX];
            Invisible := [chr(0)..chr(31), chr(127)] - [NL, ETX];
            Separators := [SP, NL, Dollor];
            Characters := 0;
            for KeyNo := 1 to MaxKey do  Hash[KeyNo] := nil;
            { Insert the word symbols }
            Define(false,'array',5,ord(Array1));
            Define(false,'begin',5,ord(Begin1));
            Define(false,'call',4,ord(call1));
            Define(false,'const',5,ord(Const1));
            Define(false,'do',2,ord(Do1));
            Define(false,'end',3,ord(End1));
            Define(false,'fi',2,ord(fi1));
            Define(false,'if',2,ord(If1));
            Define(false,'od',2,ord(od1));
            Define(false,'proc',4,ord(Proc1));
            Define(false,'skip',4,ord(skip1));
             { Insert the standard names }
            Define(false,'integer',7,ord(Integer1));
            Define(false,'boolean',7,ord(Boolean1));
            Define(false,'false',5,ord(False1));
            Define(false,'true',4,ord(True1));
            Define(false,'read',4,ord(Read1));
            Define(false,'write',5,ord(Write1));
         //   define(true,'writeln',7,writeln0);
            Names := ord(LastStandardName);
      end;

        { LEXICAL ANALYSIS }
      procedure Comment;
       begin  {ch = Dollor}
          NextChar;
          while not ((ch = NL )or(ch = ETX)) do  NextChar;
          if ch = NL then
             begin
               EndLine;
               NextChar
             end;
      end;

      procedure NextSymbol;
        var
           IsName: Boolean;  Text1: String;
           Length, Index, Value, Digit: integer;
      begin
          while ch in Separators do
              if ch = SP then NextChar
                else
                   if ch = NL then
                         begin
                             EndLine;
                             NextChar
                         end
                 else {ch = Dollor} Comment;
         if ch in Letters then
              begin
                  Length := 0; Text1 := '';
                  while ch in AlphaNumeric do
                    begin
                   //    if ch in CapitalLetters then
                   //       ch := chr(ord(ch) + ord('a') - ord('A'));
                       Length := Length + 1;
                       Text1 := Text1 + ch;
                       NextChar
                   end;
                 Search(Text1, Length, IsName, Index);
                 if IsName then  Emit2(Name1, Index)
                     else  Emit(Index);
             end
             else
                 if ch in Digits then
                    begin
                        Value := 0;
                        while ch in Digits do
                           begin
                              Digit := ord(ch) - ord('0');
                              if Value <= (MaxInt - Digit) div 10 then
                                begin
                                      Value := 10 * Value + Digit;
                                       NextChar
                                end
                               else
                                    Begin
                                       Error(Numeral3);
                                       while ch in Digits do
                                           NextChar
                                   end
                         end;
                      Emit2(Numeral1, Value)
                   end
                else
                  case  ch  of
                   '+':  begin
                             Emit1(Plus1);
                             NextChar
                         end;
                   '-':  begin
                             Nextchar;
                             if ch = '>' then
                                 begin
                                     Emit1(Arrow1);
                                     NextChar
                                 end
                              else  Emit1(Minus1);
                         end;
                   '*':  begin
                             Emit1(Asterisk1);
                             NextChar
                         end;
                   '<': begin
                            Emit1(Less1);
                            Nextchar;
                        end;
                   '=': begin
                            Emit1(Equal1);
                            NextChar
                         end;
                    '>': begin
                             Emit1(Greater1);
                             Nextchar;
                         end;
                    ':': begin
                              Nextchar;
                              if ch = '=' then
                                    begin
                                         Emit1(Becomes1);
                                         NextChar
                                    end
                               else
                                  Error(Ambiguous3)
                           end;
                      '(': begin
                               Emit1(LeftParenthesis1);
                               NextChar
                           end;
                      ')': begin
                               Emit1(rightParenthesis1);
                               NextChar
                           end;
                      '[': begin
                             Nextchar;
                             if ch = ']' then
                                 begin
                                     Emit1(Bracket1);
                                     NextChar
                                 end
                              else  Emit1(LeftBracket1);
                           end;
                      ']': begin
                               Emit1(RightBracket1);
                               NextChar
                           end;
                      ',': begin
                               Emit1(Comma1);
                               NextChar
                            end;
                      '.': begin
                               Emit1(Period1);
                               Nextchar;
                           end;
                      ';': begin
                               Emit1(Semicolon1);
                               NextChar
                           end;
                      '&': begin
                               Emit1(And1);
                               NextChar
                           end;
                      '|': begin
                               Emit1(Or1);
                               NextChar
                           end;
                      '~': begin
                               Emit1(Not1);
                               NextChar
                           end;
                      '/': begin
                               Emit1(Div1);
                               NextChar
                           end;
                      '\': begin
                               Emit1(Mod1);
                               NextChar
                           end;
                     else
                        if ch <> ETX then
                            begin
                                Emit1(Unknown1);
                                NextChar
                            end
                  end { case }
       end;

      { Pass1 : THE PL SCANNER }
 begin
   Initialize;
   BeginLine(1);
   NextChar;
   while ch <> ETX do
       NextSymbol;
   Emit1(EndText1)
 end;

end.


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -