Target of this library is to provide a flexible approach in parsing data. This will mainly be done within
arena based
parser trees which can be modified during runtime. Every parser is using the
nom framework for the actual parsing work. A complete source code example can be found
within the src/example
directory of the crate.
Every Peel
instance can be seen as a parsing graph structure which has different states and transitions. In the
example within the crate the structure looks like this:
Independently of what these parser do, the creation of this structure is done within the peel_example
function:
``rust
/// Return a
Peel` instance for the example parsers
pub fn peelexample() -> Peel
// Create and link the parsers
let parser_1 = p.new_parser(Parser1);
// Append Parser2 to Parser1
let parser_2 = p.link_new_parser(parser_1, Parser2);
// Append Parser3 to Parser1
let parser_3 = p.link_new_parser(parser_1, Parser3);
// Parser 3 referse to itself
p.link(parser_3, parser_3);
// Parser 2 referse to Parser 3
p.link(parser_2, parser_3);
// Append Parser4 to Parser3
p.link_new_parser(parser_3, Parser4);
p
} ```
The first created parser will automatically be the root parser and the entry point for the tree traversal. Every parser returns an actual result, which will be pushed into a vector. This means for our example that the result is an enum of different types:
```rust /// Return values of the parsers pub enum ParserResult { /// The result of the first example parser Result1,
/// The result of the second example parser
Result2,
/// The result of the third example parser
Result3,
/// The result of the fourth example parser
Result4,
} ```
This means that the traversal method of Peel
will try to find the deepest possible valid path within the tree
structure. After the creation of the structure the traversal can begin:
```rust let mut peel = peelexample(); peel.setlog_level(LogLevel::Trace); let result = peel.traverse(b"1234", vec![]).unwrap();
assert_eq!(result.len(), 4); println!("{:?}", result); ```
With the help of the log crate it will output:
[peel] [DEBUG] Parser 1 parsing succeed, left input length: 3
[peel] [DEBUG] Failed parser: Parser 3
[peel] [DEBUG] Parser 2 parsing succeed, left input length: 2
[peel] [DEBUG] Parser 3 parsing succeed, left input length: 1
[peel] [DEBUG] Parser 4 parsing succeed, left input length: 0
[Result1, Result2, Result3, Result3, Result4]
A minimal parser has to implement the Parser
trait which could look like this:
```rust
pub struct Parser1;
impl Parser for Parser1 { /// The result of the parser type Result = ParserResult;
/// The variant of the parser
type Variant = ParserVariant;
/// The actual parsing entry point
fn parse<'a>(&self,
input: &'a [u8], // The input for the parser
node: Option<&ParserNode>, // The current node within the tree
graph: Option<&ExampleGraph>, // Access to possible other nodes via the graph
result: Option<&Vec<Self::Result>>) // The current parsing result
-> IResult<&'a [u8], Self::Result> {
do_parse!(input,
tag!("1") >>
(ParserResult::Result1)
)
}
// Returns the actual parser variant
fn variant(&self) -> Self::Variant {
ParserVariant::Variant1(self.clone())
}
} ```
For event more advanced behavior the node
and graph
can be used to find out where the parser is located within the
current structure. Access to the current parsing result
is possible as well.
You want to contribute to this project? Wow, thanks! So please just fork it and send me a pull request.