rexlang_lexer/span.rs
1//! The Span module defines source positions, and ranges of source positions,
2//! in which nodes can be defined. It is used to link nodes back to their
3//! origins in the source.
4
5use std::fmt::{self, Display, Formatter};
6
7/// A Position represents an arbitrary source position. It includes the line
8/// number, and column number.
9#[derive(
10 Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, serde::Deserialize, serde::Serialize,
11)]
12#[serde(rename_all = "lowercase")]
13pub struct Position {
14 pub line: usize,
15 pub column: usize,
16}
17
18impl Position {
19 /// Create a new Position.
20 ///
21 /// # Arguments
22 /// * `line` The line number, where the first line of the file is at zero.
23 /// * `column` The column number, where the first column of a line is at
24 /// zero.
25 ///
26 /// # Return
27 /// A new Position.
28 pub fn new(line: usize, column: usize) -> Position {
29 Position { line, column }
30 }
31
32 /// # Return
33 /// The line number of the Position.
34 pub fn line(&self) -> usize {
35 self.line
36 }
37
38 /// # Return
39 /// The column number of the Position.
40 pub fn column(&self) -> usize {
41 self.column
42 }
43}
44
45impl fmt::Display for Position {
46 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
47 write!(formatter, "{}:{}", self.line, self.column)
48 }
49}
50
51/// A Span represents an arbitrary source range. It includes the beginning and
52/// ending Positions.
53#[derive(
54 Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, serde::Deserialize, serde::Serialize,
55)]
56#[serde(rename_all = "lowercase")]
57pub struct Span {
58 pub begin: Position,
59 pub end: Position,
60}
61
62impl Span {
63 /// Create a new Span. The beginning and ending Positions will also be
64 /// created.
65 ///
66 /// # Arguments
67 /// * `begin_line` The line number for the beginning of the Span, where the
68 /// first line of the file is at zero.
69 /// * `begin_column` The column number for the beginning of the Span, where
70 /// the first column of a line is at zero.
71 /// * `end_line` The line number for the ending of the Span, where the first
72 /// line of the file is at zero.
73 /// * `end_column` The column number for the ending of the Span, where the
74 /// first column of a line is at zero.
75 ///
76 /// # Return
77 /// A new Span, with new beginning and ending Positions.
78 pub fn new(begin_line: usize, begin_column: usize, end_line: usize, end_column: usize) -> Self {
79 Self {
80 begin: Position::new(begin_line, begin_column),
81 end: Position::new(end_line, end_column),
82 }
83 }
84
85 /// Create a new Span from beginning and ending positions.
86 ///
87 /// # Arguments
88 /// * `begin` The beginning position.
89 /// * `end` The ending position.
90 ///
91 /// # Return
92 /// A new Span, with the beginning and ending Positions.
93 pub fn from_begin_end<Pos>(begin: Pos, end: Pos) -> Self
94 where
95 Pos: Into<Position>,
96 {
97 Self {
98 begin: begin.into(),
99 end: end.into(),
100 }
101 }
102
103 pub fn merge(self, other: Span) -> Span {
104 Span {
105 begin: self.begin,
106 end: other.end,
107 }
108 }
109}
110
111impl Default for Span {
112 fn default() -> Self {
113 Self {
114 begin: Position::new(usize::MIN, usize::MIN),
115 end: Position::new(usize::MAX, usize::MAX),
116 }
117 }
118}
119
120impl Display for Span {
121 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
122 write!(f, "{} - {}", self.begin, self.end)
123 }
124}
125
126pub trait Spanned {
127 fn set_span_begin(&mut self, begin: Position) {
128 self.span_mut().begin = begin;
129 }
130 fn set_span_end(&mut self, end: Position) {
131 self.span_mut().end = end;
132 }
133 fn span(&self) -> &Span;
134 fn span_mut(&mut self) -> &mut Span;
135}