Related articles |
---|
HELP: PL/0 Compiler planinc@cs.curtin.edu.au (2000-09-15) |
Re: HELP: PL/0 Compiler ed_davis@my-deja.com (Ed Davis) (2000-10-01) |
From: | Ed Davis <ed_davis@my-deja.com> |
Newsgroups: | comp.compilers |
Date: | 1 Oct 2000 00:23:08 -0400 |
Organization: | Deja.com - Before you buy. |
References: | 00-09-106 |
Keywords: | Pascal |
planinc@cs.curtin.edu.au (Adrian Planinc) wrote:
>
> I have been fiddling around with Niklaus Wirth's PL/0
> compiler.
>
> Namely, I've got a copy of the original Pascal source of the
> compiler and have explored the possibilities of adding
> further control structures to it as an exercise.
>
> I am especially interested if anyone has any ideas or even
> Pascal source lying around which implements a FOR construct.
> This is something I am having trouble with especially!
I too like fiddling around with that compiler. It seems to be a very
well written piece of code, and easy to modify.
Two other small compilers I like working with are Oberon-0 and
obfuscated C. The non-obfuscated version is very well written and is
about as easy to modify as pl/0.
I have a version of pl/0 I found on the net - not sure if it is
identical with the original, but it is pretty close. Anyway, I've
attempted to add the for statement, as in:
for ident := expr1 to|downto expr2 do statement;
Here is what I have come up with so far. In procedure statement, add
the following:
end else if sym = forsym then begin
{ for var := expr to expr do statement; }
getsym; { skip for }
if sym <> ident then
error(0); { ident expected }
i := position(id, tx);{ find in symtab }
{ make sure it is a variable }
if i = 0 then
error(11) {ident not found in symtab}
else if table[i].kind <> variable then begin
error(12); {assignment to non variable}
i := 0
end;
getsym; { skip ident }
if sym = becomes then
getsym
else
error(13); { expecting assignment operator }
expression(lev, tx);
gen(sto, lev - table[i].level, table[i].adr);
if sym = downtosym then
d := -1
else if sym = tosym then
d := 1
else
error(0); { to|downto expected }
getsym; { skip to|downto }
expression(lev, tx);{ evaulate expr }
gen(opr, 0, 15); { duplicate to expr value }
{ load index value }
gen(lod, lev - table[i].level, table[i].adr);
if d = 1 then { do comparison }
gen(opr, 0, 11) { >= }
else
gen(opr, 0, 13);{ <= }
j := cx;
gen(jpc, 0, 0); { jump if needed }
if sym = dosym then
getsym { skip do }
else
error(18); {'do' required }
statement(lev, tx);
gen(opr, 0, 15); { duplicate to expr value }
{ load index value }
gen(lod, lev - table[i].level, table[i].adr);
gen(opr, 0, 9); { <> - compare with expr value }
x := cx;
gen(jpc, 0, 0);
{ load index value }
gen(lod, lev - table[i].level, table[i].adr);
{add 'd' to it }
gen(lit, 0, d);
gen(opr, 0, 2);
gen(sto, lev - table[i].level, table[i].adr);
gen(jmp, 0, j + 1); { jump back to top }
code[j].a := cx; { fixup }
code[x].a := cx; { fixup }
gen(int, 0, -1); { pop left over 'to value' }
end
Some additional notes:
I extended lit and int to also accept negative values. Originally,
they were declared as taking small positive numbers.
I added a 'dup top of stack' instruction.
Error recovery is non-existent.
Of course you will need to add the new keywords and symbols to the
appropriate tables.
I am thinking about converting this version to C and continuing on from
there. If anyone knows of an already existing C version, please let me
know!
If you add anything, or fix any of the bugs in the for statement code,
I would be glad hear from you.
Return to the
comp.compilers page.
Search the
comp.compilers archives again.