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 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
//! # TreeBuilder, a lightweight, nom-based parser generator library for Rust
//!
//! TreeBuilder is a parser generator focused on the correct parsing of context-free grammars
//! from ASCII input strings. It generates recursive-descent, backtracking parsers with as little code
//! as possible and with convenient features. The parsers it generates aim to be very easy to use and
//! to be compatable with Nom parsers if the user wishes to use Nom together with
//! TreeBuilder. TreeBuilder will not be supporting left-recursive grammars in this version.
//!
//! TreeBuilder's [Parser] trait shows the type signature of all
//! TreeBuilder-generated parsers.
//!
//! Example:
//!
//! ```rust
//! use tree_builder::{build_tree, Parser};
//!
//! build_tree! {
//! // Parses a Hex color
//! HexColor #=> "#",
//! HexDigit,
//! HexDigit?, HexDigit?, HexDigit?, HexDigit?, HexDigit?;
//!
//! // Parses a Hex digit
//! HexDigit #=> [0-9a-fA-F];
//! }
//!
//! fn main() {
//! // Will pass
//! HexColor::parse("#abd325").unwrap();
//! HexColor::parse("#asd000").unwrap();
//! // Will fail
//! HexColor::parse("#whatever").unwrap();
//! }
//! ```
//!
//! ## Kinds of rules
//!
//! TreeBuilder can either generate parsers whose output data structure is just
//! a String, or parsers whose output data structure is a more complicated tuple
//! type. If you use the arrow **#=>** to separate the rule name from it's
//! definition, you have created a lexical rule which outputs String, but if you
//! use **=>**, you have the option to specify what parts of a rule definition
//! you wish to keep.
//!
//! You specify the parts you wish to keep using the **@** operator (called
//! Include). Data structures for parsers are based on the includes you have
//! made, from left to right.
//!
//! Let's take for example the rules Arraya and ArrayElems which parse JSON
//! arrays below:
//!
//! ```rust
//! build_tree!{
//! JValue => /* Definition of a JSON value */;
//!
//! Array => "[", #s*, @ArrayElems?, #s*, "]";
//! ArrayElems => @JValue, #s*, @(",", #s*, @JValue, #s*)*;
//! }
//! ```
//!
//! The data structures generated for the rules above are:
//!
//! ```rust
//! struct Array(Optional<Box<ArrayElems>>);
//!
//! struct ArrayElems(Box<JValue>, Vec<Box<JValue>>);
//! ```
//!
//! When you use alternations, the data structures generated are enums, whose
//! variant names are either inferred when you only include a single
//! non-terminal in an alternation, or need to be specified.
//!
//! Alternation rule example:
//!
//! ```rust
//! build_tree!{
//! // Rule representing a JSON value
//! JValue => @JString
//! | @Number
//! | @Object
//! | @Array
//! | "true" <True>
//! | "false" <False>
//! | "null" <Null>;
//! }
//! ```
//!
//! And the data structure generated by this rule:
//!
//! ```rust
//! enum JValue {
//! JString(Box<JString>),
//! Number(Box<Number>),
//! Object(Box<Object>),
//! Array(Box<Array>),
//! True(),
//! False(),
//! Null(),
//! }
//! ```
//!
//! Keep in mind that in the rules denoted by **=>**, you cannot use
//! alternations inside of groupings at the moment. This limitation will
//! probably be fixed in the next update.
//!
//! ## TreeBuilder's language
//!
//! TreeBuilder allows for the specification of grammars which use terminals,
//! non-terminals, metacharacters and groupings/sub-parsers. Different operators
//! can be applied to the aforementioned elements which define how many times
//! one of them may be repeated.
//!
//! ### Available terms:
//!
//! 1. **Terminals**: Terminals are written just like strings in any C-like
//! language. They are defined as a string of characters which can be either
//! any character except ’\’ and ’”’, or a character escape sequence such as
//! ’\n’, delimited by double quotes.
//! The possible escape sequences are:
//! * \n (newline)
//! * \r (carriage return)
//! * \t (tab)
//! * \b (non-destructive backspace)
//! * \f (form feed)
//! * \\ (backslash)
//! * \” (double quote)
//!
//! Some examples of terminals:
//! * ”for”
//! * ”if”
//! * ”a123\nb!?.\tc\””
//!
//! 2. **Metacharacters**: A metacharacter is a special character that carries a
//! specific meaning or functionality within a grammar specification. Unlike
//! terminals, which parse their string equivalent, metacharacters have
//! special interpretations and serve as building blocks for constructing
//! powerful and elegant parser rules with as little code as possible. Here
//! are the metacharacters and their meanings:
//!
//! * **. (Dot)**: Matches any single character except a newline. It acts as a wildcard, repre-
//! senting any character in the input string.
//! * **\[ \] (Character Class)**: Matches any single character specified inside the square brack-
//! ets. For example, \[aeiou\] matches any vowel character.
//! * **[^ ] (Negated Character Class)**: Matches any single character that is not specified
//! inside the square brackets. For example, \[^0-9\] matches any non-digit character.
//! * **#d**: Matches any digit character. It is equivalent to the character class \[0-9\]. For
//! example, #d would match any digit from 0 to 9.
//! * **#D**: Matches any non-digit character. It is equivalent to the character class \[^0-9\].
//! For example, #D would match any character which isn’t a digit.
//! * **#w**: Matches any word character. It includes alphanumeric characters (a-z, A-Z, and
//! 0-9) as well as the underscore (_) character. It is equivalent to the character class
//! \[a-zA-Z0-9_\].
//! * **#W**: Matches any non-word character. It excludes alphanumeric characters (a-z, A-
//! Z, and 0-9) as well as the underscore (_) character, matching anything else. It is
//! equivalent to the character class \[^a-zA-Z0-9_\].
//! * **#s**: Matches any ASCII whitespace character, so matches any one of \f, \n, \r, \t.
//!
//! 3. **Nonterminals**: Their syntax is exactly the same as ASCII Rust identifiers. A string be-
//! ginning with either an alphabetic character or an underscore, followed by a string of either
//! alphanumerics, an underscore, or both. Their use in the definition of grammars is to spec-
//! ify that another rule is part of the rule you are currently specifying. So the parser which
//! will be generated from a rule which uses a nonterminal will apply the parser related to the
//! nonterminal at the point specified by the user.
//!
//! 4. **Groupings**: grouping refers to the act of enclosing a sequence of elements or subexpres-
//! sions within parentheses. It allows for establishing precedence and controlling the evalu-
//! ation order of elements within a grammar specification. These are grouped as one of the
//! smaller elements of the language because other operators can be applied groupings just like
//! they can be applied to the other terms.
//!
//! ### Available operators:
//!
//! | Operator | Description |
//! |----------|--------------------|
//! | e \| e | Alternation |
//! | @e | Include |
//! | e? | Optional |
//! | e* | Zero-or-more |
//! | e+ | One-or-more |
//!
//! Alternations in TreeBuilder are ordered-choice ones, meaning that out of all
//! the alternatives that you may define for a rule, only one of the
//! alternatives can succeed. This occurs because TreeBuilder will try
//! alternatives from the one defined first all the way to the last one in
//! order, and if any of the alternatives successfully parses for an input
//! string, the alternations after it are ignored completely.
//!
pub use __private::nom::error::convert_error;
/// Accepts a single grammar rule. This macro will only generate a parser for
/// a data structure, it expects you to supply with a data structure yourself.
/// This was added to allow for custom derives and visibility modifiers for data
/// structures.
///
/// Example:
/// ```
/// use tree_builder::ast_parser_maker;
///
/// #[derive(Clone, Debug)]
/// pub struct Digit(String);
///
/// ast_parser_maker!{
/// Digit => @#d*
/// }
/// ```
pub use tree_builder_macro::ast_parser_maker;
/// Accepts grammar specifications separated by semicolons. This macro will generate
/// parsers and data structures for all the grammar specifications inputted to it.
///
/// Example:
/// ```
/// use tree_builder::build_tree;
///
/// build_tree!{
/// Digit => #d;
/// Letter => [a-zA-Z];
/// }
/// ```
pub use tree_builder_macro::build_tree;
/// Accepts a single grammar rule. This macro will generate
/// a parser and data structure for the grammar specification inputted to it.
///
/// Example:
/// ```
/// use tree_builder::rule;
///
/// rule!{
/// Digit => #d
/// }
/// ```
pub use tree_builder_macro::rule;
/// Module to allow for the access of Nom and other dependencies by the
/// generated parsers
pub mod __private;
/// Module in which new parsers written for this library are kept
pub mod public_parsers;
/// Trait which specifies the function "parse", the function which gets
/// generated by TreeBuilder.
pub trait Parser {
fn parse(input: &str) -> nom::IResult<&str, Box<Self>, nom::error::VerboseError<&str>>;
}