0

I am new to SableCC. Just ran the calculator example at http://sablecc.sourceforge.net/thesis/thesis.html#PAGE26. I used the grammar file and interpreter file as they are, and tried to parse simple arithmetic expression like "45 * 5 + 2". The problem is, the interpreter method caseAMultFactor does not seem to be hit. I see it hit caseAPlusExpr, or caseAMinusExpr if I change the "+" to "-". So does the Start.apply(DepthFirstAdapter) method only go through the top mode node? How can I iterate through all nodes like that sample codes seem to do? I am using Java 1.7 and hope that's not a problem.

For your convenience I have pasted the grammar and interpreter codes here. Thanks for your help.

### Grammar:

Package postfix;

Tokens
 number = ['0' .. '9']+;
 plus = '+';
 minus = '-';
 mult = '*';
 div = '/';
 mod = '%';
 l_par = '(';
 r_par = ')';
 blank = (' ' | 13 | 10)+;


Ignored Tokens
 blank;

Productions
 expr =
  {factor} factor |
  {plus} expr plus factor |
  {minus} expr minus factor;

 factor =
  {term} term |
  {mult} factor mult term |
  {div} factor div term |
  {mod} factor mod term;


 term =
  {number} number |
  {expr} l_par expr r_par;

### Interpreter:

package postfix.interpret;
import postfix.analysis.DepthFirstAdapter;
import postfix.node.ADivFactor;
import postfix.node.AMinusExpr;
import postfix.node.AModFactor;
import postfix.node.AMultFactor;
import postfix.node.APlusExpr;
import postfix.node.TNumber;

public class Interpreter extends DepthFirstAdapter
{

     public void caseTNumber(TNumber node)
     {// When we see a number, we print it.
         System.out.print(node);
     }

     public void caseAPlusExpr(APlusExpr node)
     {
         System.out.println(node);
     }

     public void caseAMinusExpr(AMinusExpr node)
     {
         System.out.println(node);
     }

     public void caseAMultFactor(AMultFactor node)
     {// out of alternative {mult} in Factor, we print the mult.
         System.out.print(node.getMult());
     }

     public void outAMultFactor(AMultFactor node)
     {// out of alternative {mult} in Factor, we print the mult.
         System.out.print(node.getMult());
     }

     public void outADivFactor(ADivFactor node)
     {// out of alternative {div} in Factor, we print the div.
        System.out.print(node.getDiv());
     }


     public void outAModFactor(AModFactor node)
     {// out of alternative {mod} in Factor, we print the mod.
      System.out.print(node.getMod());
     }
}

1 Answers1

0

What you posted looks fine. You did not post any of the output, nor did you post the code to run the interpreter.

Here's my code (I'm omitting the code for Interpreter as it's the same as yours):

package postfix;

import postfix.parser.*;
import postfix.lexer.*;
import postfix.node.*;
import java.io.*;

public class Compiler {
    public static void main(String[] arguments) {
        try {
            Parser p = new Parser(new Lexer(new PushbackReader(
                    new StringReader("(45 + 36/2) * 3 + 5 * 2"), 1024)));
            Start tree = p.parse();
            tree.apply(new Interpreter());
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}

and when run, it produces this:

45 36 2 / + 3 * 5 2 * +

Note the * is displayed, as expected.

UPDATE 2015-03-09

First, please copy/paste this grammar into a file named postfix.grammar. It should be the same as the one you have, but just copy/paste anyway:

Package postfix;

Tokens
    number = ['0' .. '9']+;
    plus = '+';
    minus = '-';
    mult = '*';
    div = '/';
    mod = '%';
    l_par = '(';
    r_par = ')';
    blank = (' ' | 13 | 10)+;

Ignored Tokens
    blank;

Productions
    expr =
        {factor} factor |
        {plus} expr plus factor |
        {minus} expr minus factor;
    factor =
        {term} term |
        {mult} factor mult term |
        {div} factor div term |
        {mod} factor mod term;
    term =
        {number} number |
        {expr} l_par expr r_par;

Next, run this from a command line (make any necessary directory changes, of course):

java -jar "C:\Program Files\Java\sablecc-3.2\lib\sablecc.jar" src\postfix.grammar

Please ensure that you only have the Java classes from this invocation of SableCC (i.e. make sure any previously generated Java classes are deleted). Then using the Compiler class that I previously posted, try again. I cannot think of any problem with the grammar or problem with version 3.2 of SableCC that would cause the problem you're having. I'm hoping a fresh start will fix the problem.

mbmast
  • 960
  • 11
  • 25
  • Thanks for your answer. Sorry didn't see it earlier because nobody answered it in a few days of my posting. – user2045610 Mar 09 '15 at 01:31
  • When I tried your codes it output: [1,1] Unknown token: ( – user2045610 Mar 09 '15 at 01:32
  • See my UPDATE 2015-03-09. – mbmast Mar 10 '15 at 03:02
  • Also, I see you're new here. You can configure your SO profile to send you emails whenever there's activity on your postings. – mbmast Mar 10 '15 at 03:45
  • Thanks. It works! I am not sure what the difference is. It seems the command line way you suggested is the same in syntax as what I configured as External Tool. And, after your way works, I cleaned up the generated class files, use my original grammar file and compiled it with my original external tool - it still works. So something was just screwed up in my first testing and like you said, a fresh start fixed it. – user2045610 Mar 17 '15 at 04:20
  • Also, sad to say, I went ahead to try Beaver and got it to work before this. I will compare the two and pick one as my primary compiler tool. Good thing is I have 2 options now. Thanks again! – user2045610 Mar 17 '15 at 04:22
  • Also, when comparing compiler generators, two of the features I try and closely examine are 1) Whether there is good code separation between the parser and the action classes. Here SableCC is better than JavaCC, where the latter requires action class source code to be interwoven in the grammar file. – mbmast Mar 18 '15 at 17:03
  • And, 2) Whether the compiler generator is either less prone to recognizing shift/reduce conflicts or provides sufficient clues as to why you are getting a shift/reduce conflict. Shift/reduce conflicts take all the "fun" out of using these tools, so if possible, I'd use a generator that's better in this area. I think SableCC is a little weak in this area and the next version of it (version 4) will address this (although the next version has been in the works for years now). – mbmast Mar 18 '15 at 17:03
  • Thanks. Hope you see the acceptance now. On your first point (action/grammar separation), I think SableCC is good, in not requiring action codes to be interwoven into grammar, but Beaver is fine where you can still breakpoint and debug easily. Beaver also provides AST generation capability (haven't tried it yet) so hope it will bring it to the par of SableCC. Haven't tried JavaCC or ANTLR since they seem to be recursive descendent parsers (a little less favorable to me due to potential high CPU/memory use). – user2045610 Mar 19 '15 at 20:30
  • Yes. Thanks for the acceptance. I'm not sure if you were clear on this or not, but SableCC does provide AST generation. It's not documented well and I probably couldn't answer specific questions about it, but the support for it is there. Also, there is a support forum for SableCC and questions rarely go unanswered and SableCC's author, Etienne Gagnon, regularly participates in the conversations there. – mbmast Mar 20 '15 at 00:37