iowo/crates/lang/src/lst_parser/grammar/expression/collection/vec.rs

97 lines
3.4 KiB
Rust

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.error(p, SyntaxError::Expected(vec![EXPR, R_BRACK]))
}
}
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")
.error(p, SyntaxError::SpaceSepInList);
} else if p.at(SEMICOLON) {
let semi_err = p.start("semicolon_err");
p.eat(SEMICOLON);
semi_err.error(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);
}
} else if p.at(COMMA) {
let err_unexpected_comma = p.start("err_unexpected_comma");
p.do_bump();
err_unexpected_comma.error(p, SyntaxError::CommaInMatOrVec);
} else {
let err_unexpected = p.start("err_unexpected_tok");
p.do_bump();
err_unexpected.error(p, SyntaxError::Expected(vec![EXPR, SEMICOLON, R_BRACK]));
}
}
}