use std::iter::Peekable;
use std::collections::HashMap;
use tokens::{ TokenRef, TokenValueRef, TokenValue, TokenIter };
use environment::ParsingEnvironment;
use error::{ TemplateResult, TemplateError, Received };
use operator::{ OperatorOptions, OperatorKind };
use uuid::Uuid;
pub mod body;
pub mod module;
pub mod expr;
#[derive(Copy, Clone)]
pub struct ImportedFunction<'c> {
pub uuid: Uuid,
pub name: &'c str,
pub alias: &'c str,
}
impl<'c> ImportedFunction<'c> {
pub fn new<'r>(uuid: Uuid, alias: &'r str, name: &'r str) -> ImportedFunction<'r> {
ImportedFunction {
uuid: uuid, name: name, alias: alias
}
}
}
pub struct ImportedSymbols<'c> {
pub functions: HashMap<&'c str, ImportedFunction<'c>>
}
impl<'c> ImportedSymbols<'c> {
pub fn new<'r>() -> ImportedSymbols<'r> {
ImportedSymbols {
functions: HashMap::new()
}
}
}
pub trait Parse<'c> {
type Output;
fn parse<'p>(parser: &mut Parser<'p, 'c>)
-> TemplateResult<Self::Output>;
}
pub struct Parser<'p, 'c: 'p>
{
pub env: &'p ParsingEnvironment,
pub tokens: Peekable<&'p mut TokenIter<'p, 'c>>,
pub imported_symbols: Vec<ImportedSymbols<'c>>,
}
impl<'p, 'c: 'p> Parser<'p, 'c>
{
pub fn new<'r, 'z>(
env: &'r ParsingEnvironment,
tokens: &'r mut TokenIter<'r, 'z>
) -> Parser<'r, 'z>
{
Parser {
env: env,
tokens: tokens.peekable(),
imported_symbols: vec![ImportedSymbols::new()],
}
}
pub fn push_local_scope<'r>(&'r mut self) {
self.imported_symbols.push(ImportedSymbols::new());
}
pub fn pop_local_scope<'r>(&'r mut self) {
self.imported_symbols.pop();
}
pub fn add_imported_function<'r>(&'r mut self, alias: &'c str, name: &'c str) -> Uuid {
let uuid = Uuid::new_v4();
self.imported_symbols
.last_mut().unwrap()
.functions
.insert(alias, ImportedFunction::new(uuid.clone(), alias, name));
uuid
}
pub fn get_imported_function<'r>(&'r self, name: &str) -> Option<ImportedFunction<'c>> {
for symbols in &self.imported_symbols {
if let Some(found) = symbols.functions.get(name) {
return Some(*found);
}
}
None
}
pub fn current<'r>(&'r mut self) -> TemplateResult<TokenRef<'c>>
{
Ok(match self.tokens.peek() {
Some(&Ok(ref t)) => t.clone(),
None => return Err(TemplateError::UnexpectedEndOfTemplate.at(1)),
Some(&Err(ref e)) => return Err(e.clone()),
})
}
pub fn maybe_current<'r>(&'r mut self) -> TemplateResult<Option<TokenRef<'c>>>
{
Ok(match self.tokens.peek() {
Some(&Ok(ref t)) => Some(t.clone()),
None => None,
Some(&Err(ref e)) => return Err(e.clone()),
})
}
pub fn next<'r>(&'r mut self) -> TemplateResult<TokenRef<'c>>
{
let token = match self.tokens.peek() {
Some(&Ok(ref t)) => t.clone(),
None => return Err(TemplateError::UnexpectedEndOfTemplate.at(1)),
Some(&Err(ref e)) => return Err(e.clone()),
};
match self.tokens.next() {
None => return Err(TemplateError::UnexpectedEndOfTemplate.at(token.line)),
Some(Err(e)) => return Err(e),
_ => (),
};
Ok(token)
}
pub fn skip_to_next_if<'r>(&'r mut self, expected: TokenValueRef<'c>) -> TemplateResult<bool>
{
let (line, skip) = {
let token = match self.tokens.peek() {
Some(&Ok(ref token)) => token,
_ => return Err(TemplateError::UnexpectedEndOfTemplate.at(1)),
};
(token.line, token.value == expected)
};
if skip {
match self.tokens.next() {
Some(Ok(_)) => Ok(true),
None => return Err(TemplateError::UnexpectedEndOfTemplate.at(line)),
Some(Err(e)) => return Err(e),
}
} else {
Ok(false)
}
}
pub fn expect<'r>(&'r mut self, expected: TokenValueRef<'c>) -> TemplateResult<TokenRef<'c>>
{
self.expect_match_or(
|token| if token.value == expected {
Ok(token.clone())
} else {
Err(
TemplateError::ExpectedOtherTokenValue((token.value.into(), expected.into()))
.at(token.line)
)
}
)
}
pub fn expect_name<'r>(&'r mut self) -> TemplateResult<&'c str>
{
self.expect_match_or(
|token| match token.value {
TokenValueRef::Name(name) => Ok(name),
_ => Err(
TemplateError::ExpectedTokenTypeButReceived(
(TokenValue::Name("".into()), Received::Token(token.value.into()))
).at(token.line)
)
}
)
}
pub fn expect_or_error<'r>(&'r mut self, expected: TokenValueRef<'c>, error_message: TemplateError) -> TemplateResult<TokenRef<'c>>
{
self.expect_match_or(
|token| if token.value == expected {
Ok(token.clone())
} else {
Err(error_message.at(token.line))
}
)
}
pub fn expect_match_or<'r, C, T>(&'r mut self, check: C) -> TemplateResult<T>
where
C: for<'a> FnOnce(&'a TokenRef<'c>) -> TemplateResult<T>
{
let res = match self.tokens.peek() {
Some(&Ok(ref t)) => {
check(&t)
},
None => return Err(TemplateError::UnexpectedEndOfTemplate.at(1)),
Some(&Err(ref e)) => return Err(e.clone()),
};
try!(self.next());
res
}
pub fn test<'r>(&'r mut self, expected: TokenValueRef<'c>) -> TemplateResult<bool>
{
match self.tokens.peek() {
Some(&Ok(ref t)) => {
if t.value == expected {
Ok(true)
} else {
Ok(false)
}
},
None => Err(TemplateError::UnexpectedEndOfTemplate.at(1)),
Some(&Err(ref e)) => Err(e.clone()),
}
}
pub fn get_operator_options<'r>(&'r self, op_str: &'c str) -> OperatorOptions {
self.env.operators
.get(op_str)
.cloned()
.unwrap_or(OperatorOptions { precedence: None, kind: OperatorKind::Other })
}
}