grass/src/function.rs

69 lines
2.0 KiB
Rust
Raw Normal View History

2020-01-25 13:20:21 -05:00
use std::iter::Peekable;
use std::vec::IntoIter;
use crate::atrule::AtRule;
2020-01-25 13:20:21 -05:00
use crate::common::{Pos, Scope, Symbol};
use crate::args::{eat_func_args, FuncArgs};
use crate::utils::devour_whitespace;
use crate::{Token, TokenKind};
#[derive(Debug, Clone)]
pub(crate) struct Function {
scope: Scope,
args: FuncArgs,
body: Peekable<IntoIter<AtRule>>,
2020-01-25 13:20:21 -05:00
}
impl Function {
pub fn new(scope: Scope, args: FuncArgs, body: Vec<AtRule>) -> Self {
2020-01-25 13:20:21 -05:00
let body = body.into_iter().peekable();
Function { scope, args, body }
}
pub fn decl_from_tokens<I: Iterator<Item = Token>>(
toks: &mut Peekable<I>,
scope: &Scope,
) -> Result<(String, Function), (Pos, String)> {
let Token { pos, kind } = toks
.next()
.expect("this must exist because we have already peeked");
devour_whitespace(toks);
let name = match kind {
TokenKind::Ident(s) => s,
_ => {
return Err((
pos,
String::from("expected identifier after function declaration"),
))
}
};
devour_whitespace(toks);
let args = match toks.next() {
Some(Token {
kind: TokenKind::Symbol(Symbol::OpenParen),
..
}) => eat_func_args(toks),
_ => return Err((pos, String::from("expected `(` after function declaration"))),
};
let mut nesting = 1;
let mut body: Vec<AtRule> = Vec::new();
2020-01-25 13:20:21 -05:00
while nesting > 0 {
if let Some(tok) = toks.next() {
match &tok.kind {
TokenKind::AtRule(rule) => body.push(AtRule::from_tokens(&rule, tok.pos, toks, scope)),
2020-01-25 13:20:21 -05:00
TokenKind::Symbol(Symbol::CloseCurlyBrace) => nesting -= 1,
_ => {}
}
2020-01-25 13:20:21 -05:00
} else {
return Err((pos, String::from("unexpected EOF")));
}
}
Ok((name, Function::new(scope.clone(), args, body)))
}
}