use crate::parser::{ error::SyntaxError, grammar::expression::{self, expression}, syntax_kind::SyntaxKind::*, CompletedMarker, Marker, Parser, }; pub fn matrix(p: &mut Parser) -> CompletedMarker { let matrix = p.start(); p.eat(MAT_KW); if !p.eat(PAT_DIMENSIONS) { eprintln!("TODO (as eprintln so i dont forget): improve recovery algorithms"); return matrix.complete_err(p, SyntaxError::Expected(vec![PAT_DIMENSIONS])); } matrix_body(p); matrix.complete(p, MATRIX) } fn matrix_body(p: &mut Parser) { let mat_body = p.start(); if !p.eat(L_BRACK) { mat_body.complete_err(p, SyntaxError::Expected(vec![MAT_BODY])); return (); } let mut going = true; let mut mat_row = p.start(); let mut row_items = 0; while going { let mat_item = p.start(); if expression(p).is_some() { mat_item.complete(p, MAT_ITEM); row_items += 1; match p.current() { COMMA => p.do_bump(), SEMICOLON => { mat_row.complete(p, MAT_ROW); mat_row = p.start(); p.do_bump(); row_items = 0; } R_BRACK => going = false, _ => { let err = p.start(); p.do_bump(); err.complete_err(p, SyntaxError::Expected(vec![COMMA, SEMICOLON, R_BRACK])); } }; } else if p.at(R_BRACK) { going = false; } else { let err = p.start(); p.do_bump(); err.complete_err(p, SyntaxError::Expected(vec![EXPR, R_BRACK])); } } if row_items != 0 { mat_row.complete(p, MAT_ROW); } else { mat_row.abandon(p); } p.eat(R_BRACK); mat_body.complete(p, MAT_BODY); }