rustla/parser/
table_parsers.rs1use crate::parser::line_cursor::LineCursor;
9use crate::parser::Parser;
10use crate::parser::types_and_aliases::TextBlockResult;
11
12#[derive(Debug)]
13pub enum TableResult {
20 CompleteTable {
21 col_widths: Vec<u32>,
22 head_rows: Vec<Row>,
23 body_rows: Vec<Row>,
24 },
25 MalformedTableError(String),
26}
27
28impl TableResult {}
29
30#[derive(Debug)]
31pub struct Cell {
32 vspan: u32,
33 hspan: u32,
34 content_offset: u32,
35 text_lines: Vec<String>,
36}
37
38impl Cell {
39 pub fn new(vspan: u32, hspan: u32, content_offset: u32, text_lines: Vec<String>) -> Self {
41 Self {
42 vspan: vspan,
43 hspan: hspan,
44 content_offset: content_offset,
45 text_lines: text_lines,
46 }
47 }
48}
49
50type Row = Vec<Cell>;
52
53impl Parser {
55
56 pub fn parse_grid_table(src_lines: &Vec<String>, line_cursor: &LineCursor) -> TableResult {
58 let table_lines = match Self::isolate_grid_table(src_lines, line_cursor) {
60 TableIsolationResult::Table(lines) => lines,
61 TableIsolationResult::EmptyTable => {
62 return TableResult::MalformedTableError(format!(
63 "Table starting on line {} was empty.",
64 line_cursor.sum_total()
65 ))
66 }
67 TableIsolationResult::EndOfInput => {
68 return TableResult::MalformedTableError(format!(
69 "Ran off the end of input when scanning a table starting on line {}.",
70 line_cursor.sum_total()
71 ))
72 }
73 };
74
75 let table_height = if let Some(line_len) = table_lines.len().checked_sub(1) {
76 line_len
77 } else {
78 return TableResult::MalformedTableError(format!(
79 "Table on line {} only had a top border?",
80 line_cursor.sum_total()
81 ));
82 };
83 let table_width = {
84 match table_lines.get(0) {
85 Some(line) => match line.chars().count().checked_sub(1) {
86 Some(num) => num,
87 None => return TableResult::MalformedTableError(format!(
88 "The first row of grid table on line {} was only a single character long?",
89 line_cursor.sum_total()
90 )),
91 },
92 None => {
93 return TableResult::MalformedTableError(format!(
94 "Table on line {} didn't even have a top border?",
95 line_cursor.sum_total()
96 ))
97 }
98 }
99 };
100
101 let mut cell_corner_coordinates = Vec::<(usize, usize)>::from([(0, 0)]);
102
103 let done_cells = [usize::MAX].repeat(table_width);
104
105 while let Some((top_pos, left_pos)) = cell_corner_coordinates.pop() {
107 if top_pos == table_height || left_pos == table_width || top_pos <= done_cells[left_pos]
108 {
109 continue;
110 }
111
112 let (right_pos, bottom_pos) = if let Some((right, bottom)) =
114 Self::outline_cell(&table_lines, top_pos, left_pos)
115 {
116 (right, bottom)
117 } else {
118 continue;
119 };
120 }
121 todo!()
122 }
123
124 fn isolate_grid_table(
126 src_lines: &Vec<String>,
127 line_cursor: &LineCursor,
128 ) -> TableIsolationResult {
129 let start_line = line_cursor.relative_offset();
130 let indent_allowed = true;
131 let remove_indent = true;
132 let alignment = if let Some(line) = src_lines.get(line_cursor.relative_offset()) {
133 line.chars().take_while(|c| c.is_whitespace()).count()
134 } else {
135 return TableIsolationResult::EndOfInput;
136 };
137
138 let (mut lines, offset) = if let TextBlockResult::Ok { lines, offset } = Parser::read_text_block(
139 src_lines,
140 start_line,
141 indent_allowed,
142 remove_indent,
143 Some(alignment),
144 true
145 ) {
146 (lines, offset)
147 } else {
148 return TableIsolationResult::EndOfInput;
149 };
150
151 while let Some(line) = lines.last_mut() {
154 if let Some(capts) =
155 crate::parser::automata::GRID_TABLE_TOP_AND_BOT_AUTOMATON.captures(line)
156 {
157 break;
158 } else {
159 if let None = lines.pop() {
160 return TableIsolationResult::EmptyTable;
161 }
162 }
163 }
164
165 if lines.len() == 1 {
167 return TableIsolationResult::EmptyTable;
168 }
169
170 TableIsolationResult::Table(lines)
171 }
172
173 fn outline_cell(
176 table_lines: &Vec<String>,
177 top_pos: usize,
178 left_pos: usize,
179 ) -> Option<(usize, usize)> {
180 let colseps = Vec::<usize>::new();
181 if let Some((right, bottom)) = Self::find_right_colsep(table_lines, top_pos, left_pos) {
182 Some((right, bottom))
183 } else {
184 None
185 }
186 }
187
188 fn find_right_colsep(
189 table_lines: &Vec<String>,
190 top_pos: usize,
191 left_pos: usize,
192 ) -> Option<(usize, usize)> {
193 if let Some(line) = table_lines.get(top_pos) {
194 let topline_chars = line.chars().enumerate().skip(left_pos + 1);
195
196 for (i, c) in topline_chars {
197 if c == '+' {
198 if let Some(bottom_pos) =
199 Self::find_below_rowsep(table_lines, top_pos, left_pos, i)
200 {
201 return Some((i, bottom_pos));
202 } else {
203 return None;
204 };
205 } else {
206 continue;
207 }
208 }
209 } else {
210 return None;
211 }
212 None
213 }
214
215 fn find_below_rowsep(
217 table_lines: &Vec<String>,
218 top_pos: usize,
219 left_pos: usize,
220 right_pos: usize,
221 ) -> Option<usize> {
222 let lines = table_lines.iter().skip(top_pos + 1);
223
224 for line in lines {
225 let c = if let Some(c) = line.chars().skip(left_pos).next() {
226 c
227 } else {
228 return None;
229 };
230 }
231 todo!()
232 }
233
234 fn find_left_colsep(table_lines: &Vec<String>) {
236 todo!()
237 }
238
239 fn find_above_rowsep(table_lines: &Vec<String>) {
241 todo!()
242 }
243
244 pub fn parse_simple_table(table_string: Vec<String>) -> TableResult {
248 todo!()
249 }
250
251 pub fn isolate_simple_table(src_lines: &Vec<String>) {
253 todo!()
254 }
255}
256
257pub enum TableIsolationResult {
258 Table(Vec<String>),
259 EndOfInput,
260 EmptyTable,
261}