texlang/parse/
relation.rs

1//! Parsing of relations (<, = and >)
2//!
3//! A relation is defined on p209 of the TeXBook to be a character token with
4//! catcode 12 (other) and value <, = or >.
5
6use crate::prelude as txl;
7use crate::traits::*;
8use crate::{token, types, vm};
9
10#[derive(Debug, Clone, PartialEq, Eq)]
11pub struct Ordering(pub std::cmp::Ordering);
12
13impl Default for Ordering {
14    fn default() -> Self {
15        Ordering(std::cmp::Ordering::Equal)
16    }
17}
18
19impl Parsable for Ordering {
20    // TeX.2021.503
21    fn parse_impl<S: TexlangState>(input: &mut vm::ExpandedStream<S>) -> txl::Result<Self> {
22        super::Spaces::parse(input)?;
23        let ordering_or = get_required_element![
24            input,
25            "a relation",
26            format!["a relation is a token with character code {} and one of the following values: <, =, >", types::CatCode::Other],
27            token::Value::Other('<') => Ordering(std::cmp::Ordering::Less),
28            token::Value::Other('=') => Ordering(std::cmp::Ordering::Equal),
29            token::Value::Other('>') => Ordering(std::cmp::Ordering::Greater),
30        ];
31        Ok(ordering_or.unwrap_or_default())
32    }
33}
34
35#[cfg(test)]
36mod tests {
37    use super::*;
38    use crate::parse::testing::*;
39
40    parse_success_tests![
41        (less_than_1, r"<a", Ordering(std::cmp::Ordering::Less)),
42        (less_than_2, r"<a", Ordering(std::cmp::Ordering::Less)),
43        (equals, r"=a", Ordering(std::cmp::Ordering::Equal)),
44        (greater_than, r">a", Ordering(std::cmp::Ordering::Greater)),
45    ];
46
47    #[derive(Default)]
48    struct State;
49
50    impl TexlangState for State {
51        fn cat_code(&self, c: char) -> types::CatCode {
52            if c == '<' {
53                return types::CatCode::Letter;
54            }
55            types::CatCode::PLAIN_TEX_DEFAULTS
56                .get(c as usize)
57                .copied()
58                .unwrap_or_default()
59        }
60    }
61
62    parse_failure_tests![
63        Ordering,
64        State,
65        (empty_input, ""),
66        (letter, "a"),
67        (control_sequence, r"\A"),
68        (incorrect_catcode, "<"),
69    ];
70}