1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
//! bnf, a library for parsing Backus–Naur form context-free grammars
//! 
//! Inspired by the JavaScript library [prettybnf](https://github.com/dhconnelly/prettybnf)
//! 
//! 
//! The code is available on [Github](https://github.com/snewt/bnf)
//! 
//! ## What does a parsable BNF grammar look like?
//! 
//! The following grammar from the [Wikipedia page on Backus-Naur form](https://en.wikipedia.org/wiki/Backus%E2%80%93Naur_form#Example)
//! exemplifies a compatible grammar after adding ';' characters to indicate the end of a producion.
//! 
//! ```text
//! <postal-address> ::= <name-part> <street-address> <zip-part>;
//! 
//!         <name-part> ::= <personal-part> <last-name> <opt-suffix-part> <EOL>
//!                     | <personal-part> <name-part>;
//! 
//!     <personal-part> ::= <initial> "." | <first-name>;
//! 
//!     <street-address> ::= <house-num> <street-name> <opt-apt-num> <EOL>;
//! 
//!         <zip-part> ::= <town-name> "," <state-code> <ZIP-code> <EOL>;
//! 
//! <opt-suffix-part> ::= "Sr." | "Jr." | <roman-numeral> | "";
//!     <opt-apt-num> ::= <apt-num> | "";
//! ```
//! 
//! ## Output
//! Take the following grammar to be input to this library's `parse` function:
//!
//! ```text
//! <A> ::= <B> | "C";
//! <B> ::= "D" | "E"; 
//! ```
//! 
//! The output is a `Grammar` object representing a tree that looks like this:
//!
//! ```text
//! Grammar {
//!     productions: [
//!         Production {
//!             lhs: Nonterminal(
//!                 "A"
//!             ),
//!             rhs: [
//!                 Expression {
//!                     terms: [
//!                         Nonterminal(
//!                             "B"
//!                         )
//!                     ]
//!                 },
//!                 Expression {
//!                     terms: [
//!                         Terminal(
//!                             "C"
//!                         )
//!                     ]
//!                 }
//!             ]
//!         },
//!         Production {
//!             lhs: Nonterminal(
//!                 "B"
//!             ),
//!             rhs: [
//!                 Expression {
//!                     terms: [
//!                         Terminal(
//!                             "D"
//!                         )
//!                     ]
//!                 },
//!                 Expression {
//!                     terms: [
//!                         Terminal(
//!                             "E"
//!                         )
//!                     ]
//!                 }
//!             ]
//!         }
//!     ]
//! }
//! ```
//! 
//! ## Example
//! 
//! ```rust
//! extern crate bnf;
//! 
//! fn main() {
//!     let input =
//!         "<postal-address> ::= <name-part> <street-address> <zip-part>;
//! 
//!               <name-part> ::= <personal-part> <last-name> <opt-suffix-part> <EOL>
//!                             | <personal-part> <name-part>;
//! 
//!           <personal-part> ::= <initial> \".\" | <first-name>;
//! 
//!          <street-address> ::= <house-num> <street-name> <opt-apt-num> <EOL>;
//! 
//!                <zip-part> ::= <town-name> \",\" <state-code> <ZIP-code> <EOL>;
//! 
//!         <opt-suffix-part> ::= \"Sr.\" | \"Jr.\" | <roman-numeral> | \"\";
//!             <opt-apt-num> ::= <apt-num> | \"\";";
//! 
//!     let grammar = bnf::parse(input);
//!     println!("{:#?}", grammar);
//! }
//! ```
//!

#[macro_use] extern crate nom;
mod parsers;
mod reports;
pub mod node;
use node::{Grammar};
use nom::{IResult};

/// Parse a BNF grammer
pub fn parse(input: &str) -> Grammar {
    match parsers::grammar(input.as_bytes()) {
        IResult::Done(_,o) => return o,
        IResult::Error(e) => {
            reports::report_error(e);
        }
        IResult::Incomplete(n) => reports::report_incomplete(n, input.len()),
    }

    Grammar::new()
}