use crate::clojure::lex::Lexeme;
use super::{
printer::{BuildInput, Command},
style::Style,
};
use Lexeme as L;
use Style as S;
pub fn generate_printer_input<'a, I>(
lexemes: I,
printer_input: &mut Vec<Command<'a>>,
) where
I: Iterator<Item = &'a Lexeme<'a>>,
{
let mut last_var_quote: Option<u32> = None;
for l in lexemes {
match *l {
L::Whitespace { source } => {
printer_input.add_styled(S::Whitespace, source)
}
L::Nil { source, .. } => printer_input.add_styled(S::NilValue, source),
L::Boolean { source, .. } => {
printer_input.add_styled(S::BooleanValue, source)
}
L::Numeric { source, .. } => {
printer_input.add_styled(S::NumberValue, source)
}
L::String { source, .. } => {
printer_input.add_styled(S::StringDecoration, "\"");
printer_input.add_styled(S::StringValue, &source[1..source.len() - 1]);
printer_input.add_styled(S::StringDecoration, "\"");
}
L::SymbolicValuePrefix { source, .. } => {
printer_input.add_styled(S::SymbolicValueDecoration, source)
}
L::SymbolicValue { source, .. } => {
printer_input.add_styled(S::SymbolicValue, source)
}
L::Symbol {
form_ix,
namespace,
name,
..
} => {
let is_var_quoted = last_var_quote
.map(|ix| ix == form_ix.parent)
.unwrap_or(false);
if is_var_quoted {
if let Some(s) = namespace {
printer_input.add_styled(S::VarQuoteNamespace, s);
printer_input.add_styled(S::VarQuoteDecoration, "/");
}
printer_input.add_styled(S::VarQuoteName, name);
} else {
if let Some(s) = namespace {
printer_input.add_styled(S::SymbolNamespace, s);
printer_input.add_styled(S::SymbolDecoration, "/");
}
printer_input.add_styled(S::SymbolName, name);
}
}
L::Keyword {
alias,
namespace,
name,
..
} => {
printer_input
.add_styled(S::KeywordDecoration, if alias { "::" } else { ":" });
if let Some(s) = namespace {
printer_input.add_styled(S::KeywordNamespace, s);
printer_input.add_styled(S::KeywordDecoration, "/");
}
printer_input.add_styled(S::KeywordName, name);
}
L::VarQuote { form_ix, source } => {
printer_input.add_styled(S::VarQuoteDecoration, source);
last_var_quote = Some(form_ix.ix);
}
L::TaggedLiteral { source, .. } => {
printer_input.add_styled(S::TaggedLiteralDecoration, source);
}
L::Tag {
namespace, name, ..
} => {
if let Some(s) = namespace {
printer_input.add_styled(S::TaggedLiteralNamespace, s);
printer_input.add_styled(S::TaggedLiteralDecoration, "/");
}
printer_input.add_styled(S::TaggedLiteralName, name);
}
L::StartList { source, .. }
| L::EndList { source, .. }
| L::StartVector { source, .. }
| L::EndVector { source, .. }
| L::StartSet { source, .. }
| L::EndSet { source, .. }
| L::StartMap { source, .. }
| L::EndMap { source, .. } => {
printer_input.add_styled(S::CollectionDelimiter, source)
}
ref unhandled => todo!("no rule for: {:?}", unhandled),
}
}
}