From 14a8735623c7383c1ba5eb4fad13a5588beffabb Mon Sep 17 00:00:00 2001 From: Sophie Forrest Date: Thu, 12 Sep 2024 02:31:27 +1200 Subject: feat(parser): complete offering parser + courseid Complete courseid and offering parsers. These will be swapped into the codebase in the next commit. --- src/parser.rs | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 101 insertions(+), 4 deletions(-) diff --git a/src/parser.rs b/src/parser.rs index c722bfc..87da6be 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -3,13 +3,16 @@ //! Nom parsers used within the parsing steps. use nom::{ - bytes::complete::{tag, take_while}, - character::complete::multispace0, - combinator::map_res, - sequence::{pair, preceded}, + branch::alt, + bytes::complete::{tag, take, take_till, take_while}, + character::complete::{char, multispace0}, + combinator::{map_res, rest}, + sequence::{delimited, pair, preceded, separated_pair}, IResult, }; +use crate::{CourseOffering, Trimester}; + /// Determines if the provided character is an ascii digit. const fn is_decimal_digit(c: char) -> bool { c.is_ascii_digit() @@ -42,6 +45,62 @@ pub fn course_reference_number(input: &str) -> IResult<&str, u16> { preceded(pair(tag("CRN"), multispace0), crn_digits)(input) } +/// Parser that parses a timetable separator. +/// +/// # Errors +/// +/// This function will return an error if input does not match expected format by nom. +pub fn timetable_separator(input: &str) -> IResult<&str, char> { + delimited(multispace0, char('\u{2022}'), multispace0)(input) +} + +/// Parses a trimester from an input. +/// +/// # Errors +/// +/// This function will return an error if input does not match expected format by nom. +pub fn trimester(input: &str) -> IResult<&str, Trimester> { + map_res( + alt(( + tag("block dates/3"), + tag("part year/3"), + tag("full year"), + take_till(char::is_whitespace), + )), + Trimester::try_from, + )(input) +} + +/// Parses a course offering from an input. +/// +/// # Errors +/// +/// This function will return an error if . +pub fn offering(input: &str) -> IResult<&str, CourseOffering> { + let (input, (trimester, crn)) = + separated_pair(trimester, timetable_separator, course_reference_number)(input)?; + Ok((input, CourseOffering::new(crn, trimester))) +} + +/// Parses a course title from an input. +/// +/// # Errors +/// +/// This function will return an error if nom is unable to parse the input. This should only happen +/// if the input is less than 8 characters. +pub fn title(input: &str) -> IResult<&str, &str> { + take(8usize)(input) +} + +/// Parses a course subtitle from an input. +/// +/// # Errors +/// +/// This function will return an error if the subtitle is not preceded by "`\u{2013}` ". +pub fn subtitle(input: &str) -> IResult<&str, &str> { + preceded(tag("\u{2013} "), rest)(input) +} + #[cfg(test)] #[allow(clippy::unwrap_used)] mod tests { @@ -71,4 +130,42 @@ mod tests { fn crn_parser_no_whitespace() { assert_eq!(course_reference_number("CRN615").unwrap().1, 615); } + + #[test] + fn offering_parser_alphabetic_durations() { + let block_dates = offering("block dates/3 \u{2022} CRN 25341").unwrap(); + + assert_eq!(block_dates.1.course_reference_number, 25341); + assert_eq!(block_dates.1.trimester, Trimester::BlockDates); + + let part_year = offering("part year/3 \u{2022} CRN 1816").unwrap(); + + assert_eq!(part_year.1.course_reference_number, 1816); + assert_eq!(part_year.1.trimester, Trimester::PartYear); + + let full_year = offering("full year \u{2022} CRN 19175").unwrap(); + + assert_eq!(full_year.1.course_reference_number, 19175); + assert_eq!(full_year.1.trimester, Trimester::FullYear); + } + + #[test] + fn title_parser() { + assert_eq!(title("HELT 502 ").unwrap().1, "HELT 502"); + } + + #[test] + fn subtitle_parser() { + let parsed_subtitle = + subtitle("\u{2013} Identification, Assessment and Control of Hazards and Risks") + .unwrap(); + + // The dash and space were parsed, and are not remaining data. + assert_eq!(parsed_subtitle.0, ""); + // The actual subtitle. + assert_eq!( + parsed_subtitle.1, + "Identification, Assessment and Control of Hazards and Risks" + ); + } } -- cgit 1.4.1