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
//! 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 each 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() }