This is a replacement for the Beaver parser generator with the goal of being easier to use.

Things that NeoBeaver does differently:

  • Improved warning & error messages.
  • Unused terminals are not removed.
  • Implicit terminals.
  • Inline type declarations.
  • Automatic component names.
  • Directives anywhere.

More deails about each of the differences are described below.

Improved warning & error messages

If there is a conflict, NeoBeaver prints the parsing states for each conflict.

For example,

Conflict: SHIFT MUL / REDUCE expr -> expr MUL expr
Context: item set S10
  expr -> expr . ADD expr [MUL, EOF, RPAREN, ADD]
  expr -> expr . MUL expr [MUL, EOF, RPAREN, ADD]
  expr -> expr MUL expr [MUL, EOF, RPAREN, ADD]

Unused terminals are not removed

Beaver requires you to declare terminals explicitly:

%terminals ADD, MUL;
%terminals LPAREN, RPAREN;
%terminals ID;

However, if a terminal is not used by any production it will not appear in the generated parser. This becomes annoying when you are developing a new parser, as it does not allow a partially completed parser with a full scanner.

NeoBeaver instead always generates terminals that have been explicitly declared. This makes it significantly easier to develop a new parser: you can specify all terminals and make your scanner compile without completing the parser.

Implicit terminals

NeoBeaver does not require all terminals to be explicitly declared. You can still do so to make sure that the terminals are generated in case you comment out some productions.

Any production component that does not have its own production rule is assumed to be a terminal.

Inline type declarations

In Beaver, you have to specify the type of each production by using %typeof declarations. This can be replaced by using inline type specifiers in NeoBeaver. For example,

MyType product = comp1 comp2;

Automatic component names

When you want to use a production component in the semantic action, you'll have to name it in Beaver. For example,

sender = address.addr {: return new Sender(name, addr); };

In NeoBeaver you can use automatic component names:

sender = name address {: return new Sender(name, address); };

Directives anywhere

Beaver does not allow directives (like %left and %terminals) to be mixed with grammar productions. This restriction is removed in NeoBeaver.

How to run it

Use the following commands to generate a classic Beaver parser using NeoBeaver:

gradle jar
java -jar neobeaver.jar --beaver <grammar>

Beaver Frontend

There is a frontend with the same interface as classic Beaver. The frontend uses the Maven id nbfront.


Copyright (c) 2017, Jesper Öqvist

This project is provided under the Modified BSD License. See the LICENSE file, in the same directory as this README file.