2020-01-14 19:34:13 -05:00
|
|
|
use crate::common::{Pos, Symbol, Whitespace};
|
2020-01-12 20:56:07 -05:00
|
|
|
use crate::{Scope, Token, TokenKind};
|
2020-01-14 17:39:19 -05:00
|
|
|
use std::iter::{Iterator, Peekable};
|
2020-01-12 20:15:27 -05:00
|
|
|
|
2020-01-20 13:15:47 -05:00
|
|
|
pub(crate) trait IsWhitespace {
|
2020-01-12 20:15:27 -05:00
|
|
|
fn is_whitespace(&self) -> bool;
|
|
|
|
}
|
|
|
|
|
2020-01-20 16:00:37 -05:00
|
|
|
pub(crate) fn devour_whitespace<I: Iterator<Item = W>, W: IsWhitespace>(
|
|
|
|
s: &mut Peekable<I>,
|
|
|
|
) -> bool {
|
2020-01-12 20:15:27 -05:00
|
|
|
let mut found_whitespace = false;
|
|
|
|
while let Some(w) = s.peek() {
|
|
|
|
if !w.is_whitespace() {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
found_whitespace = true;
|
|
|
|
s.next();
|
|
|
|
}
|
|
|
|
found_whitespace
|
|
|
|
}
|
2020-01-12 20:56:07 -05:00
|
|
|
|
2020-01-20 13:39:20 -05:00
|
|
|
#[cfg_attr(feature = "nightly", track_caller)]
|
2020-01-20 13:15:47 -05:00
|
|
|
pub(crate) fn deref_variable(name: &str, scope: &Scope) -> Vec<Token> {
|
2020-01-12 20:56:07 -05:00
|
|
|
let mut toks = scope
|
|
|
|
.vars
|
|
|
|
.get(name)
|
|
|
|
.expect("todo! expected variable to exist")
|
|
|
|
.iter()
|
|
|
|
.peekable();
|
|
|
|
let mut val = Vec::with_capacity(toks.len());
|
|
|
|
while let Some(tok) = toks.next() {
|
2020-01-18 20:24:28 -05:00
|
|
|
match tok.kind {
|
2020-01-12 20:56:07 -05:00
|
|
|
TokenKind::Variable(ref v) => val.extend(deref_variable(v, scope)),
|
|
|
|
TokenKind::Whitespace(_) => {
|
|
|
|
devour_whitespace(&mut toks);
|
|
|
|
if toks.peek().is_some() {
|
|
|
|
val.push(Token {
|
|
|
|
kind: TokenKind::Whitespace(Whitespace::Space),
|
|
|
|
pos: tok.pos,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => val.push(tok.clone()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
val
|
|
|
|
}
|
2020-01-14 17:39:19 -05:00
|
|
|
|
2020-01-20 13:15:47 -05:00
|
|
|
pub(crate) fn eat_interpolation<I: Iterator<Item = Token>>(
|
2020-01-20 17:01:25 -05:00
|
|
|
tokens: &mut I,
|
2020-01-14 17:39:19 -05:00
|
|
|
scope: &Scope,
|
|
|
|
) -> Vec<Token> {
|
|
|
|
let mut val = Vec::new();
|
2020-01-20 17:01:25 -05:00
|
|
|
while let Some(tok) = tokens.next() {
|
2020-01-18 20:24:28 -05:00
|
|
|
match tok.kind {
|
2020-01-14 17:39:19 -05:00
|
|
|
TokenKind::Symbol(Symbol::CloseCurlyBrace) => break,
|
|
|
|
TokenKind::Symbol(Symbol::OpenCurlyBrace) => {
|
|
|
|
todo!("invalid character in interpolation")
|
|
|
|
}
|
|
|
|
TokenKind::Variable(ref v) => val.extend(deref_variable(v, scope)),
|
2020-01-20 17:01:25 -05:00
|
|
|
TokenKind::Interpolation => val.extend(eat_interpolation(tokens, scope)),
|
2020-01-18 20:24:28 -05:00
|
|
|
_ => val.push(tok),
|
2020-01-14 17:39:19 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
val
|
|
|
|
}
|
2020-01-14 19:34:13 -05:00
|
|
|
|
2020-01-20 13:15:47 -05:00
|
|
|
pub(crate) fn eat_variable_value<I: Iterator<Item = Token>>(
|
2020-01-14 19:34:13 -05:00
|
|
|
toks: &mut Peekable<I>,
|
|
|
|
scope: &Scope,
|
2020-01-19 00:10:37 -05:00
|
|
|
) -> Result<Vec<Token>, (Pos, String)> {
|
2020-01-14 19:34:13 -05:00
|
|
|
devour_whitespace(toks);
|
2020-01-18 09:42:25 -05:00
|
|
|
// todo!(line might not end with semicolon)
|
2020-01-14 19:34:13 -05:00
|
|
|
let iter1 = toks.take_while(|x| x.kind != TokenKind::Symbol(Symbol::SemiColon));
|
|
|
|
let mut iter2 = Vec::new();
|
|
|
|
for tok in iter1 {
|
|
|
|
match tok.kind {
|
|
|
|
TokenKind::Variable(ref name) => iter2.extend(deref_variable(name, scope)),
|
|
|
|
_ => iter2.push(tok),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
devour_whitespace(toks);
|
|
|
|
Ok(iter2)
|
|
|
|
}
|