mech_syntax/
structures.rs

1#[macro_use]
2use crate::*;
3
4#[cfg(not(feature = "no-std"))] use core::fmt;
5#[cfg(feature = "no-std")] use alloc::fmt;
6#[cfg(feature = "no-std")] use alloc::string::String;
7#[cfg(feature = "no-std")] use alloc::vec::Vec;
8use nom::{
9  IResult,
10  branch::alt,
11  sequence::tuple as nom_tuple,
12  combinator::{opt, eof, peek},
13  multi::{many1, many_till, many0, separated_list1,separated_list0},
14  bytes::complete::{take_until, take_while},
15  Err,
16  Err::Failure
17};
18use std::collections::HashMap;
19use colored::*;
20
21use crate::*;
22use crate::nodes::Matrix;
23
24// Structures
25// =============================================================================
26
27pub fn max_err<'a>(x: Option<ParseError<'a>>, y: ParseError<'a>) -> ParseError<'a> {
28  match (x,&y) {
29    (None, y) => y.clone(),
30    _ => y.clone(),
31  }
32}
33
34// structure := empty-set | empty-table | table | matrix | tuple | tuple-struct | record | map | set ;
35pub fn structure(input: ParseString) -> ParseResult<Structure> {
36  match empty_set(input.clone()) {
37    Ok((input, set)) => {return Ok((input, Structure::Set(set)));},
38    _ => (),
39  }
40  match empty_map(input.clone()) {
41    Ok((input, map)) => {return Ok((input, Structure::Map(map)));},
42    _ => (),
43  }
44  match table(input.clone()) {
45    Ok((input, tbl)) => {
46      return Ok((input, Structure::Table(tbl)));
47    },
48    //Err(Failure(err)) => { return Err(Failure(err)); }, 
49    _ => (),
50  }
51  match matrix(input.clone()) {
52    Ok((input, mtrx)) => {return Ok((input, Structure::Matrix(mtrx)));},
53    //Err(Failure(err)) => { return Err(Failure(err)); }, 
54    _ => (),
55  }
56  match tuple(input.clone()) {
57    Ok((input, tpl)) => {return Ok((input, Structure::Tuple(tpl)));},
58    _ => (),
59  }
60  match tuple_struct(input.clone()) {
61    Ok((input, tpl)) => {return Ok((input, Structure::TupleStruct(tpl)));},
62    _ => (),
63  }
64  match record(input.clone()) {
65    Ok((input, table)) => {return Ok((input, Structure::Record(table)));},
66    _ => (),
67  }
68  match map(input.clone()) {
69    Ok((input, map)) => {return Ok((input, Structure::Map(map)));},
70    _ => (),
71  }
72  match set(input.clone()) {
73    Ok((input, set)) => {return Ok((input, Structure::Set(set)));},
74    Err(err) => {return Err(err);}
75  }
76}
77
78// Matrix
79// ----------------------------------------------------------------------------
80
81// matrix := matrix-start, (box-drawing-char | whitespace)*, matrix-row*, box-drawing-char*, matrix-end ;
82pub fn matrix(input: ParseString) -> ParseResult<Matrix> {
83  let msg = "Expects right bracket ']' to finish the matrix";
84  let (input, (_, r)) = range(matrix_start)(input)?;
85  let (input, _) = many0(alt((box_drawing_char,whitespace)))(input)?;
86  let (input, rows) = many0(matrix_row)(input)?;
87  let (input, _) = many0(alt((box_drawing_char,whitespace)))(input)?;
88  let (input, _) = whitespace0(input)?;
89  let (input, _) = match label!(matrix_end, msg, r)(input) {
90    Ok(k) => k,
91    Err(err) => {
92      return Err(err);
93    }
94  };
95  Ok((input, Matrix{rows}))
96}
97
98// matrix-column := (space | tab)*, expression, ((space | tab)*, ("," | table-separator)?, (space | tab)*) ;
99pub fn matrix_column(input: ParseString) -> ParseResult<MatrixColumn> {
100  let (input, _) = many0(space_tab)(input)?;
101  let (input, element) = match expression(input) {
102    Ok(result) => result,
103    Err(err) => {
104      return Err(err);
105    }
106  };
107  let (input, _) = nom_tuple((many0(space_tab),opt(alt((comma,table_separator))), many0(space_tab)))(input)?;
108  Ok((input, MatrixColumn{element}))
109}
110
111// matrix-row := table-separator?, (space | tab)*, matrix-column+, semicolon?, new-line?, (box-drawing-char+, new-line)? ;
112pub fn matrix_row(input: ParseString) -> ParseResult<MatrixRow> {
113  let (input, _) = many0(space_tab)(input)?;
114  let (input, _) = opt(table_separator)(input)?;
115  let (input, _) = many0(space_tab)(input)?;
116  let (input, columns) = match many1(matrix_column)(input) {
117    Ok(result) => result,
118    Err(error) => {
119      return Err(error);
120    }
121  };
122  let (input, _) = nom_tuple((opt(semicolon), opt(new_line)))(input)?;
123  let (input, _) = opt(nom_tuple((many1(box_drawing_char),new_line)))(input)?;
124  Ok((input, MatrixRow{columns}))
125}
126
127// matrix-start := box-tl-round | box-tl | left-bracket ;
128pub fn matrix_start(input: ParseString) -> ParseResult<Token> {
129  alt((box_tl_round, box_tl, box_tl_bold, left_bracket))(input)
130}
131
132// matrix-end := box-br-round | box-br | right-bracket ;
133pub fn matrix_end(input: ParseString) -> ParseResult<Token> {
134  let result = alt((box_br_round, box_br, box_br_bold, right_bracket))(input);
135  result
136}
137
138// Table
139// ----------------------------------------------------------------------------
140
141// table := inline-table | regular-table | fancy-table ;
142fn table(input: ParseString) -> ParseResult<Table> { 
143  alt((inline_table, regular_table, fancy_table))(input)
144}
145
146// fancy-table := table-top, fancy-header, +fancy-row, table-bottom ;
147pub fn fancy_table(input: ParseString) -> ParseResult<Table> {
148  let (input, _) = table_top(input)?;
149  let (input, _) = many0(space_tab)(input)?;
150  let (input, _) = table_separator(input)?;
151  let (input, _) = many0(space_tab)(input)?;
152  let (input, header) = table_header(input)?;
153  let (input, rows) = separated_list1(new_line,alt((table_row,row_separator)))(input)?;
154  let rows: Vec<TableRow> = rows.into_iter().filter(|row| !row.columns.is_empty()).collect();
155  Ok((input, Table{header, rows}))
156}
157
158// row-separator := *whitespace, *box-drawing-char, *(space | tab), *whitespace ;
159pub fn row_separator(input: ParseString) -> ParseResult<TableRow> {
160  let (input, _) = whitespace0(input)?;
161  let (input, _) = many1(alt((box_drawing_char,table_end,space_tab)))(input)?;
162  let (input, _) = many0(space_tab)(input)?;
163  Ok((input, TableRow{columns: vec![]}))
164}
165
166// table-top := table-start, *box-drawing-char, new-line ;
167fn table_top(input: ParseString) -> ParseResult<()> {
168  let (input, _) = table_start(input)?;
169  let (input, _) = many0(box_drawing_char)(input)?;
170  let (input, _) = new_line(input)?;
171  Ok((input, ()))
172}
173
174// table-bottom := *box-drawing-char, table-end;
175fn table_bottom(input: ParseString) -> ParseResult<()> {
176  let (input, _) = many0(box_drawing_char)(input)?;
177  let (input, _) = table_end(input)?;
178  Ok((input, ()))
179}
180
181// inline-table := table-separator, *whitespace, table-header, *whitespace, +table-row;
182pub fn inline_table(input: ParseString) -> ParseResult<Table> {
183  let (input, _) = table_separator(input)?;
184  let (input, _) = whitespace0(input)?;
185  let (input, header) = table_header(input)?;
186  let (input, _) = whitespace0(input)?;
187  let (input, rows) = many1(inline_table_row)(input)?;
188  Ok((input, Table{header, rows}))
189}
190
191// table-row := bar, list1((space | tab)*, expression), (space | tab)*, bar, new-line ;
192pub fn inline_table_row(input: ParseString) -> ParseResult<TableRow> {
193  let (input, _) = many0(space_tab)(input)?;
194  let (input, row) = many1(nom_tuple((many0(space_tab), expression)))(input)?;
195  let (input, _) = many0(space_tab)(input)?;
196  let (input, _) = table_separator(input)?;
197  let row = row.into_iter().map(|(_,tkn)| TableColumn{element:tkn}).collect();
198  Ok((input, TableRow{columns: row}))
199}
200
201// fancy-table := table-start, (box-drawing-char | whitespace)*, table-header, (box-drawing-char | whitespace)*, table-row+, box-drawing-char*, whitespace*, table-end ;
202pub fn regular_table(input: ParseString) -> ParseResult<Table> {
203  let (input, _) = table_separator(input)?;
204  let (input, _) = whitespace0(input)?;
205  let (input, header) = table_header(input)?;
206  let (input, rows) = separated_list1(new_line,table_row)(input)?;
207  Ok((input, Table{header,rows}))
208}
209
210// table-header := list1(space-tab+, field), (space | tab)*, (bar| box-vert), whitespace* ;
211pub fn table_header(input: ParseString) -> ParseResult<Vec<Field>> {
212  let (input, fields) = separated_list1(many1(alt((space_tab, table_separator))),field)(input)?;
213  let (input, _) = many0(space_tab)(input)?;
214  let (input, _) = table_separator(input)?;
215  let (input, _) = whitespace0(input)?;
216  Ok((input, fields))
217}
218
219// table-row := bar, list1((space | tab)*, expression), (space | tab)*, bar, new-line ;
220pub fn table_row(input: ParseString) -> ParseResult<TableRow> {
221  let (input, _) = whitespace0(input)?;
222  let (input, _) = table_separator(input)?;
223  let (input, row) = many1(nom_tuple((many0(alt((space_tab, table_separator))), expression)))(input)?;
224  let (input, _) = many0(space_tab)(input)?;
225  let (input, _) = table_separator(input)?;
226  let (input, _) = many0(space_tab)(input)?;
227  let row = row.into_iter().map(|(_,tkn)| TableColumn{element:tkn}).collect();
228  Ok((input, TableRow{columns: row}))
229}
230
231// table-column := (space | tab)*, expression, ((space | tab)*, ("," | table-separator)?, (space | tab)*) ;
232pub fn table_column(input: ParseString) -> ParseResult<TableColumn> {
233  let (input, _) = many0(space_tab)(input)?;
234  let (input, element) = match expression(input) {
235    Ok(result) => result,
236    Err(err) => {
237      return Err(err);
238    }
239  };
240  let (input, _) = nom_tuple((many0(space_tab),opt(alt((comma,table_separator))), many0(space_tab)))(input)?;
241  Ok((input, TableColumn{element}))
242}
243
244// field := identifier, kind-annotation? ;
245pub fn field(input: ParseString) -> ParseResult<Field> {
246  let (input, name) = identifier(input)?;
247  let (input, kind) = opt(kind_annotation)(input)?;
248  Ok((input, Field{name, kind}))
249}
250
251// box-drawing-char := box-tl | box-br | box-bl | box-tr | box-tr-round | box-bl-round | box-vert | box-cross | box-horz | box-t-left | box-t-right | box-t-top | box-t-bottom ;
252pub fn box_drawing_char(input: ParseString) -> ParseResult<Token> {
253  alt((box_tl, box_bl, box_tr, box_tl_bold, box_bl_bold, box_tr_bold, box_tr_round, box_bl_round, box_vert, box_cross, box_horz, box_t_left, box_t_right, box_t_top, box_t_bottom))(input)
254}
255
256// box-drawing-emoji := box-tl | box-br | box-bl | box-tr | box-tl-round | box-br-round | box-tr-round | box-bl-round | box-vert | box-cross | box-horz | box-t-left | box-t-right | box-t-top | box-t-bottom ;
257pub fn box_drawing_emoji(input: ParseString) -> ParseResult<Token> {
258  alt((box_tl, box_bl, box_tr, box_tl_bold, box_bl_bold, box_tr_bold, box_tl_round, box_br_round, box_tr_round, box_bl_round, box_vert, box_cross, box_horz, box_t_left, box_t_right, box_t_top, box_t_bottom))(input)
259}
260
261// table-start := box-tl-round | box-tl | left-brace ;
262pub fn table_start(input: ParseString) -> ParseResult<Token> {
263  alt((box_tl_round, box_tl, box_tl_bold, left_brace, table_separator))(input)
264}
265
266// table-end := box-br-round | box-br | right-brace ;
267pub fn table_end(input: ParseString) -> ParseResult<Token> {
268  let result = alt((box_br_round, box_br, box_br_bold, right_brace, table_separator))(input);
269  result
270}
271
272// table-separator := box_vert ;
273pub fn table_separator(input: ParseString) -> ParseResult<Token> {
274  let (input, token) = alt((box_vert,box_vert_bold,bar))(input)?;
275  Ok((input, token))
276}
277
278pub fn table_horz(input: ParseString) -> ParseResult<Token> {
279  let (input, token) = alt((dash,box_horz))(input)?;
280  Ok((input, token))
281}
282
283// Map
284// ----------------------------------------------------------------------------
285
286// empty-table := table-start, whitespace*, table-end ;
287pub fn empty_map(input: ParseString) -> ParseResult<Map> {
288  let (input, _) = left_brace(input)?;
289  let (input, _) = whitespace0(input)?;
290  let (input, _) = colon(input)?;
291  let (input, _) = whitespace0(input)?;
292  let (input, _) = right_brace(input)?;
293  Ok((input, Map{elements: vec![]}))
294}
295
296// map := "{", whitespace*, mapping*, whitespace*, "}" ;
297pub fn map(input: ParseString) -> ParseResult<Map> {
298  let msg = "Expects right bracket '}' to terminate inline table";
299  let (input, (_, r)) = range(left_brace)(input)?;
300  let (input, _) = whitespace0(input)?;
301  let (input, elements) = many1(mapping)(input)?;
302  let (input, _) = whitespace0(input)?;
303  let (input, _) = label!(right_brace, msg, r)(input)?;
304  Ok((input, Map{elements}))
305}
306
307// mapping :=  whitespace*, expression, whitespace*, ":", whitespace*, expression, comma?, whitespace* ;
308pub fn mapping(input: ParseString) -> ParseResult<Mapping> {
309  let msg1 = "Unexpected space before colon ':'";
310  let msg2 = "Expects a value";
311  let msg3 = "Expects whitespace or comma followed by whitespace";
312  let msg4 = "Expects whitespace";
313  let (input, _) = whitespace0(input)?;
314  let (input, key) = expression(input)?;
315  let (input, _) = whitespace0(input)?;
316  let (input, _) = colon(input)?;
317  let (input, _) = whitespace0(input)?;
318  let (input, value) = label!(expression, msg2)(input)?;
319  let (input, _) = whitespace0(input)?;
320  let (input, _) = opt(comma)(input)?;
321  let (input, _) = whitespace0(input)?;
322  Ok((input, Mapping{key, value}))
323}
324
325
326// Record
327// ----------------------------------------------------------------------------
328
329// record := table-start, whitespace*, binding+, whitespace*, table_end ;
330pub fn record(input: ParseString) -> ParseResult<Record> {
331  let msg = "Expects right bracket ']' to terminate inline table";
332  let (input, (_, r)) = range(table_start)(input)?;
333  let (input, _) = whitespace0(input)?;
334  let (input, bindings) = many1(binding)(input)?;
335  let (input, _) = whitespace0(input)?;
336  let (input, _) = label!(table_end, msg, r)(input)?;
337  Ok((input, Record{bindings}))
338}
339
340// binding := identifier, kind_annotation?, colon, expression, ","? ;
341pub fn binding(input: ParseString) -> ParseResult<Binding> {
342  let msg1 = "Unexpected space before colon ':'";
343  let msg2 = "Expects a value";
344  let msg3 = "Expects whitespace or comma followed by whitespace";
345  let msg4 = "Expects whitespace";
346  let (input, _) = whitespace0(input)?;
347  let (input, name) = identifier(input)?;
348  let (input, kind) = opt(kind_annotation)(input)?;
349  let (input, _) = whitespace0(input)?;
350  let (input, _) = colon(input)?;
351  let (input, _) = whitespace0(input)?;
352  let (input, value) = label!(expression, msg2)(input)?;
353  let (input, _) = whitespace0(input)?;
354  let (input, _) = opt(comma)(input)?;
355  let (input, _) = whitespace0(input)?;
356  Ok((input, Binding{name, kind, value}))
357}
358
359// Set
360// ----------------------------------------------------------------------------
361
362// empty-set := table-start, whitespace*, empty, whitespace*, table-end ;
363pub fn empty_set(input: ParseString) -> ParseResult<Set> {
364  let (input, _) = left_brace(input)?;
365  let (input, _) = whitespace0(input)?;
366  let (input, _) = opt(empty)(input)?;
367  let (input, _) = whitespace0(input)?;
368  let (input, _) = right_brace(input)?;
369  Ok((input,  Set{elements: vec![]}))
370}
371
372// set := "{", whitespace*, list0(("," | whitespace+), expression), whitespace*, "}" ;
373pub fn set(input: ParseString) -> ParseResult<Set> {
374  let msg = "Expects right bracket '}' to terminate inline table";
375  let (input, (_, r)) = range(left_brace)(input)?;
376  let (input, _) = whitespace0(input)?;
377  let (input, elements) = separated_list1(alt((list_separator,whitespace1)), expression)(input)?;
378  let (input, _) = whitespace0(input)?;
379  let (input, _) = label!(right_brace, msg, r)(input)?;
380  Ok((input, Set{elements}))
381}
382
383// Tuple
384// ----------------------------------------------------------------------------
385
386// tuple := "(", list0(",", expression), ")" ;
387pub fn tuple(input: ParseString) -> ParseResult<Tuple> {
388  let (input, _) = left_parenthesis(input)?;
389  let (input, _) = whitespace0(input)?;
390  let (input, exprs) = separated_list0(list_separator, expression)(input)?;
391  let (input, _) = whitespace0(input)?;
392  let (input, _) = right_parenthesis(input)?;
393  Ok((input, Tuple{elements: exprs}))
394}
395
396// tuple-struct = atom, "(", expression, ")" ;
397pub fn tuple_struct(input: ParseString) -> ParseResult<TupleStruct> {
398  let (input, _) = grave(input)?;
399  let (input, name) = identifier(input)?;
400  let (input, _) = left_parenthesis(input)?;
401  let (input, _) = whitespace0(input)?;
402  let (input, value) = expression(input)?;
403  let (input, _) = whitespace0(input)?;
404  let (input, _) = right_parenthesis(input)?;
405  Ok((input, TupleStruct{name, value: Box::new(value)}))
406}