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

Re: SableCC vs. JTB vs. JJTree



Eran Tromer wrote:
> How does SableCC compare to JJTree and JTB?
>

OK.

I've been pressured (by the Sable Research Group) into replying to this
message...

I will only compare SableCC to JTB, which is available as open source
software (if you ignore that JavaCC, which is required to run JTB is
proprietary;-).

There are two main major differences in the ASTs built by SableCC and
JTB.

(I) The first difference is the absence of typed alternative nodes in
JTB.

Example:

  Productions
     exp = {add} exp plus term |
           {sub} exp minus term;

Where: plus, minus, and term are tokens.

For this grammar, SableCC generates the following Hierarchy:
   PExp extends Node
   AAddExp extends PExp
   ASubExp extends PExp

The object-oriented switch (i.e. visitor) switches on aletrnatives
(AAddExp, ASubExp). In other words, when a production node is visited,
it is seen a a specific alternative (add/sub). No integer switch and/or
cast is needed to access its elements (children).

In JTB, a NodeChoice class would be generated. Then, in order to access
the "real" node, one has to switch based on the NodeChoice.which integer
field (0=> first alternative, 1=> second alternative,...), then use a
type cast to use get the specific node.

I will show an example of all this after explaining the next difference.

(II) The second difference is that in SableCC ASTs, children are
accessed by name, not by position. This way, it is easy to make cosmetic
changes to a grammar without changing the implementation code. It is
also much easier to read code using a named based scheme. This is a very
important difference in a software engineering view.

So, if I wanted to write some code that accesses the children of an
expression, it would look like:

(This program writes the input expression back in prefix notation)

----------------
[SableCC]

  void caseAAddExp(AAddExp add)
  {
    System.out.print("+ ");
    add.getExp().apply(this);
    System.out.print(" " + add.getTerm());
  }
  void caseASubExp(ASubExp sub)
  {
    System.out.print("- ");
    sub.getExp().apply(this);
    System.out.print(" " + sub.getTerm());
  }
----------------    
[JTB]

  void visit(Exp exp)
  {
    switch (exp.f0.which)
    {
      case 0:
        {
          NodeSequence seq = (NodeSequence)n.f0.choice;
          System.out.print("+ ");
          seq.elementAt(0).apply(this);
          System.out.print(" " + seq.elementAt(2));
        }
        break;
      case 1:
        {
          NodeSequence seq = (NodeSequence)n.f0.choice;
          System.out.print("- ");
          seq.elementAt(0).apply(this);
          System.out.print(" " + seq.elementAt(2));
        }
        break;
    }       
  }
------------

Now. Even worse... I change the grammar slightly:

  Productions
     exp = {sub} exp term minus|
           {add} exp term plus;

What do I have to modify, in SableCC, to get back running code? NOTHING!

But here, there are the modifications for JTB:
(1) case 0 and 1 should be interchanged.
(2) elementAt(2) should be changed to elementAt(1).

As you might guess, it is not obvious to check that all these changes
were correctly made. Just look at the code, and try to verify if
anything is wrong:
--------------
[SableCC]

Same as before :-))))
----------------    
[JTB]

  void visit(Exp exp)
  {
    switch (exp.f0.which)
    {
      case 0:
        {
          NodeSequence seq = (NodeSequence)n.f0.choice;
          System.out.print("+ ");
          seq.elementAt(0).apply(this);
          System.out.print(" " + seq.elementAt(1));
        }
        break;
      case 1:
        {
          NodeSequence seq = (NodeSequence)n.f0.choice;
          System.out.print("- ");
          seq.elementAt(0).apply(this);
          System.out.print(" " + seq.elementAt(1));
        }
        break;
    }       
  }
------------

Yes. There's a bug. It's yours to find;-)

In summary, SableCC's advantage is a better software engineering
approach, with emphasis on code maintenance and readability. In
addition, its strictlyy-typed ASTs will help to get compile time errors
instead of runtime exceptions in case there are bugs in the code. 

Have fun!

Etienne

P.S.: You are allowed to forward this message to other lists/newsgroups,
if you find it relevant.
-- 

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