use std::collections::HashMap;
use std::fmt;
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct WS {
pub left: bool,
pub right: bool,
}
impl Default for WS {
fn default() -> Self {
WS { left: false, right: false }
}
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum MathOperator {
Add,
Sub,
Mul,
Div,
Modulo,
}
impl fmt::Display for MathOperator {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{}",
match *self {
MathOperator::Add => "+",
MathOperator::Sub => "-",
MathOperator::Mul => "*",
MathOperator::Div => "/",
MathOperator::Modulo => "%",
}
)
}
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum LogicOperator {
Gt,
Gte,
Lt,
Lte,
Eq,
NotEq,
And,
Or,
}
impl fmt::Display for LogicOperator {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{}",
match *self {
LogicOperator::Gt => ">",
LogicOperator::Gte => ">=",
LogicOperator::Lt => "<",
LogicOperator::Lte => "<=",
LogicOperator::Eq => "==",
LogicOperator::NotEq => "!=",
LogicOperator::And => "and",
LogicOperator::Or => "or",
}
)
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct FunctionCall {
pub name: String,
pub args: HashMap<String, Expr>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct MathExpr {
pub lhs: Box<Expr>,
pub rhs: Box<Expr>,
pub operator: MathOperator,
}
#[derive(Clone, Debug, PartialEq)]
pub struct LogicExpr {
pub lhs: Box<Expr>,
pub rhs: Box<Expr>,
pub operator: LogicOperator,
}
#[derive(Clone, Debug, PartialEq)]
pub struct StringConcat {
pub values: Vec<ExprVal>,
}
#[derive(Clone, Debug, PartialEq)]
#[allow(missing_docs)]
pub enum ExprVal {
String(String),
Int(i64),
Float(f64),
Bool(bool),
Ident(String),
Math(MathExpr),
Logic(LogicExpr),
Test(Test),
MacroCall(MacroCall),
FunctionCall(FunctionCall),
Array(Vec<Expr>),
StringConcat(StringConcat),
}
#[derive(Clone, Debug, PartialEq)]
pub struct Expr {
pub val: ExprVal,
pub negated: bool,
pub filters: Vec<FunctionCall>,
}
impl Expr {
pub fn new(val: ExprVal) -> Expr {
Expr { val, negated: false, filters: vec![] }
}
pub fn new_negated(val: ExprVal) -> Expr {
Expr { val, negated: true, filters: vec![] }
}
pub fn with_filters(val: ExprVal, filters: Vec<FunctionCall>) -> Expr {
Expr { val, filters, negated: false }
}
pub fn has_default_filter(&self) -> bool {
if self.filters.is_empty() {
return false;
}
self.filters[0].name == "default"
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Test {
pub ident: String,
pub negated: bool,
pub name: String,
pub args: Vec<Expr>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct FilterSection {
pub filter: FunctionCall,
pub body: Vec<Node>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Set {
pub key: String,
pub value: Expr,
pub global: bool,
}
#[derive(Clone, Debug, PartialEq)]
pub struct MacroCall {
pub namespace: String,
pub name: String,
pub args: HashMap<String, Expr>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct MacroDefinition {
pub name: String,
pub args: HashMap<String, Option<Expr>>,
pub body: Vec<Node>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Block {
pub name: String,
pub body: Vec<Node>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Forloop {
pub key: Option<String>,
pub value: String,
pub container: Expr,
pub body: Vec<Node>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct If {
pub conditions: Vec<(WS, Expr, Vec<Node>)>,
pub otherwise: Option<(WS, Vec<Node>)>,
}
#[derive(Clone, Debug, PartialEq)]
pub enum Node {
Super,
Text(String),
VariableBlock(Expr),
MacroDefinition(WS, MacroDefinition, WS),
Extends(WS, String),
Include(WS, String),
ImportMacro(WS, String, String),
Set(WS, Set),
Raw(WS, String, WS),
FilterSection(WS, FilterSection, WS),
Block(WS, Block, WS),
Forloop(WS, Forloop, WS),
If(If, WS),
Break(WS),
Continue(WS),
}