New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to use take_until_range() as part of your own parser? #192
Comments
There are actually only 4 errors here, it is just that cargo outputs them twice since I believe you are compiling in test mode (which is rather annoying).
You need to bound That will fix the errors to make |
Following your suggestions in gitter, I came up with this: fn mt940_tag<I>() -> impl Parser<Input = I, Output = String>
where
I: Stream<Item = char>,
I::Error: ParseError<I::Item, I::Range, I::Position>,
{
(
token(':'),
char::digit(),
many::<String, _>(char::alpha_num()),
token(':'),
)
.map(|(_, x, y, _)| format!("{}{}", x, y))
}
fn mt940_record_start<I>() -> impl Parser<Input = I, Output = (String, String)>
where
I: Stream<Item = char>,
I::Error: ParseError<I::Item, I::Range, I::Position>,
{
(mt940_tag(), take_until(byte::bytes(&b"\r\n"[..])))
} Which gives me
I tried giving it various types and mapping it but to no avail. Help appreciated. :) |
These all boil down to the same error in the end and the only real way to solve it is to slowly read through the error to understand what rustc fails at. The second from the bottom is probably the clearerest (by a slight margin).
Here it says that it expected a In this case you have specified Any other of the errors could lead us to the same conclusion in a slight less clear way as they all boil down to trying to use |
Oh, thanks! Well, reading the error is one thing but figuring out exactly what it means in relation to my code is another. I suggest adding an example for char::string to the |
So right now I'm here: fn mt940_tag<I>() -> impl Parser<Input = I, Output = String>
where
I: Stream<Item = char>,
I::Error: ParseError<I::Item, I::Range, I::Position>,
{
(
token(':'),
char::digit(),
many::<String, _>(char::alpha_num()),
token(':'),
)
.map(|(_, x, y, _)| format!("{}{}", x, y))
}
fn mt940_record_start<I>() -> impl Parser<Input = I, Output = (String, String)>
where
I: Stream<Item = char>,
I::Error: ParseError<I::Item, I::Range, I::Position>,
{
(mt940_tag(), take_until(char::string("\r\n")))
}
fn mt940_record<I>() -> impl Parser<Input = I, Output = String>
where
I: Stream<Item = char>,
I::Error: ParseError<I::Item, I::Range, I::Position>,
{
(
mt940_record_start(),
many((not_followed_by(look_ahead(mt940_tag())), char::string("\r\n"))),
).map(|(_, _)| "test".to_string())
} and it's telling me
The problem is that I can't just define that for So I tried mapping that output to fn mt940_record<I>() -> impl Parser<Input = I, Output = String>
where
I: Stream<Item = char>,
I::Error: ParseError<I::Item, I::Range, I::Position>,
{
(
mt940_record_start(),
many((not_followed_by(look_ahead(mt940_tag()).map(|x| x.as_str())), char::string("\r\n"))),
).map(|(_, _)| "lol".to_string())
} which then resulted in
Ok so far so good. Now I needed annotations on fn mt940_record<I>() -> impl Parser<Input = I, Output = String>
where
I: Stream<Item = char>,
I::Error: ParseError<I::Item, I::Range, I::Position>,
{
(
mt940_record_start(),
many::<String, _>((not_followed_by(look_ahead(mt940_tag()).map(|x| x.as_str())), char::string("\r\n"))),
).map(|(_, _)| "lol".to_string())
} gets me
Now where does my static lifetime come from? I don't quite yet and frankly, I think I'm going down the wrong road on this. Please help. :) |
The static lifetime comes from what
You are trying to extend with a tuple here as you are passing a tuple of parsers to
Just using
As an aside, do you really want a |
Thanks, that was the last bit I needed to actually make it compile. Types are magical. And I believe I want a Anyway, I believe the problem that I originally asked for help with in Gitter is not actually solved and that's how to parse the line format properly. For reference, I'm putting my whole bunch of code there. The problem is that the extern crate combine;
use combine::parser::char;
use combine::parser::repeat::take_until;
use combine::*;
#[derive(Debug, PartialEq)]
pub struct Record {
pub tag: String,
pub message: String,
}
fn mt940_tag<I>() -> impl Parser<Input = I, Output = String>
where
I: Stream<Item = char>,
I::Error: ParseError<I::Item, I::Range, I::Position>,
{
(
token(':'),
char::digit(),
many::<String, _>(char::alpha_num()),
token(':'),
)
.map(|(_, x, y, _)| format!("{}{}", x, y))
}
fn mt940_record_start<I>() -> impl Parser<Input = I, Output = (String, String)>
where
I: Stream<Item = char>,
I::Error: ParseError<I::Item, I::Range, I::Position>,
{
(mt940_tag(), take_until(char::string("\r\n")))
}
fn mt940_record<I>() -> impl Parser<Input = I, Output = Record>
where
I: Stream<Item = char>,
I::Error: ParseError<I::Item, I::Range, I::Position>,
{
(
mt940_record_start(),
many::<String, _>(
(
not_followed_by(look_ahead(mt940_tag()).map(|_| "mt940_tag")),
char::string("\r\n"),
)
.map(|(_, x)| x),
),
)
.map(|(start, rest)| Record {
tag: start.0,
message: format!("{start}{rest}", start = start.1, rest = rest),
})
}
/// A Statement is just a list of Records.
fn mt940_statement<I>() -> impl Parser<Input = I, Output = Vec<Record>>
where
I: Stream<Item = char>,
I::Error: ParseError<I::Item, I::Range, I::Position>,
{
many1::<Vec<_>, _>(mt940_record())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parse_mt940_tag() {
let expected = Ok(("20".to_string(), ""));
let result = mt940_tag().easy_parse(":20:");
assert_eq!(expected, result);
}
#[test]
fn parse_mt940_record_start() {
let expected = Ok((("20".to_string(), "3996-11-11111111".to_string()), "\r\n"));
let result = mt940_record_start().easy_parse(":20:3996-11-11111111\r\n");
assert_eq!(expected, result);
}
#[test]
fn parse_mt940_record() {
let expected = Ok((
Record {
tag: "20".to_string(),
message: "3996-11-11111111\r\nTESTTEST\r\nMORETEST\r\n".to_string(),
},
"",
));
let result = mt940_record().easy_parse(":20:3996-11-11111111\r\nTESTTEST\r\nMORETEST\r\n");
assert_eq!(expected, result);
}
#[test]
fn parse_mt940_statement() {
let test_data = "\
:20:3996-1234567890\r\n\
:25:DABADKKK/1234567890\r\n\
:28C:00014/001\r\n\
:60F:C091019DKK3859701,48\r\n\
:86:For your inform. IBAN no.: DK5030001234567890\r\n\
:86:DABADKKK \r\n\
:86:1234567890\r\n\
:86:DANSKE BANK HOLMENS KANAL 2-12\r\n\
:61:0910201020DK5312,50NMSCDBT.teste kunden\r\n\
:86:F.M.T.\r\n\
V/TESTE KUNDEN\r\n\
HOLMENS KANAL 2-12\r\n\
1192 KOBENHAVN H\r\n\
:61:0910201020DK3009,51NMSCDBT.Pet Van Park\r\n\
:86:DBTS 1111272333/Bnf. PET VAN PARK AMSTERDAM/Bnf.acc. NL47ABNAXXXX\r\n\
558756/Our fee DKK 40,00/Foreign fee DKK 200,00\r\n\
:62F:C091020DKK3851379,47\r\n\
:64:C091020DKK3851379,47\r\n\
\r\n
";
let expected = Ok((
vec![
Record {
tag: "20".to_string(),
message: "3996-1234567890".to_string(),
},
Record {
tag: "25".to_string(),
message: "DABADKKK/1234567890".to_string(),
},
Record {
tag: "28C".to_string(),
message: "00014/001".to_string(),
},
Record {
tag: "60F".to_string(),
message: "C091019DKK3859701,48".to_string(),
},
Record {
tag: "86".to_string(),
message: ")
For your inform. IBAN no.: DK5030001234567890\n\
DABADKKK\n\
1234567890\n\
DANSKE BANK HOLMENS KANAL 2-12\n\
".to_string(),
},
Record {
tag: "61".to_string(),
message: "0910201020DK5312,50NMSCDBT.teste kunden".to_string(),
},
Record {
tag: "86".to_string(),
message: "F.M.T.\n\
V/TESTE KUNDEN\n\
HOLMENS KANAL 2-12\n\
1192 KOBENHAVN H\n\
".to_string(),
},
Record {
tag: "61".to_string(),
message: "0910201020DK3009,51NMSCDBT.Pet Van Park".to_string(),
},
Record {
tag: "86".to_string(),
message: "DBTS 1111272333/Bnf. PET VAN PARK AMSTERDAM/Bnf.acc. NL47ABNAXXXX\n\
558756/Our fee DKK 40,00/Foreign fee DKK 200,00"
.to_string(),
},
Record {
tag: "62F".to_string(),
message: "C091020DKK3851379,47".to_string(),
},
Record {
tag: "64".to_string(),
message: "C091020DKK3851379,47".to_string(),
},
],
"",
));
let result = mt940_statement().easy_parse(test_data);
assert_eq!(expected, result);
}
} |
I think you are just missing a |
I believe we worked this out on gitter, so closing (feel free to re-open if necessary). |
So I have a parser that looks like this:
But that gives me a lot of errors:
I really only want a parser that recognizes something until "\r\n".
The text was updated successfully, but these errors were encountered: