rested 0.9.2

Language/Interpreter for easily defining and running requests to an http server.
Documentation
use crate::{error_meta::ContextualError, lexer::locations::GetSpan};

use super::{
    ast::{
        result::ParsedNode, CallExpr, Endpoint, Expression, ExpressionList, Item, Request,
        Statement, StringLiteral, VariableDeclaration,
    },
    error::ParseError,
};

pub trait Visitor<'source>
where
    Self: std::marker::Sized,
{
    fn visit_item(&mut self, item: &Item<'source>) {
        item.visit_children_with(self);
    }

    fn visit_variable_declaration(&mut self, declaration: &VariableDeclaration<'source>) {
        declaration.visit_children_with(self);
    }

    fn visit_request(&mut self, request: &Request<'source>) {
        request.visit_children_with(self);
    }

    fn visit_statement(&mut self, statement: &Statement<'source>) {
        statement.visit_children_with(self);
    }

    fn visit_endpoint(&mut self, endpoint: &Endpoint<'source>) {
        endpoint.visit_children_with(self);
    }

    fn visit_expr(&mut self, expr: &Expression<'source>) {
        expr.visit_children_with(self);
    }

    fn visit_string(&mut self, stringlit: &StringLiteral<'source>) {
        stringlit.visit_children_with(self);
    }

    fn visit_call_expr(&mut self, expr: &CallExpr<'source>) {
        expr.visit_children_with(self);
    }

    fn visit_parsed_node<T: GetSpan>(&mut self, token: &ParsedNode<'source, T>) {
        token.visit_children_with(self);
    }

    fn visit_error(&mut self, err: &ContextualError<ParseError<'source>>) {
        err.visit_children_with(self);
    }
}

pub trait VisitWith<'source> {
    fn visit_with<V: Visitor<'source>>(&self, visitor: &mut V);
    fn visit_children_with<V: Visitor<'source>>(&self, visitor: &mut V);
}

impl<'source> VisitWith<'source> for Item<'source> {
    fn visit_with<V: Visitor<'source>>(&self, visitor: &mut V) {
        visitor.visit_item(self);
    }

    fn visit_children_with<V: Visitor<'source>>(&self, visitor: &mut V) {
        match self {
            Item::Set { identifier, value } => {
                visitor.visit_parsed_node(identifier);
                visitor.visit_expr(value);
            }
            Item::Let(d) => {
                visitor.visit_variable_declaration(d);
            }
            Item::Request(req) => {
                visitor.visit_request(req);
            }
            Item::Expr(expr) => visitor.visit_expr(expr),
            Item::Attribute {
                arguments: Some(arguments),
                identifier,
                ..
            } => {
                visitor.visit_parsed_node(identifier);
                for arg in arguments.exprs.iter() {
                    visitor.visit_expr(arg);
                }
            }
            Item::Error(e) => visitor.visit_error(e),
            _ => {}
        }
    }
}

impl<'source> VisitWith<'source> for VariableDeclaration<'source> {
    fn visit_with<V: Visitor<'source>>(&self, visitor: &mut V) {
        visitor.visit_variable_declaration(self);
    }

    fn visit_children_with<V: Visitor<'source>>(&self, visitor: &mut V) {
        let VariableDeclaration { identifier, value } = self;

        visitor.visit_parsed_node(identifier);
        visitor.visit_expr(value)
    }
}

impl<'source> VisitWith<'source> for Request<'source> {
    fn visit_with<V: Visitor<'source>>(&self, visitor: &mut V) {
        visitor.visit_request(self);
    }

    fn visit_children_with<V: Visitor<'source>>(&self, visitor: &mut V) {
        match self {
            Request {
                endpoint,
                block: Some(block),
                ..
            } => {
                visitor.visit_endpoint(endpoint);
                for statement in block.statements.iter() {
                    visitor.visit_statement(statement)
                }
            }
            Request { endpoint, .. } => visitor.visit_endpoint(endpoint),
        }
    }
}

impl<'source> VisitWith<'source> for Statement<'source> {
    fn visit_with<V: Visitor<'source>>(&self, visitor: &mut V) {
        visitor.visit_statement(self)
    }

    fn visit_children_with<V: Visitor<'source>>(&self, visitor: &mut V) {
        match self {
            Statement::Header { name, value } => {
                visitor.visit_parsed_node(name);
                visitor.visit_expr(value);
            }
            Statement::Body { value, .. } => visitor.visit_expr(value),
            Statement::Error(e) => visitor.visit_error(e),
            Statement::LineComment(_) => {}
        }
    }
}

impl<'source> VisitWith<'source> for Endpoint<'source> {
    fn visit_with<V: Visitor<'source>>(&self, visitor: &mut V) {
        visitor.visit_endpoint(self)
    }

    fn visit_children_with<V: Visitor<'source>>(&self, visitor: &mut V) {
        if let Endpoint::Expr(e) = self {
            visitor.visit_expr(e)
        }
    }
}

impl<'source> VisitWith<'source> for Expression<'source> {
    fn visit_with<V: Visitor<'source>>(&self, visitor: &mut V) {
        visitor.visit_expr(self)
    }

    fn visit_children_with<V: Visitor<'source>>(&self, visitor: &mut V) {
        match self {
            Expression::Call(expr) => visitor.visit_call_expr(expr),
            Expression::Array(ExpressionList { exprs, .. }) => {
                for expr in exprs.iter() {
                    visitor.visit_expr(expr)
                }
            }
            Expression::Object((_, entries)) => {
                for entry in entries.iter() {
                    match entry {
                        ParsedNode::Ok(entry) => {
                            visitor.visit_parsed_node(&entry.key);
                            visitor.visit_expr(&entry.value)
                        }
                        ParsedNode::Error(e) => visitor.visit_error(e),
                    }
                }
            }
            Expression::TemplateSringLiteral { parts, .. } => {
                for expr in parts.iter() {
                    visitor.visit_expr(expr)
                }
            }
            Expression::Error(e) => visitor.visit_error(e),
            Expression::Identifier(ident) => visitor.visit_parsed_node(ident),
            Expression::String(s) => visitor.visit_string(s),
            _ => {}
        };
    }
}

impl<'source> VisitWith<'source> for StringLiteral<'source> {
    fn visit_with<V: Visitor<'source>>(&self, visitor: &mut V) {
        visitor.visit_string(self)
    }

    fn visit_children_with<V: Visitor<'source>>(&self, _visitor: &mut V) {}
}

impl<'source> VisitWith<'source> for CallExpr<'source> {
    fn visit_with<V: Visitor<'source>>(&self, visitor: &mut V) {
        visitor.visit_call_expr(self)
    }

    fn visit_children_with<V: Visitor<'source>>(&self, visitor: &mut V) {
        visitor.visit_parsed_node(&self.identifier);
        for arg in self.arguments.exprs.iter() {
            visitor.visit_expr(arg)
        }
    }
}

impl<'source> VisitWith<'source> for ContextualError<ParseError<'source>> {
    fn visit_with<V: Visitor<'source>>(&self, visitor: &mut V) {
        visitor.visit_error(self)
    }

    fn visit_children_with<V: Visitor<'source>>(&self, _visitor: &mut V) {}
}

impl<'source, T: GetSpan> VisitWith<'source> for ParsedNode<'source, T> {
    fn visit_with<V: Visitor<'source>>(&self, visitor: &mut V) {
        visitor.visit_parsed_node(self)
    }

    fn visit_children_with<V: Visitor<'source>>(&self, visitor: &mut V) {
        if let ParsedNode::Error(e) = self {
            visitor.visit_error(e)
        }
    }
}