A special input type for nom to locate tokens
The documentation of the crate is available here.
The crate provide the LocatedSpan
struct that encapsulates the data. Look at the below example and the explanations:
````rust
extern crate nom;
extern crate nom_locate;
use nom::types::CompleteStr;
use nom_locate::LocatedSpan;
type Span<'a> = LocatedSpan
struct Token<'a> { pub position: Span<'a>, pub foo: String, pub bar: String, }
named!(parsefoobar( Span ) -> Token, doparse!( takeuntil!("foo") >> position: position!() >> foo: tag!("foo") >> bar: tag!("bar") >> (Token { position: position, foo: foo.tostring(), bar: bar.to_string() }) ));
fn main () { let input = Span::new(CompleteStr("Lorem ipsum \n foobar")); let output = parsefoobar(input); let position = output.unwrap().1.position; asserteq!(position, Span { offset: 14, line: 2, fragment: CompleteStr("") }); asserteq!(position.getcolumn(), 2); } ````
Import nom and nom_locate.
````rust
extern crate nom; extern crate nom_locate;
use nom_locate::LocatedSpan; ````
Also you'd probably create type alias for convenience so you don't have to specify the fragment
type every time:
rust
type Span = LocatedSpan<CompleteStr>;
Note you'd better in most case use CompleteStr in order to optimize your parser.
The output structure of your parser may contain the position as a Span
(which provides the index
, line
and column
information to locate your token).
rust
struct Token<'a> {
pub position: Span<'a>,
pub foo: String,
pub bar: String,
}
The parser has to accept a Span
as an input. You may use position!()
in your nom parser, in order to capture the location of your token:
rust
named!(parse_foobar( Span ) -> Token, do_parse!(
take_until!("foo") >>
position: position!() >>
foo: tag!("foo") >>
bar: tag!("bar") >>
(Token {
position: position,
foo: foo.to_string(),
bar: bar.to_string()
})
));
The parser returns a nom::IResult<Token, _>
(hence the unwrap().1
). The position
property contains the offset
, line
and column
.
rust
fn main () {
let input = Span::new("Lorem ipsum \n foobar");
let output = parse_foobar(input);
let position = output.unwrap().1.position;
assert_eq!(position, Span {
offset: 14,
line: 2,
fragment: ""
});
assert_eq!(position.get_column(), 2);
}