In the previous syntax-directed translation lab, we built a translator that collected strings representing output phrases, one for declaration. We're going to move the abstraction level up in this lab by creating objects that represent phrases rather than strings.
First, copy all of the code from the previous lab into a new module or project.
Now, let's create classes that represent the various kinds of output phrases. At the root, let's place an abstract OutputModelObject
class so that we can create data structures of generic output objects:
/** A generic root for any object representing an output component */
public abstract class OutputModelObject {
/** The method used to generate code for a specific object */
@Override
public String toString() { return super.toString(); }
}
After walking the tree with our code generator, we will have access to an object representing an output file. Our "emitter" is then just:
System.out.println(listener.file.toString());
Now create the following class hierarchy:
OutputFile
has a list ofOutputModelObject
objects and itstoString()
method just returns a string with all of those objects rendered to string;each one is followed by newline. You can also add a handy method to add declarations:
public void addDecl(OutputModelObject decl) { decls.add(decl); }
PrimitiveDecl
has two strings,type
andid
and itstoString()
simply returns "type id;
"ObjectRefDecl
is the same really except that itstoString()
returns "type*
id;
"
Now that we have the appropriate output model objects, we have to alter the code generator, Gen
, so that it does not collect a list of strings. Instead, it should create and fill an OutputFile
object:
public class Gen extends LangBaseListener {
public OutputFile file;
@Override
public void enterFile(LangParser.FileContext ctx) {
// set file field
}
@Override
public void enterDecl(LangParser.DeclContext ctx) {
// very much like last lab except add
// ObjectRefDecl or PrimitiveDecl not strings
// and add to file
}
/** Pretend we have type information */
public boolean isClassName(String typename) {
return Character.isUpperCase(typename.charAt(0));
}
}
Try that out with your main program printing out the listeners file object. You should get the same output as in the previous lab:
(file (decl (typename int) x ;) (decl (typename A) b ;))
int x;
A *b;
Unfortunately, our translator is still not the best we can do. (Dramatic foreshadowing of the next lab!)