use crate::lst_parser::{ error::SyntaxError, grammar::expression::atom, CompletedMarker, Marker, Parser, SyntaxKind::*, }; pub fn vec_matrix_list(p: &mut Parser) -> CompletedMarker { let start = p.start("vec_matrix_list_start"); assert!(p.eat(L_BRACK)); let row_start = p.start("matrix_row_start"); if let Some(item) = atom(p) { item.precede(p, "coll_item_start") .complete(p, COLLECTION_ITEM); if p.at(COMMA) { row_start.abandon(p); return finish_list(p, start); } finish_mat_or_vec(p, start, row_start) } else if p.eat(R_BRACK) { row_start.abandon(p); start.complete(p, LIST) } else { row_start.abandon(p); start.complete_err(p, SyntaxError::Expected(vec![EXPR, R_BRACK])) } } // TODO: handle semicolons, other wrong toks fn finish_list(p: &mut Parser, list_start: Marker) -> CompletedMarker { loop { if p.eat(COMMA) { if let Some(item) = atom(p) { item.precede(p, "coll_item_start") .complete(p, COLLECTION_ITEM); } else if p.eat(R_BRACK) { return list_start.complete(p, LIST); } } else if p.eat(R_BRACK) { return list_start.complete(p, LIST); } else if let Some(item) = atom(p) { item.precede(p, "next_item") .complete(p, COLLECTION_ITEM) .precede(p, "err_space_sep") .complete_err(p, SyntaxError::SpaceSepInList); } else if p.at(SEMICOLON) { let semi_err = p.start("semicolon_err"); p.eat(SEMICOLON); semi_err.complete_err(p, SyntaxError::SemicolonInList); if let Some(item) = atom(p) { item.precede(p, "coll_item_start") .complete(p, COLLECTION_ITEM); } else if p.eat(R_BRACK) { return list_start.complete(p, LIST); } } } } // TODO: handle commas, general other wrong toks fn finish_mat_or_vec(p: &mut Parser, coll_start: Marker, mut row_start: Marker) -> CompletedMarker { let mut is_matrix = false; let mut row_item_count = 1; loop { if let Some(item) = atom(p) { item.precede(p, "coll_item_start") .complete(p, COLLECTION_ITEM); row_item_count += 1; } else if p.at(SEMICOLON) { is_matrix = true; row_start.complete(p, MAT_ROW); p.eat(SEMICOLON); row_start = p.start("matrix_row_start"); row_item_count = 0; } else if p.at(R_BRACK) { if is_matrix && row_item_count == 0 { row_start.abandon(p); p.eat(R_BRACK); return coll_start.complete(p, MATRIX); } else if is_matrix { row_start.complete(p, MAT_ROW); p.eat(R_BRACK); return coll_start.complete(p, MATRIX); } else { row_start.abandon(p); p.eat(R_BRACK); return coll_start.complete(p, VEC); } } } }