parse_action: everything before keyword is an identifier
Some checks are pending
ci/woodpecker/push/woodpecker Pipeline is pending

Signed-off-by: Maxime “pep” Buquet <pep@bouah.net>
This commit is contained in:
Maxime “pep” Buquet 2023-01-11 00:14:12 +01:00
parent 0aec3cea6e
commit 1cb94ccfaf
Signed by: pep
GPG key ID: DEDA74AEECA9D0F2

View file

@ -12,7 +12,7 @@ use minidom::Element;
use nom::{
self,
branch::alt,
bytes::complete::{tag, take_until, take_until1, take_while1},
bytes::complete::{tag, take_until, take_until1, take_while, take_while1},
character::complete::{multispace0, space0, space1},
combinator::recognize,
multi::{many0, many1},
@ -102,57 +102,74 @@ fn parse_sep(i: &str) -> IResult<&str, &str> {
Ok((i, ""))
}
fn parse_connect(i: &str) -> IResult<&str, Action> {
let (i, (name, _, _)) = tuple((take_while1(is_not_space), space1, tag("connects\n")))(i)?;
fn parse_action(i: &str) -> IResult<&str, Action> {
let mut name = String::new();
let (i, namepart) = recognize(tuple((take_while1(is_not_space), space1)))(i)?;
name.push_str(namepart);
Ok((i, Action::Connect(String::from(name))))
let mut i = i;
let (i, tagname) = loop {
let res = tuple((
alt((
tag("connects"),
tag("disconnects"),
tag("sends:"),
tag("receives:"),
)),
space0,
tag("\n"),
))(i);
match res {
Ok((i, (tagname, _, _))) => break (i, tagname),
Err(err) => {
if i.len() > 0 && &i[0..=1] == "\n" {
return Err(err);
} else {
()
}
}
}
let (j, namepart) = recognize(tuple((take_while1(is_not_space), space1)))(i)?;
name.push_str(namepart);
i = j;
};
let name = String::from(name.trim());
let (i, action) = match tagname {
"connects" => (i, Action::Connect(name)),
"disconnects" => (i, Action::Disconnect(name)),
tagname @ "sends:" | tagname @ "receives:" => parse_send_receive(tagname, name, i)?,
_ => unreachable!(),
};
Ok((i, action))
}
fn parse_disconnect(i: &str) -> IResult<&str, Action> {
let (i, (name, _, _)) = tuple((take_while1(is_not_space), space1, tag("disconnects\n")))(i)?;
Ok((i, Action::Disconnect(String::from(name))))
}
fn parse_action_line(i: &str) -> IResult<&str, &str> {
fn parse_action_subline(i: &str) -> IResult<&str, &str> {
let (i, (_, line, _)) = tuple((many1(tag("\t")), take_until1("\n"), tag("\n")))(i)?;
Ok((i, line))
}
fn parse_send_receive(tagname: &str) -> impl Fn(&str) -> IResult<&str, (String, Element)> + '_ {
move |i: &str| {
let (i, (name, _, _, _, lines)) = tuple((
take_while1(is_not_space),
space1,
tag(tagname),
take_while1(|c| c == ' ' || c == '\r' || c == '\n'), // Spaces but \t
recognize(many1(parse_action_line)),
))(i)?;
let lines = lines.trim();
fn parse_send_receive<'a>(tagname: &str, name: String, i: &'a str) -> IResult<&'a str, Action> {
let (i, (_, lines)) = tuple((
take_while(|c| c == ' ' || c == '\r' || c == '\n'), // Spaces but \t
recognize(many1(parse_action_subline)),
))(i)?;
let lines = lines.trim();
let elem: Element =
Element::from_reader_with_prefixes(&lines.as_bytes()[..], String::from(DEFAULT_NS))
.unwrap();
Ok((i, (String::from(name), elem)))
}
}
fn parse_send(i: &str) -> IResult<&str, Action> {
let (i, (name, elem)) = parse_send_receive("sends:")(i)?;
Ok((i, Action::Send(name, elem)))
}
fn parse_receive(i: &str) -> IResult<&str, Action> {
let (i, (name, elem)) = parse_send_receive("receives:")(i)?;
Ok((i, Action::Receive(name, elem)))
let elem: Element =
Element::from_reader_with_prefixes(&lines.as_bytes()[..], String::from(DEFAULT_NS))
.unwrap();
Ok(match tagname {
"sends:" => (i, Action::Send(name, elem)),
"receives:" => (i, Action::Receive(name, elem)),
_ => unreachable!(),
})
}
fn parse_actions(i: &str) -> IResult<&str, Vec<Action>> {
let (i, actions) = many1(delimited(
allspaces,
alt((parse_connect, parse_disconnect, parse_send, parse_receive)),
allspaces,
))(i)?;
let (i, actions) = many1(delimited(allspaces, parse_action, allspaces))(i)?;
Ok((i, actions))
}
@ -243,8 +260,13 @@ mod tests {
fn test_action_connect() {
let buf1 = "louise connects\n";
let action = Action::Connect(String::from("louise"));
assert_eq!(parse_connect(buf1).unwrap().1, action);
let action1 = Action::Connect(String::from("louise"));
assert_eq!(parse_action(buf1).unwrap().1, action1);
let buf2 = "louise's phone connects\n";
let action2 = Action::Connect(String::from("louise's phone"));
assert_eq!(parse_action(buf2).unwrap().1, action2);
}
#[test]
@ -252,11 +274,11 @@ mod tests {
let buf1 = "louise disconnects\n";
let action = Action::Disconnect(String::from("louise"));
assert_eq!(parse_disconnect(buf1).unwrap().1, action);
assert_eq!(parse_action(buf1).unwrap().1, action);
}
#[test]
fn test_action_send_receive() {
fn test_action_send() {
let buf = r#"rosa sends:
<presence
@ -270,20 +292,25 @@ mod tests {
String::from("rosa"),
Element::from_reader_with_prefixes(&xml[..], String::from(DEFAULT_NS)).unwrap(),
);
assert_eq!(parse_send(buf).unwrap().1, send);
assert_eq!(parse_action(buf).unwrap().1, send);
}
let buf2 = r#"rosa receives:
#[test]
fn test_action_receive() {
let buf = r#"rosa receives:
<presence
type="unavailable"
/>
"#;
let xml = b"<presence\n\t\ttype=\"unavailable\"\t\n/>";
let receive = Action::Receive(
String::from("rosa"),
Element::from_reader_with_prefixes(&xml[..], String::from(DEFAULT_NS)).unwrap(),
);
assert_eq!(parse_receive(buf2).unwrap().1, receive);
assert_eq!(parse_action(buf).unwrap().1, receive);
}
#[test]