summaryrefslogtreecommitdiff
path: root/src/syntax/span.rs
blob: df9a3520e90b92ce126851180bea2f40e8cac1ce (plain) (blame)
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
//! Spans map elements to the part of source code they originate from.

use std::fmt::{self, Debug, Display, Formatter};
use serde::Serialize;


/// Annotates a value with the part of the source code it corresponds to.
#[derive(Copy, Clone, Eq, PartialEq, Hash, Serialize)]
pub struct Spanned<T> {
    pub v: T,
    pub span: Span,
}

impl<T> Spanned<T> {
    pub fn new(v: T, span: Span) -> Spanned<T> {
        Spanned { v, span }
    }

    pub fn value(self) -> T {
        self.v
    }

    pub fn map<F, V>(self, f: F) -> Spanned<V> where F: FnOnce(T) -> V {
        Spanned { v: f(self.v), span: self.span }
    }

    pub fn map_v<V>(&self, new_v: V) -> Spanned<V> {
        Spanned { v: new_v, span: self.span }
    }
}

impl<T> Display for Spanned<T> where T: std::fmt::Display {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "({}, {}, ", self.span.start, self.span.end)?;
        self.v.fmt(f)?;
        write!(f, ")")
    }
}

impl<T> Debug for Spanned<T> where T: std::fmt::Debug {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "({}, {}, ", self.span.start, self.span.end)?;
        self.v.fmt(f)?;
        write!(f, ")")
    }
}

/// Describes a slice of source code.
#[derive(Copy, Clone, Eq, PartialEq, Hash, Serialize)]
pub struct Span {
    pub start: Position,
    pub end: Position,
}

impl Span {
    pub const ZERO: Span = Span { start: Position::ZERO, end: Position::ZERO };

    pub fn new(start: Position, end: Position) -> Span {
        Span { start, end }
    }

    pub fn merge(a: Span, b: Span) -> Span {
        Span {
            start: a.start.min(b.start),
            end: a.end.max(b.end),
        }
    }

    pub fn at(pos: Position) -> Span {
        Span { start: pos, end: pos }
    }

    pub fn expand(&mut self, other: Span) {
        *self = Span::merge(*self, other)
    }
}

impl Display for Span {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "({}, {})", self.start, self.end)
    }
}

debug_display!(Span);

/// A line-column position in source code.
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize)]
pub struct Position {
    /// The 0-indexed line (inclusive).
    pub line: usize,
    /// The 0-indexed column (inclusive).
    pub column: usize,
}

impl Position {
    pub const ZERO: Position = Position { line: 0, column: 0 };

    pub fn new(line: usize, column: usize) -> Position {
        Position { line, column }
    }
}

impl Display for Position {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{}:{}", self.line, self.column)
    }
}

debug_display!(Position);