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
//! Nom, eating data byte by byte //! //! The goal is to make a parser combinator library that is safe, //! supports streaming (push and pull), and as much as possible zero copy. //! //! The code is available on [Github](https://github.com/Geal/nom) //! //! # Example //! //! ``` //! #[macro_use] //! extern crate nom; //! //! use nom::{Consumer,ConsumerState,MemProducer,IResult}; //! use nom::IResult::*; //! //! // Parser definition //! //! named!( om_parser, tag!( "om" ) ); //! named!( nomnom_parser< &[u8], Vec<&[u8]> >, many1!( tag!( "nom" ) ) ); //! named!( end_parser, tag!( "kthxbye") ); //! //! //! // Streaming parsing and state machine //! //! #[derive(PartialEq,Eq,Debug)] //! enum State { //! Beginning, //! Middle, //! End, //! Done //! } //! //! struct TestConsumer { //! state: State, //! counter: usize //! } //! //! impl Consumer for TestConsumer { //! fn consume(&mut self, input: &[u8]) -> ConsumerState { //! match self.state { //! State::Beginning => { //! match om_parser(input) { //! Error(_) => ConsumerState::ConsumerError(0), //! Incomplete(_) => ConsumerState::Await(0, 2), //! Done(_,_) => { //! // "om" was recognized, get to the next state //! self.state = State::Middle; //! ConsumerState::Await(2, 3) //! } //! } //! }, //! State::Middle => { //! match nomnom_parser(input) { //! Error(a) => { //! // the "nom" parser failed, let's get to the next state //! self.state = State::End; //! ConsumerState::Await(0, 7) //! }, //! Incomplete(_) => ConsumerState::Await(0, 3), //! Done(i,noms_vec) => { //! // we got a few noms, let's count them and continue //! self.counter = self.counter + noms_vec.len(); //! ConsumerState::Await(input.len() - i.len(), 3) //! } //! } //! }, //! State::End => { //! match end_parser(input) { //! Error(_) => ConsumerState::ConsumerError(0), //! Incomplete(_) => ConsumerState::Await(0, 7), //! Done(_,_) => { //! // we recognized the suffix, everything was parsed correctly //! self.state = State::Done; //! ConsumerState::ConsumerDone //! } //! } //! }, //! State::Done => { //! // this should not be called //! ConsumerState::ConsumerError(42) //! } //! } //! } //! //! fn failed(&mut self, error_code: u32) { //! println!("failed with error code: {}", error_code); //! } //! //! fn end(&mut self) { //! println!("we counted {} noms", self.counter); //! } //! } //! //! fn main() { //! let mut p = MemProducer::new(b"omnomnomnomkthxbye", 4); //! let mut c = TestConsumer{state: State::Beginning, counter: 0}; //! c.run(&mut p); //! //! assert_eq!(c.counter, 3); //! assert_eq!(c.state, State::Done); //! } //! ``` //! #![cfg_attr(feature = "core", feature(no_std))] #![cfg_attr(feature = "core", feature(core))] #![cfg_attr(feature = "core", feature(collections))] #![cfg_attr(feature = "core", no_std)] #[macro_use] #[cfg(feature = "core")] extern crate core; #[cfg(feature = "core")] extern crate collections; #[cfg(feature = "core")] mod std { #[macro_use] pub use core::{fmt, iter, option, ops, slice, mem}; pub use collections::{boxed, vec, string}; pub mod prelude { pub use core::prelude as v1; } } pub use self::util::*; pub use self::internal::*;//{IResult, IResultClosure, GetInput, GetOutput}; pub use self::macros::*; #[cfg(not(feature = "core"))] pub use self::producer::*;//{ProducerState,Producer,FileProducer,MemProducer}; #[cfg(not(feature = "core"))] pub use self::consumer::*;//{ConsumerState,Consumer}; pub use self::nom::*; #[macro_use] mod util; mod internal; #[macro_use] mod macros; #[macro_use] #[cfg(not(feature = "core"))] mod producer; #[cfg(not(feature = "core"))] mod consumer; #[macro_use] mod nom;