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