lexer_rs/lexer/
lexer_of_string.rs1use std::marker::PhantomData;
3
4use crate::{FmtContext, PosnInCharStream};
5use crate::{LexerError, LexerOfStr};
6
7#[derive(Debug)]
34pub struct LexerOfString<P, T, E>
35where
36 P: PosnInCharStream,
37{
38 text: String,
39 line_start_ncolumns: Vec<(P, usize)>,
40 _phantom_token: PhantomData<T>,
41 _phantom_error: PhantomData<E>,
42}
43
44impl<P, T, E> Default for LexerOfString<P, T, E>
46where
47 P: PosnInCharStream,
48{
49 fn default() -> Self {
50 Self {
51 text: String::new(),
52 line_start_ncolumns: Vec::new(),
53 _phantom_token: PhantomData,
54 _phantom_error: PhantomData,
55 }
56 }
57}
58
59impl<P, T, E> LexerOfString<P, T, E>
61where
62 P: PosnInCharStream,
63 T: std::fmt::Debug + Clone,
64 E: LexerError<P>,
65{
66 pub fn set_text<S: Into<String>>(mut self, text: S) -> Self {
69 self.text = text.into();
70 self.find_line_starts();
71 self
72 }
73
74 pub fn take_text(&mut self) -> String {
77 self.line_start_ncolumns.clear();
78 std::mem::take(&mut self.text)
79 }
80
81 pub fn text(&self) -> &str {
84 &self.text
85 }
86
87 pub fn lexer(&self) -> LexerOfStr<P, T, E> {
90 LexerOfStr::new(&self.text)
91 }
92
93 fn find_line_starts(&mut self) {
97 let mut line_start_ncolumns = Vec::new();
98 let mut s: &str = &self.text;
99 let mut pos = P::default();
100 line_start_ncolumns.push((pos, 0)); while let Some((line, next_line)) = s.split_once('\n') {
102 let ncolumns = line.chars().count();
103 line_start_ncolumns.push((pos, ncolumns));
104 pos = pos.advance_line(line.len() + 1);
105 s = next_line;
106 }
107 let ncolumns = s.chars().count();
108 line_start_ncolumns.push((pos, ncolumns));
109 self.line_start_ncolumns = line_start_ncolumns;
110 }
111}
112
113impl<P, T, E> FmtContext<P> for LexerOfString<P, T, E>
116where
117 P: PosnInCharStream,
118 E: LexerError<P>,
119{
120 fn line_length(&self, line: usize) -> usize {
121 self.line_start_ncolumns[line].1
122 }
123
124 fn fmt_line(&self, f: &mut dyn std::fmt::Write, line: usize) -> std::fmt::Result {
125 let s = &self.text[self.line_start_ncolumns[line].0.byte_ofs()..];
126 let s = s.split_once('\n').map(|(s, _)| s).unwrap_or(s);
127 write!(f, "{}", s)
128 }
129}