CLU példaprogramok

  Compiler

Azért, hogy tesztelhessük a szimbólum-táblát, készíthetünk egy egyszerű fordítóprogramot. A fordító sor-orientált, és csupán három programozási elemet ismer: egymásba ágyazható eljárás-deklarációk, változó-definíciók, és egy fordítási direktíva, ami arra utasítja a fordítót, hogy írja ki a standard outputra a paraméterként adott változó aktuális értékét.
A nyelv szintaxisa helyett álljon itt egy kicsi "példaprogram", ami szemlélteti a lehetőségeket:

procedure 1                ide már akármit írhatunk például ezt is.
   var a="geza"            az eljárás neve akármi lehet, nem tárolódik             
   var c "kata"            itt a forma: VAR név [=] "valami" 
   var dd "lajcsi          ez hibás lesz, de a fordítás megy tovább a következő sorra

   procedure 2             beágyazott eljárás
       #report dd          ez hibát fog adni
       var b="misi"

       procedure 3
          var b="feri"    itt egy új lokális változó egy régi nevével
          # report b      itt a forma: # REPORT név
          var b="juli"    ez megint hiba lesz
          var a="jani"
          # report a      na ez mi lesz?
       endproc

       # report a
       # report b
   endproc
   var c "katyi"          ez is hibát fog okozni 
endproc
A programocskának a Source.in nevet kell viselni, ez ugyanis a Compiler input-ja.

A megvalósításban gyakorlatilag csak a stream- és string-kezelés érdemel kiemelést, illetve jól megfigyelhető a kivételkezelés blokkokhoz való kötése a Compile eljárásban.

A FindVarName eljárás a beolvasott sorban megkeresi az azonosító nevének részsorozatát, és az idézőjelek közti szöveget, azaz kettő visszatérési értékkel rendelkezik!


MyTable=TSymbolTable[3]

FindVarName = proc (src:string) returns (string,string) signals (CMP_SyntaxError)
           key:array[char]:=array[char]$create(0)
           value:string
           found:bool:=false
           for c:char in string$chars(src) do
              if ~(c=' ') then
                found:=true
                if (c='"' | c='=') then break end
                array[char]$addh(key,c)
              else
                if (c=' ') & found then break
                else
                  signal CMP_SyntaxError
                end
              end
           end
           if string$indexc('"',src)=0 then
             signal CMP_SyntaxError
           end
           Value:=string$rest(src,string$indexc('"',src)+1)
           if string$indexc('"',Value)=0 then
             signal CMP_SyntaxError
           end
           Value:=string$substr(Value,1,string$indexc('"',Value)-1)
           return (string$ac2s(key),value)
end FindVarName

Compile = proc (inp,outp:stream) signals (CMP_BadArg(string))
          if ~stream$can_read(inp) then signal CMP_BadArg("input file") end
          if ~stream$can_write(outp) then signal CMP_BadArg("output file") end

          Table:MyTable
          Key:string
          Value:string
          ThisLine:string
          Dept:int:=0
          Indent:array[char]:=array[char]$Create(0)

          Table:=MyTable$Create()

          while (true) do
             ThisLine:=stream$getl(inp)
             % stream$putl(outp,ThisLine)

             if string$indexs("procedure",ThisLine)0 then
               MyTable$Enter(Table)
               stream$puts(outp,string$ac2s(indent))
               stream$putl(outp,"Enter new procedure frame")
               dept:=dept+3
               Indent:=array[char]$fill(0,dept,' ')
             end

             if string$indexs("endproc",ThisLine)0 then
               MyTable$Leave(Table)
               dept:=dept-3
               Indent:=array[char]$fill(0,dept,' ')
               stream$puts(outp,string$ac2s(indent))
               stream$putl(outp,"Leave procedure frame")
             end

             if string$indexs("var",ThisLine)0 then
               % variable definition
               stream$puts(outp,string$ac2s(indent))
               ThisLine:=string$rest(ThisLine,string$indexs("var",ThisLine)+4)
               begin
                  Key,Value:=FindVarName(ThisLine)
               end except
                 when CMP_SyntaxError:
                      stream$puts(outp,"*** Syntax error at definition: var ")
                      stream$putl(outp,ThisLine)
                      continue
               end
               stream$puts(outp,"Storing '")
               stream$puts(outp,Key)
               stream$puts(outp,"' with the defined value '")
               stream$puts(outp,Value)
               stream$putl(outp,"'")
               begin
                 Value:=MyTable$Store(Table,Key,Value)
               end except
                 when SYM_Redefine(s:string):
                      stream$puts(outp,string$ac2s(indent))
                      stream$puts(outp,"*** Redefinition error: ")
                      stream$putl(outp,s)
               end
             end

             if string$indexc('#',ThisLine)0 then
               % compiler directive calling
               stream$puts(outp,string$ac2s(indent))
               ThisLine:=string$rest(ThisLine,string$indexc('#',ThisLine)+1)
               if string$indexs("report",ThisLine)0 then
                 Key:=string$rest(ThisLine,string$indexs("report",ThisLine)+7)
                 stream$puts(outp,"### Reporting current value of ")
                 stream$puts(outp,Key)
                 stream$puts(outp,": ")
                 begin
                   Value:=MyTable$Search(Table,Key)
                   stream$putl(outp,Value)
                 end except
                 when SYM_NotFound: stream$putl(outp,"NOT FOUND") end
               else
                 stream$puts(outp,"*** Unknown compiler directive: ")
                 stream$putl(outp,ThisLine)
               end
             end

          end
          except when End_Of_File:
          end

end Compile

start_up=proc()
  Compile(stream$open(file_name$parse("source.in"),"read"),stream$primary_output())
end start_up