Search code examples
antlrgrammarbison

ANTLR grammar from bison


I'm trying to translate a grammar from bison to ANTLR. The grammar itself is pretty simple in bison but I cannot find a simple way for doing this.

Grammar in bison:

expr = expr or expr | expr and expr | (expr)

Any hints/links/pointers are welcome.

Thanks, Iulian


Solution

  • In ANTLR3, you cannot create left recursive rules (ANTLR4 can handle left recursion in certain cases):

    a : a b
      ;
    

    tail recursion is fine:

    a : b a
      ;
    

    For more information on left recursive rules, see ANTLR's Wiki.

    So, your example could look like:

    parse
      :  expr+ EOF
      ;
    
    expr
      :  orExpr
      ;
    
    orExpr
      :  andExpr ('or' andExpr)*
      ;
    
    andExpr
      :  atom ('and' atom)*
      ;
    
    atom
      :  Boolean
      |  '(' expr ')'
      ;
      
    Boolean
      :  'true'
      |  'false'
      ;
    

    Here's a small demo in Java:

    grammar BoolExp;
    
    @members {
      public static void main(String[] args) throws Exception {
        if(args.length != 1) {
          System.out.println("Usage:");
          System.out.println(" - Windows    : java -cp .;antlr-3.2.jar BoolExpParser \"EXPRESSION\"");
          System.out.println(" - *nix/MacOS : java -cp .:antlr-3.2.jar BoolExpParser \"EXPRESSION\"");
          System.exit(0);
        }
        ANTLRStringStream in = new ANTLRStringStream(args[0]);
        BoolExpLexer lexer = new BoolExpLexer(in);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        BoolExpParser parser = new BoolExpParser(tokens);
        parser.parse();
      }
    }
    
    parse
      :  e=expr EOF {System.out.println($e.bool);}
      ;
    
    expr returns [boolean bool]
      :  e=orExpr {$bool = $e.bool;}
      ;
    
    orExpr returns [boolean bool]
      :  e1=andExpr       {$bool = $e1.bool;} 
         ('or' e2=andExpr {$bool = $bool || $e2.bool;}
         )*
      ;
    
    andExpr returns [boolean bool]
      :  e1=atom        {$bool = $e1.bool;} 
         ('and' e2=atom {$bool = $bool && $e2.bool;}
         )*
      ;
    
    atom returns [boolean bool]
      :  b=Boolean      {$bool = new Boolean($b.text).booleanValue();}
      |  '(' e=expr ')' {$bool = $e.bool;}
      ;
    
    Boolean
      :  'true'
      |  'false'
      ;
    
    Space
      :  (' ' | '\t' | '\n' | '\r') {skip();}
      ;
    

    First create a lexer & parser (1) and then compile all source files (2). Finally, execute the BoolExpParser class (3).

    1

    // Windows & *nix/MacOS
    java -cp antlr-3.2.jar org.antlr.Tool BoolExp.g
    

    2

    // Windows
    javac -cp .;antlr-3.2.jar *.java
    
    // *nix/MacOS
    javac -cp .:antlr-3.2.jar *.java
    

    3

    // Windows
    java -cp .;antlr-3.2.jar BoolExpParser "false and true or true"
    
    // *nix/MacOS
    java -cp .:antlr-3.2.jar BoolExpParser "false and true or true"
    

    Terence Parr's ANTLR reference is the book on ANTLR. And Scott created some excellent video tutorials on ANTLR 3 (with Eclipse).