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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
//! 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. (*Note: parser allows for an optional ';'
//! 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 for DNA sequences to be input to this library's
//! `parse` function.
//! ```text
//! <dna> ::= <base> | <base> <dna>
//! <base> ::= "A" | "C" | "G" | "T"
//! ```
//!
//! The output is a `Grammar` object representing a tree that looks like this:
//! ```text
//! Grammar {
//!     productions: [
//!         Production {
//!             lhs: Nonterminal(
//!                 "dna"
//!             ),
//!             rhs: [
//!                 Expression {
//!                     terms: [
//!                         Nonterminal(
//!                             "base"
//!                         )
//!                     ]
//!                 },
//!                 Expression {
//!                     terms: [
//!                         Nonterminal(
//!                             "base"
//!                         ),
//!                         Nonterminal(
//!                             "dna"
//!                         )
//!                     ]
//!                 }
//!             ]
//!         },
//!         Production {
//!             lhs: Nonterminal(
//!                 "base"
//!             ),
//!             rhs: [
//!                 Expression {
//!                     terms: [
//!                         Terminal(
//!                             "A"
//!                         )
//!                     ]
//!                 },
//!                 Expression {
//!                     terms: [
//!                         Terminal(
//!                             "C"
//!                         )
//!                     ]
//!                 },
//!                 Expression {
//!                     terms: [
//!                         Terminal(
//!                             "G"
//!                         )
//!                     ]
//!                 },
//!                 Expression {
//!                     terms: [
//!                         Terminal(
//!                             "T"
//!                         )
//!                     ]
//!                 }
//!             ]
//!         }
//!     ]
//! }
//! ```
//!
//! Once the `Grammar` object is populated you can generate a random sentence
//! from it by calling the object's generate function. `grammar.generate()`.
//! For the above grammar you could expect something like "T" "TGGC" or "AG".
//!
//! If the generate function can't find a production for a nonterminal it tries
//! to evaluate it will produce the identifer as is, i.e. `<identifier>`.
//!
//! The generate function will return an error if it detects an infinite loop
//! caused by a production such as `<PATTERN> ::= <PATTERN>`.
//!
//! ## Parse Example
//!
//! ```rust
//! extern crate bnf;
//! use bnf::Grammar;
//!
//! 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 = Grammar::from_str(input);
//!     match grammar {
//!         Ok(g) => println!("{:#?}", g),
//!         Err(e) => println!("Failed to make grammar from String: {}", e),
//!     }
//! }
//! ```
//!
//! ## Generate Example
//!
//! ```rust
//! extern crate bnf;
//! use bnf::Grammar;
//!
//! fn main() {
//!     let input =
//!         "<dna> ::= <base> | <base> <dna>
//!         <base> ::= \"A\" | \"C\" | \"G\" | \"T\"";
//!     let grammar = Grammar::from_str(input).unwrap();
//!     let sentence = grammar.generate();
//!     match sentence {
//!         Ok(s) => println!("random sentence: {}", s),
//!         Err(e) => println!("something went wrong: {}!", e)
//!     }
//! }
//! ```
//!

#[macro_use]
extern crate nom;
extern crate rand;
extern crate stacker;
mod parsers;
mod error;
mod term;
mod expression;
mod production;
mod grammar;
pub use term::Term;
pub use expression::Expression;
pub use production::Production;
pub use grammar::Grammar;
pub use error::Error;