# BNFC 3.0 A reimplementation of [BNFC](https://github.com/BNFC/bnfc). ## Goals of BNFC BNFC is a **wizard** to generate parsers and printers in different programming languages (PL) from a readable grammar in Labelled Backus-Naur Form (LBNF). Its prime intended uses are those: 1. In teaching, to speed up the generation of a compiler front-end so students can focus on the more interesting back-end. The multi-backend structure of BNFC is especially important for the use in teaching, since not all students use Haskell. 2. In computer language prototyping, to quickly get basic infrastructure (parser, printer, AST). 3. In more serious software projects, to get started on a parser which may later be hand-edited to implement more subtle language features. A common benefit of BNFC to all users is that they do not need to master the ugly ad-hoc syntax of parser generators (I only say "`yacc`"). Goals derived from these use cases are: 1. BNFC should be correct, i.e., have a specification and follow it. This is a common goal of much of PL-related software, I suppose. 2. BNFC should be user/beginner-friendly. - BNFC should give comprehensible error messages with error location. - BNFC should alert users of common mistakes. Example: `coercions` applied to wrong range, or duplicating a _parenthesis_ rule. 3. BNFC should output pretty code that can serve as basis for hand-editing. Users do look at the generated code. - Well-chosen identifiers. - Tabular alignment where possible. - Comments pointing to the origin of generated code (from which grammar rule). 4. BNFC should be robust. - Generated code should build in the overwhelming majority of cases. Clashes with language keywords and builtin identifiers should be avoided. - BNFC should evolve in a backwards-compatible way if reasonable. ## Problems with BNFC Version 2 From the user perspective: - Lack of robustness, produces garbage in corner cases rather than reporting an error. - Lack of good error messages. - Lack of some basic features in some backends, e.g. position information. - Lack of modularity, e.g. defining two grammars that share some AST types. - Lack of configurability of printer. From the developer perspective: 1. Hard to maintain. - Internal data structures do not express invariants. - Lots of cut-and-paste code. - Backends do not share common routines, each backend generates output from scratch. - Feature bloat (`rules`, `define`, `layout`, left-recursion introduction). 2. Hard to extend. - Each backend has to reinvent the wheel, since common API for backends is missing. - Feature bloat: obscure features like `define` and `layout` make backends harder to implement. ## Goals of reimplemenation 1. Improve maintainability of BNFC - better internal data structures that express invariants - common API for backends - well-structured testsuite that can be run in reasonable time and on CI servers 2. Improve robustness and UX of BNFC - thorough "type" checking of the LBNF with good error message. 3. Improve output of BNFC - e.g. use readable, common names for symbols in the parser (e.g. `LPAREN` for "(") - e.g. use pretty-printing library for Haskell printer