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
use core::fmt;

use gramatika::{DebugLisp, Span, Spanned, Substr, Token as _};

use crate::{token::Token, utils::join_substrs};

pub struct Text(pub Substr, pub Span);

impl Text {
	pub fn content(&self) -> &str {
		self.0.as_str()
	}

	pub fn append(&mut self, token: Token) {
		self.0 = join_substrs(&self.0, &token.lexeme());
		self.1 = self.1.through(token.span());
	}

	pub fn concat(mut self, token: Token) -> Self {
		self.0 = join_substrs(&self.0, &token.lexeme());
		self.1 = self.1.through(token.span());
		self
	}
}

impl From<Token> for Text {
	fn from(value: Token) -> Self {
		Self(value.lexeme(), value.span())
	}
}

impl Spanned for Text {
	fn span(&self) -> Span {
		self.1
	}
}

impl DebugLisp for Text {
	fn fmt(&self, f: &mut fmt::Formatter, indent: usize) -> fmt::Result {
		let span = self.span();

		if span.end.line > span.start.line && f.alternate() {
			writeln!(f, r#"(Text """"#)?;
			for (idx, line) in self.0.lines().enumerate() {
				writeln!(
					f,
					"{}{:>4} | {line}",
					gramatika::debug::INDENT.repeat(indent),
					span.start.line + idx + 1,
				)?;
			}
			write!(f, r#"{}""")"#, gramatika::debug::INDENT.repeat(indent))?;
		} else if f.alternate() {
			writeln!(f, r#"(Text"#)?;
			writeln!(
				f,
				r#"{}`{}` ({span:?})"#,
				gramatika::debug::INDENT.repeat(indent + 1),
				self.content(),
			)?;
			write!(f, "{})", gramatika::debug::INDENT.repeat(indent))?;
		} else {
			write!(f, r#"(Text `{}` ({span:?}))"#, self.content())?;
		}

		Ok(())
	}
}

impl fmt::Debug for Text {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		DebugLisp::fmt(self, f, 0)
	}
}

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