wdl_format/token.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
//! Tokens used during formatting.
mod post;
mod pre;
use std::fmt::Display;
pub use post::*;
pub use pre::*;
use crate::Config;
/// Tokens that are streamable.
pub trait Token: Eq + PartialEq {
/// Returns a displayable version of the token.
fn display<'a>(&'a self, config: &'a Config) -> impl Display + 'a;
}
/// A stream of tokens. Tokens in this case are either [`PreToken`]s or
/// [`PostToken`]s. Note that, unless you are working on formatting
/// specifically, you should never need to work with [`PostToken`]s.
#[derive(Debug)]
pub struct TokenStream<T: Token>(Vec<T>);
impl<T: Token> Default for TokenStream<T> {
fn default() -> Self {
Self(Default::default())
}
}
impl<T: Token> TokenStream<T> {
/// Pushes a token into the stream.
pub fn push(&mut self, token: T) {
self.0.push(token);
}
/// Removes any number of `token`s at the end of the stream.
pub fn trim_end(&mut self, token: &T) {
while Some(token) == self.0.last() {
let _ = self.0.pop();
}
}
/// Removes any number of `token`s at the end of the stream.
pub fn trim_while<F: Fn(&T) -> bool>(&mut self, predicate: F) {
while let Some(token) = self.0.last() {
if !predicate(token) {
break;
}
let _ = self.0.pop();
}
}
}
impl<T: Token> IntoIterator for TokenStream<T> {
type IntoIter = std::vec::IntoIter<Self::Item>;
type Item = T;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
/// The kind of comment.
#[derive(Debug, Eq, PartialEq)]
pub enum Comment {
/// A comment on its own line.
Preceding(String),
/// A comment on the same line as the code preceding it.
Inline(String),
}
/// Trivia.
#[derive(Debug, Eq, PartialEq)]
pub enum Trivia {
/// A blank line. This may be ignored by the postprocessor.
BlankLine,
/// A comment.
Comment(Comment),
}
/// Whether optional blank lines are allowed in the current context.
#[derive(Eq, PartialEq, Default, Debug, Clone, Copy)]
pub enum LineSpacingPolicy {
/// Blank lines are allowed before comments.
BeforeComments,
/// Blank lines are always allowed.
#[default]
Always,
}