[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Tips on adding GOTO, GOSUB to MiniBasic

Arman Anwar wrote:
> Etienne,
> I'm still unsure on how to use SableCC to genrate a compiler ?
> By compiler I mean e.g:
> helloWorld.basic > ( basic compiler ) > helloWorld.java > ( java
> compiler ) > java byte code ..

A small remark:  Java as an intermediate language is not a good match
for compiling unstructured basic code.  You would be in a better shape
if you used something like:

helloWorld.basic > ( basic compiler ) > helloWorld.jasmin > ( Jasmin
compiler ) > java byte code .

A typical compiler makes two or more passes over the AST:
(1) One (or more) passes to do collect/compute information that is
necessary for the later generation stage.
(2) A last pass where you generate the code.  This can be as simple as
"writing" source code text into an Output stream. (You don't need to
generate an AST of the destination language).

Typically, we call the first stages "resource allocation", as you
allocate resources as labels (for branch targets) etc.  We call the
second stage "code generation".


FOR I = 1 TO 5

You could plan to generate the following pattern of "jasmin" code:

(I assume here that you already know the Java bytecode language)

[1] You allocate a new "local slot" for "I", if none was already
allocated for it. Let say 3.
[2] You allocate 2 new labels, let say 53, 54.
[2] You generate the following code:

; --- BEGIN inAForStmt ---
iconst_1    ; push 1
istore 3    ; pop -> local_3


iconst_5    ; push 5
iload_3     ; push local_3
if_icmpeq label_54   ; if eq goto label_54
; --- END inAForStmt


; --- BEGIN outAForStmt ---
goto label_53  

; --- END outAForStmt ---

As you see, in the case of a FOR statement, the resource allocator needs
to make sure that the "iteration" variable has been allocated a slot.
(You should allocate a single slot for a variable in the whole basic
program, to be consistent with the semantics of Basic).  Then, it should
create two new labels.

The final recursive AST traversal (using a DepthFirstAdapter) writes
code in two beats: the "inAForStmt" and  "outAForStmt" methods. 

It would look like:

class CodeGeneration extends D..P..Adapter
{ PrintStream out;  Resources res;
  CodeGeneration(PrintStream out, Resources res)
  { this.out = out;  this.res = res; }

  void inAForStmt(... node)
     out.println("iconst_" + node.getFrom().getText());
     out.println("istore " + res.local(node.getVar().getText()));

     out.println("label_" + res.label(node) + ":"); 

  void outAForStmt(... node)
     out.println("goto label_" + res.label(node)); 
     out.println("label_" + (res.label(node) + 1) + ":"); 

I hope this gives you an idea.  There are many books out there about how
to write compilers that may explain all this in detail.

> As I understand miniBasic is an interpreter right ??


Have fun.

Etienne Gagnon, M.Sc.                        e-mail: egagnon@j-meg.com
Author of SableCC:                 http://www.sable.mcgill.ca/sablecc/