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
//! 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 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); //! } //! ``` //! pub use self::util::*; pub use self::internal::*;//{IResult, IResultClosure, GetInput, GetOutput}; pub use self::macros::*; pub use self::producer::*;//{ProducerState,Producer,FileProducer,MemProducer}; pub use self::consumer::*;//{ConsumerState,Consumer}; pub use self::nom::*; #[macro_use] pub mod util; pub mod internal; #[macro_use] pub mod macros; #[macro_use] pub mod producer; pub mod consumer; #[macro_use] pub mod nom;