use super::core::is_blank;
use super::core::Lexer;
use crate::parser::core::Result;
impl Lexer<'_> {
pub async fn skip_if<F>(&mut self, f: F) -> Result<bool>
where
F: FnMut(char) -> bool,
{
Ok(self.consume_char_if(f).await?.is_some())
}
pub async fn skip_blanks(&mut self) -> Result<()> {
while self.skip_if(is_blank).await? {}
Ok(())
}
pub async fn skip_comment(&mut self) -> Result<()> {
if self.skip_if(|c| c == '#').await? {
let mut lexer = self.disable_line_continuation();
while lexer.skip_if(|c| c != '\n').await? {}
Lexer::enable_line_continuation(lexer);
}
Ok(())
}
pub async fn skip_blanks_and_comment(&mut self) -> Result<()> {
self.skip_blanks().await?;
self.skip_comment().await
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::source::Source;
use futures_executor::block_on;
#[test]
fn lexer_skip_blanks() {
let mut lexer = Lexer::from_memory(" \t w", Source::Unknown);
let c = block_on(async {
lexer.skip_blanks().await?;
lexer.peek_char().await
});
assert_eq!(c, Ok(Some('w')));
let c = block_on(async {
lexer.skip_blanks().await?;
lexer.peek_char().await
});
assert_eq!(c, Ok(Some('w')));
}
#[test]
fn lexer_skip_blanks_does_not_skip_newline() {
let mut lexer = Lexer::from_memory("\n", Source::Unknown);
block_on(async {
lexer.skip_blanks().await.unwrap();
assert_eq!(lexer.peek_char().await, Ok(Some('\n')));
});
}
#[test]
fn lexer_skip_blanks_skips_line_continuations() {
let mut lexer = Lexer::from_memory("\\\n \\\n\\\n\\\n \\\nX", Source::Unknown);
let c = block_on(async {
lexer.skip_blanks().await?;
lexer.peek_char().await
});
assert_eq!(c, Ok(Some('X')));
let mut lexer = Lexer::from_memory(" \\\n\\\n \\\n Y", Source::Unknown);
let c = block_on(async {
lexer.skip_blanks().await?;
lexer.peek_char().await
});
assert_eq!(c, Ok(Some('Y')));
}
#[test]
fn lexer_skip_comment_no_comment() {
let mut lexer = Lexer::from_memory("\n", Source::Unknown);
block_on(async {
lexer.skip_comment().await.unwrap();
assert_eq!(lexer.peek_char().await, Ok(Some('\n')));
});
}
#[test]
fn lexer_skip_comment_empty_comment() {
let mut lexer = Lexer::from_memory("#\n", Source::Unknown);
let c = block_on(async {
lexer.skip_comment().await?;
lexer.peek_char().await
});
assert_eq!(c, Ok(Some('\n')));
let c = block_on(async {
lexer.skip_comment().await?;
lexer.peek_char().await
});
assert_eq!(c, Ok(Some('\n')));
}
#[test]
fn lexer_skip_comment_non_empty_comment() {
let mut lexer = Lexer::from_memory("\\\n### foo bar\\\n", Source::Unknown);
let c = block_on(async {
lexer.skip_comment().await?;
lexer.peek_char().await
});
assert_eq!(c, Ok(Some('\n')));
assert_eq!(lexer.index(), 14);
let c = block_on(async {
lexer.skip_comment().await?;
lexer.peek_char().await
});
assert_eq!(c, Ok(Some('\n')));
assert_eq!(lexer.index(), 14);
}
#[test]
fn lexer_skip_comment_not_ending_with_newline() {
let mut lexer = Lexer::from_memory("#comment", Source::Unknown);
let c = block_on(async {
lexer.skip_comment().await?;
lexer.peek_char().await
});
assert_eq!(c, Ok(None));
let c = block_on(async {
lexer.skip_comment().await?;
lexer.peek_char().await
});
assert_eq!(c, Ok(None));
}
}