summaryrefslogtreecommitdiffstats
path: root/src/poem/read
diff options
context:
space:
mode:
authorRory Dudley2024-05-17 16:14:42 -0600
committerRory Dudley2024-05-17 16:14:42 -0600
commit40a403c412be52b713a7363840bfa3f507985a9f (patch)
tree7df199c63e2a14516497e1265eaab414f6f537f0 /src/poem/read
parentabc835cd020a66b40d0f39e7c950644b436c3a86 (diff)
downloaddwarvish-40a403c412be52b713a7363840bfa3f507985a9f.tar.gz
Rewrite of the next! macro
This patch replaces the next! macro with a next() function. It serves the same purpose, but instead of only checking for two different runes (a fallback, or one that matches the peek), it can now take a list of runes/characters to look ahead for, in addition to the fallback.
Diffstat (limited to 'src/poem/read')
-rw-r--r--src/poem/read/parse.rs45
1 files changed, 34 insertions, 11 deletions
diff --git a/src/poem/read/parse.rs b/src/poem/read/parse.rs
index 7b01d85..0dbdf0f 100644
--- a/src/poem/read/parse.rs
+++ b/src/poem/read/parse.rs
@@ -1,20 +1,43 @@
+use crate::poem::elements::rune::Rune;
+use std::str::Chars;
+
/// Look ahead one character in the input
///
/// May need to look ahead one character in the input string to determine the
/// proper rune. For instance `&`, vs `&&`.
-#[macro_export]
-macro_rules! next {
- ($chars:expr, $i:expr, $otherwise:expr, $rune:expr, $ahead:expr) => {
- match $chars.clone().peekable().peek() {
- Some(c) if *c == $ahead => {
- $chars.next();
- $i += 1;
- $rune
- }
- Some(_) => $otherwise,
- None => $otherwise,
+///
+/// # Arguments:
+/// `chars` - An iterator over the characters in the poem
+/// `i` - A counter to keep track of the current column
+/// `otherwise` - The rune to return if there are no matches
+/// `ahead` - A list of tuples, containing characters to look ahead for,
+/// alongside which rune they correspond to
+///
+/// # Examples:
+/// ```
+/// next(&mut chars, &mut i, Rune::Write, vec![('>', Rune::Addendum)])
+/// next(&mut chars, &mut i, Rune::Quiet, vec![('&', Rune::And)])
+/// ```
+pub fn next(chars: &mut Chars, i: &mut usize, otherwise: Rune, ahead: Vec<(char, Rune)>) -> Rune {
+ // Try to get the next character in the poem
+ let next = match chars.peekable().peek() {
+ Some(c) => *c,
+ None => {
+ return otherwise;
}
};
+
+ // Check if that next character matches any characters in ahead
+ for (c, rune) in ahead.iter() {
+ if next == *c {
+ chars.into_iter().next();
+ *i += 1;
+ return *rune;
+ }
+ }
+
+ // If it doesn't match, return the default
+ otherwise
}
/// Keep pushing to the [Word][super::super::elements::word::Word] stack