summaryrefslogtreecommitdiff
path: root/src/chomp/check/spanning.rs
blob: 59c3811a20354edd6e84e46cdf766f70292449f4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
use proc_macro2::Span;

use super::super::{
    ast::{Alt, Call, Cat, Epsilon, Fix, Literal, Parameter, Variable},
    visit::{Visitable, Visitor},
};

#[derive(Clone, Copy, Debug)]
pub struct Spanning;

impl Visitor for Spanning {
    type Out = Option<Span>;

    fn visit_epsilon(&mut self, eps: &Epsilon) -> Self::Out {
        eps.map(|e| e.span)
    }

    fn visit_literal(&mut self, lit: &Literal) -> Self::Out {
        lit.span()
    }

    fn visit_cat(&mut self, cat: &Cat) -> Self::Out {
        let fst = cat.first().visit(self);
        let snd = cat.second().visit(self);

        match (fst, snd) {
            (None, snd) => snd,
            (Some(fst), None) => Some(fst),
            (Some(fst), Some(snd)) => fst.join(snd),
        }
    }

    fn visit_alt(&mut self, alt: &Alt) -> Self::Out {
        let left = alt.left().visit(self);
        let right = alt.right().visit(self);

        match (left, right) {
            (None, right) => right,
            (Some(left), None) => Some(left),
            (Some(left), Some(right)) => left.join(right),
        }
    }

    fn visit_fix(&mut self, fix: &Fix) -> Self::Out {
        fix.span()
    }

    fn visit_variable(&mut self, var: &Variable) -> Self::Out {
        var.name().span()
    }

    fn visit_parameter(&mut self, param: &Parameter) -> Self::Out {
        param.name().span()
    }

    fn visit_call(&mut self, call: &Call) -> Self::Out {
        call.span()
    }
}