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 endprocA 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