forked from katzen-cafe/iowo
70 lines
1.9 KiB
Rust
70 lines
1.9 KiB
Rust
|
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);
|
||
|
}
|