const dbg = 0; al=7; ll=40; txmax=50; nul=0; ident=1; number=2; plus=3; minus=4; times=5; slash=6; oddsym=7; eql=8; neq=9; lss=10; leq=11; gtr=12; geq=13; lparen=14; rparen=15; comma=16; semicolon=17; period=18; becomes=19; beginsym=20; endsym=21; ifsym=22; thensym=23; whilesym=24; dosym=25; constsym=27; varsym=28; elsesym=30; repeatsym=31; untilsym=32; writesym = 33; constant=1; variable=2; lit=1; lod=3; sto=4; jmp=7; jpc=8; add=21; sub=22; mul=23; divcmd=24; eqlcmd=28; neqcmd=29; lsscmd=30; leqcmd=31; gtrcmd=32; geqcmd=33; deccmd=34; chrcmd=35; scrrow=$d6; flags=$02b1; xreg=$02b3; yreg=$02b4; clrscrline=$e9ff; putrowcol=$e50a; var line:array [ll] of char ; id:array [al] of char ; cc:integer ; ch:char ; sym: integer ; num: integer ; tabn: array [txmax] of integer ; tabk: array [txmax] of integer ; tabv: array [txmax] of integer ; tx,lx,dx: integer ; err: integer ; procedure error(n); begin if err = 0 then begin write ("# "); case n of 5: writeln ("; oder , erwartet"); 9: writeln (". erwartet"); 11: writeln ("bezeichner unbekannt"); 12: writeln ("zuweisung zu konstante"); 13: writeln (":= erwartet"); 16: writeln ("then erwartet"); 17: writeln ("; oder end erwartet"); 18: writeln ("do erwartet"); 20: writeln ("vergleichssymbol erwartet"); 22: writeln ("schliessende klammer fehlt"); 23: writeln ("falsches symbol am faktor-ende"); 24: writeln ("until erwartet"); 30: writeln ("zahl zu gross") end end ; err := err + 1; end ; procedure getch; var row: integer ; begin if (line[cc] = 13) or (cc = ll) then begin cc:= 0; row := memc [scrrow]; write (chr (19)); memc [xreg] := 0; call (clrscrline); write (chr (19)); read (line); memc [xreg] := row; memc [yreg] := 0; memc [flags] := 0; call (putrowcol); ch:= 32; end else begin ch := line[cc]; cc := cc + 1; end ; end ; function getsum; var i,sum: integer ; begin sum := 0; for i:= 0 to al - 1 do if id[i] >= 65 then sum := sum + id[i] - 64; getsum:= sum; end ; procedure getsym; var k,q: integer ; begin sym := nul; while ch = 32 do getch; if (ch >= 65) and (ch <=90) then begin k := 0; repeat if k < al then begin id[k] := ch; k := k + 1; end ; getch; until (ch < 65) or (ch > 90); if k < al then repeat id[k] := 32; k := k + 1; until k = al; q:= getsum; if q = 37 then sym := beginsym else if q = 23 then sym := endsym else if q = 15 then sym := ifsym else if q = 47 then sym := thensym else if q = 57 then sym := whilesym else if q = 19 then sym := dosym else if q = 71 then sym := constsym else if q = 41 then if id[0] = 69 then sym := elsesym else sym := varsym else if q = 65 then sym := repeatsym else if q = 76 then sym := untilsym else if q = 75 then sym := writesym else sym := ident; end else if (ch >= 48) and (ch <= 57) then begin num := 0; sym := number; repeat num := num * 10 + (ch - 48); getch; until (ch < 48) or (ch > 57); if num > 65535 then begin error(30); num := 0; end end else if ch = 58 then begin getch; if ch = 61 then begin sym := becomes; getch; end end else if ch = 60 then begin getch; if ch = 62 then begin sym := neq; getch; end else if ch = 61 then begin sym := leq; getch; end else sym := lss; end else if ch = 62 then begin getch; if ch = 61 then begin sym := geq; getch; end else sym := gtr; end else if ch = 43 then begin sym := plus; getch; end else if ch = 45 then begin sym := minus; getch; end else if ch = 42 then begin sym := times; getch; end else if ch = 47 then begin sym := slash; getch; end else if ch = 44 then begin sym := comma; getch; end else if ch = 59 then begin sym := semicolon; getch; end else if ch = 40 then begin sym := lparen; getch; end else if ch = 41 then begin sym := rparen; getch; end else if ch = 61 then begin sym := eql; getch; end else if ch = 46 then sym := period; if dbg then writeln ("sym:",sym); end ; procedure enter(kind); begin tx:= tx + 1; (* if tx > txmax then *) tabn[tx] := getsum; tabk[tx] := kind; case kind of constant: tabv[tx] := num; variable: begin tabv[tx] := dx; dx := dx + 1; end end end ; function position; var i,sum: integer ; begin sum := getsum; tabn[0] := sum; i := tx; while tabn[i] <> sum do i := i - 1; position := i; end ; procedure gen(fct, arg); begin write (" "); case fct of lit: writeln ("+lit ", arg); lod: writeln ("+lod var", arg); sto: writeln ("+sto var", arg); jmp: writeln ("jmp lbl", arg); jpc: writeln ("+jpc lbl", arg); add: writeln ("jsr add"); sub: writeln ("jsr sub"); mul: writeln ("jsr mul"); divcmd: writeln ("jsr div"); eqlcmd: writeln ("jsr eql"); neqcmd: writeln ("jsr neq"); lsscmd: writeln ("jsr lss"); leqcmd: writeln ("jsr leq"); gtrcmd: writeln ("jsr gtr"); geqcmd: writeln ("jsr geq"); deccmd: writeln ("jsr outdec"); chrcmd: writeln ("jsr outchr") end ; end ; function getlx; begin lx := lx + 1; getlx := lx - 1; end ; procedure lbl(no); begin writeln ("lbl", no); end ; procedure constdecl; begin if sym = ident then begin getsym; if sym = eql then begin getsym; if sym = number then begin enter(constant); getsym; end end end end ; procedure vardecl; begin if sym = ident then begin enter(variable); getsym; end end ; procedure expression; var addop: integer ; procedure factor; var i: integer ; begin if dbg then writeln ("factor"); if sym = ident then begin i := position; if i = 0 then error(11); case tabk[i] of constant: gen(lit, tabv[i]); variable: gen(lod, tabv[i]) end ; getsym; end else if sym = number then begin if num > 65535 then begin error(30); num := 0; end ; gen(lit, num); getsym; end else if sym = lparen then begin getsym; expression; if sym <> rparen then error(22); getsym; end else error(23); end ; procedure term; var mulop: integer ; begin if dbg then writeln ("term"); factor; while (sym = times) or (sym = slash) do begin mulop := sym; getsym; factor; if mulop = times then gen(mul, 0) else gen(divcmd, 0); end ; end ; begin if dbg then writeln ("expression"); term; while (sym = plus) or (sym = minus) do begin addop := sym; getsym; term; if addop = plus then gen(add, 0) else gen(sub, 0); end ; end ; procedure condition; var relop: integer ; begin if dbg then writeln ("condition"); expression; case sym of eql, neq, lss, leq, gtr, geq: begin relop := sym; getsym; expression; case relop of eql: gen(eqlcmd, 0); neq: gen(neqcmd, 0); lss: gen(lsscmd, 0); leq: gen(leqcmd, 0); gtr: gen(gtrcmd, 0); geq: gen(geqcmd, 0) end end else begin error(20); getsym; end end ; end ; procedure statement; var i,lx0,lx1: integer ; begin if dbg then writeln ("statement"); if sym = ident then begin i:= position; if i = 0 then error(11); if tabk[i] <> variable then begin error(12); i:= 0; end ; getsym; if sym <> becomes then error(13); getsym; expression; if i <> 0 then gen(sto, tabv[i]); end else if sym = ifsym then begin writeln ("; if"); lx0 := getlx; lx1 := getlx; getsym; condition; if sym <> thensym then error(16); getsym; gen(jpc, lx0); writeln ("; then"); statement; if sym = elsesym then begin gen(jmp, lx1); writeln ("; else"); lbl(lx0); getsym; statement; writeln ("; endif"); lbl(lx1); end else begin writeln ("; endif"); lbl(lx0); end end else if sym = beginsym then begin getsym; statement; while sym = semicolon do begin getsym; statement; end ; if sym <> endsym then error(17); getsym; end else if sym = whilesym then begin writeln ("; while"); lx0 := getlx; lx1 := getlx; lbl(lx0); getsym; condition; if sym <> dosym then error(19); getsym; gen(jpc, lx1); writeln ("; do"); statement; gen(jmp, lx0); writeln ("; endwhile"); lbl(lx1); end else if sym = repeatsym then begin writeln ("; repeat"); lx0 := getlx; lbl(lx0); getsym; statement; while sym = semicolon do begin getsym; statement; end ; if sym <> untilsym then error(24); writeln ("; until"); getsym; condition; gen(jpc, lx0); writeln ("; endrepeat"); end else if sym = writesym then begin writeln ("; write"); getsym; expression; gen(deccmd, 0); while sym = comma do begin gen(lit, 32); gen(chrcmd, 0); getsym; expression; gen(deccmd, 0); end ; gen(lit, 13); gen(chrcmd, 0); writeln ("; endwrite"); end ; end ; procedure block; begin if dbg then writeln ("block"); if sym = constsym then begin getsym; constdecl; while sym = comma do begin getsym; constdecl; end ; if sym <> semicolon then error(5); getsym; end ; if sym = varsym then begin getsym; vardecl; while sym = comma do begin getsym; vardecl; end ; if sym <> semicolon then error(5); getsym; end ; statement; end ; procedure dump; var i: integer ; begin for i:= 0 to tx do writeln (tabn[i],":",tabk[i],":",tabv[i]); end ; begin cc:= 0; ch:= 32; line[cc] := 13; sym := nul; num := 0; tx:= 0; tabn[0]:= 0; tabk[0] := 0; tabv[0] := 0; lx:= 1; dx:= 1; err := 0; writeln (chr (147)); getsym; block; if sym <> period then error(9); if err = 0 then dump; end .