From 9af71ed3f4ad04cf5d31bc195b7abd12b5a61872 Mon Sep 17 00:00:00 2001 From: Schrottkatze Date: Tue, 30 Apr 2024 09:45:36 +0200 Subject: [PATCH] lang: implement vec, list and matrix --- .../parser/grammar/expression/collection.rs | 8 +-- .../grammar/expression/collection/matrix.rs | 71 ------------------- .../grammar/expression/collection/vec.rs | 71 ++++++++++++++++++- .../parser/grammar/expression/instruction.rs | 6 +- crates/lang/src/parser/syntax_kind.rs | 11 ++- 5 files changed, 78 insertions(+), 89 deletions(-) delete mode 100644 crates/lang/src/parser/grammar/expression/collection/matrix.rs diff --git a/crates/lang/src/parser/grammar/expression/collection.rs b/crates/lang/src/parser/grammar/expression/collection.rs index 0b525ad..e72cb6c 100644 --- a/crates/lang/src/parser/grammar/expression/collection.rs +++ b/crates/lang/src/parser/grammar/expression/collection.rs @@ -5,13 +5,12 @@ use crate::parser::{ CompletedMarker, Parser, }; -use self::{attr_set::attr_set, matrix::matrix, vec::vec}; +use self::{attr_set::attr_set, vec::vec_matrix_list}; mod attr_set; -mod matrix; mod vec; -const COLLECTION_START: TokenSet = enum_set!(MAT_KW | L_BRACK | L_BRACE); +const COLLECTION_START: TokenSet = enum_set!(L_BRACK | L_BRACE); pub fn collection(p: &mut Parser) -> Option { if !COLLECTION_START.contains(p.current()) { @@ -19,8 +18,7 @@ pub fn collection(p: &mut Parser) -> Option { } Some(match p.current() { - MAT_KW => matrix(p), - L_BRACK => vec(p), + L_BRACK => vec_matrix_list(p), L_BRACE => attr_set(p), _ => unreachable!(), }) diff --git a/crates/lang/src/parser/grammar/expression/collection/matrix.rs b/crates/lang/src/parser/grammar/expression/collection/matrix.rs deleted file mode 100644 index a8e21a1..0000000 --- a/crates/lang/src/parser/grammar/expression/collection/matrix.rs +++ /dev/null @@ -1,71 +0,0 @@ -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("matrix"); - 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("mat_body"); - 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("mat_row"); - let mut row_items = 0; - while going { - let mat_item = p.start("mat_item"); - 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("mat_row"); - p.do_bump(); - row_items = 0; - } - R_BRACK => going = false, - _ => { - let err = p.start("err"); - p.do_bump(); - - err.complete_err(p, SyntaxError::Expected(vec![COMMA, SEMICOLON, R_BRACK])); - } - }; - } else if p.at(R_BRACK) { - mat_item.abandon(p); - going = false; - } else { - mat_item.abandon(p); - let err = p.start("err"); - 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); -} diff --git a/crates/lang/src/parser/grammar/expression/collection/vec.rs b/crates/lang/src/parser/grammar/expression/collection/vec.rs index 76f3684..eff741a 100644 --- a/crates/lang/src/parser/grammar/expression/collection/vec.rs +++ b/crates/lang/src/parser/grammar/expression/collection/vec.rs @@ -1,5 +1,70 @@ -use crate::parser::{CompletedMarker, Parser}; +use crate::parser::{ + error::SyntaxError, grammar::expression::atom, CompletedMarker, Marker, Parser, SyntaxKind::*, +}; -pub fn vec(p: &mut Parser) -> CompletedMarker { - todo!() +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).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) { + start.complete(p, LIST) + } else { + 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).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); + } + } +} + +// 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).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); + } + } + } } diff --git a/crates/lang/src/parser/grammar/expression/instruction.rs b/crates/lang/src/parser/grammar/expression/instruction.rs index 5a12f4c..832d2ab 100644 --- a/crates/lang/src/parser/grammar/expression/instruction.rs +++ b/crates/lang/src/parser/grammar/expression/instruction.rs @@ -1,6 +1,6 @@ use crate::parser::{syntax_kind::SyntaxKind::*, CompletedMarker, Parser}; -use super::lit::literal; +use super::{atom, lit::literal}; pub fn instr(p: &mut Parser) -> Option { if !p.at(IDENT) { @@ -26,8 +26,8 @@ fn instr_name(p: &mut Parser) { } fn instr_params(p: &mut Parser) { - if let Some(start) = literal(p) { - while literal(p).is_some() {} + if let Some(start) = atom(p) { + while atom(p).is_some() {} start.precede(p).complete(p, INSTR_PARAMS); } diff --git a/crates/lang/src/parser/syntax_kind.rs b/crates/lang/src/parser/syntax_kind.rs index cc1754c..0447a90 100644 --- a/crates/lang/src/parser/syntax_kind.rs +++ b/crates/lang/src/parser/syntax_kind.rs @@ -23,10 +23,6 @@ pub enum SyntaxKind { LET_KW, #[token("in")] IN_KW, - #[token("mat")] - MAT_KW, - #[regex("[\\d]+x[\\d]+")] - PAT_DIMENSIONS, #[regex("[\\d]+")] INT_NUM, #[regex("[+-]?([\\d]+\\.[\\d]*|[\\d]*\\.[\\d]+)")] @@ -34,11 +30,12 @@ pub enum SyntaxKind { #[regex(r#""([^"\\]|\\["\\bnfrt]|u[a-fA-F0-9]{4})*""#)] STRING, MATRIX, - MAT_BODY, MAT_ROW, - MAT_ITEM, - DECL, + VEC, LIST, + // either of a vec, a matrix or a list + COLLECTION_ITEM, + DECL, PARENTHESIZED_EXPR, EXPR, LITERAL,