summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRory Dudley2024-05-17 16:14:42 -0600
committerRory Dudley2024-05-17 16:14:42 -0600
commit40a403c412be52b713a7363840bfa3f507985a9f (patch)
tree7df199c63e2a14516497e1265eaab414f6f537f0
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.
-rw-r--r--src/poem/read.rs7
-rw-r--r--src/poem/read/parse.rs45
2 files changed, 38 insertions, 14 deletions
diff --git a/src/poem/read.rs b/src/poem/read.rs
index afa35e7..35ca2e1 100644
--- a/src/poem/read.rs
+++ b/src/poem/read.rs
@@ -5,7 +5,8 @@ use super::{
use core::fmt;
mod parse;
use crate::compose::Environment;
-use crate::{next, poem, remark, string};
+use crate::{poem, remark, string};
+use parse::next;
#[derive(Debug, PartialEq, Eq)]
pub enum Mishap {
@@ -191,9 +192,9 @@ impl Readable for Poem {
verse.couplet = true;
Rune::Read
}
- '>' => next!(chars, i, Rune::Write, Rune::Addendum, '>'),
+ '>' => next(&mut chars, &mut i, Rune::Write, vec![('>', Rune::Addendum)]),
'|' => Rune::Couplet,
- '&' => next!(chars, i, Rune::Quiet, Rune::And, '&'),
+ '&' => next(&mut chars, &mut i, Rune::Quiet, vec![('&', Rune::And)]),
';' => Rune::Continue,
'\n' => {
j += 1;
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