From d9ae98528219126755a73715fc84d5ca72308567 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moritz=20H=C3=B6lting?= <87192362+moritz-hoelting@users.noreply.github.com> Date: Wed, 13 Aug 2025 12:58:35 +0200 Subject: [PATCH] change syntax of array declaration: move brackets from after name to after type --- grammar.md | 2 +- src/syntax/syntax_tree/statement.rs | 139 ++++++++++++---------------- src/transpile/error.rs | 8 ++ src/transpile/expression.rs | 26 +++++- 4 files changed, 93 insertions(+), 82 deletions(-) diff --git a/grammar.md b/grammar.md index fc9549d..aa2432a 100644 --- a/grammar.md +++ b/grammar.md @@ -99,7 +99,7 @@ FunctionParameterList: ```ebnf ArrayVariableDeclaration: - ('int' | 'bool') identifier '[' integer ']' VariableDeclarationAssignment? + ('int' | 'bool') '[' integer ']' identifier VariableDeclarationAssignment? ``` ## ComptimeValueDeclaration diff --git a/src/syntax/syntax_tree/statement.rs b/src/syntax/syntax_tree/statement.rs index 8a245e6..7b995f7 100644 --- a/src/syntax/syntax_tree/statement.rs +++ b/src/syntax/syntax_tree/statement.rs @@ -493,7 +493,7 @@ impl SingleVariableDeclaration { /// /// ```ebnf /// ArrayVariableDeclaration: -/// ('int' | 'bool') identifier '[' integer ']' VariableDeclarationAssignment? +/// ('int' | 'bool') '[' integer ']' identifier VariableDeclarationAssignment? /// ``` #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)] @@ -501,9 +501,6 @@ pub struct ArrayVariableDeclaration { /// The type of the variable. #[get = "pub"] variable_type: Keyword, - /// The identifier of the variable. - #[get = "pub"] - identifier: Identifier, /// The opening bracket of the array. #[get = "pub"] open_bracket: Punctuation, @@ -513,6 +510,9 @@ pub struct ArrayVariableDeclaration { /// The closing bracket of the array. #[get = "pub"] close_bracket: Punctuation, + /// The identifier of the variable. + #[get = "pub"] + identifier: Identifier, /// The optional assignment of the variable. #[get = "pub"] assignment: Option, @@ -1053,11 +1053,7 @@ impl Parser<'_> { None }; - // read identifier - self.stop_at_significant(); - let identifier = self.parse_identifier(handler)?; - - match self.stop_at_significant() { + let index = match self.stop_at_significant() { Reading::IntoDelimited(punc) if punc.punctuation == '[' && matches!(variable_type.keyword, KeywordKind::Int | KeywordKind::Bool) => @@ -1094,84 +1090,69 @@ impl Parser<'_> { let close_bracket = tree.close; let inner = tree.tree?; - match inner { - IndexingType::IntegerSize(size) => { - let assignment = self - .try_parse(|p| { - // read equals sign - let equals = p.parse_punctuation('=', true, &VoidHandler)?; - - // read expression - let expression = p.parse_expression(&VoidHandler)?; - - Ok(VariableDeclarationAssignment { equals, expression }) - }) - .ok(); - - Ok(VariableDeclaration::Array(ArrayVariableDeclaration { - variable_type, - identifier, - open_bracket, - size, - close_bracket, - assignment, - annotations: VecDeque::new(), - })) - } - IndexingType::None => match variable_type.keyword { - KeywordKind::Int => { - Ok(VariableDeclaration::Score(ScoreVariableDeclaration { - int_keyword: variable_type, - criteria: criteria_selection, - identifier, - open_bracket, - close_bracket, - assignment: None, - annotations: VecDeque::new(), - })) - } - KeywordKind::Bool => Ok(VariableDeclaration::Tag(TagVariableDeclaration { - bool_keyword: variable_type, - identifier, - open_bracket, - close_bracket, - target_assignment: None, - annotations: VecDeque::new(), - })), - _ => unreachable!(), - }, - } + Some((open_bracket, inner, close_bracket)) } - // SingleVariableDeclaration with Assignment - Reading::Atomic(Token::Punctuation(punc)) if punc.punctuation == '=' => { - self.forward(); - let equals = punc; - let expression = self.parse_expression(handler)?; - let assignment = VariableDeclarationAssignment { equals, expression }; + _ => None, + }; - if variable_type.keyword == KeywordKind::Val { - Ok(VariableDeclaration::ComptimeValue( - ComptimeValueDeclaration { - val_keyword: variable_type, - identifier, - assignment: Some(assignment), - annotations: VecDeque::new(), - }, - )) - } else { - Ok(VariableDeclaration::Single(SingleVariableDeclaration { - variable_type, + // read identifier + self.stop_at_significant(); + let identifier = self.parse_identifier(handler)?; + + // TODO: allow assignment when map and array literals have been implemented + let assignment = if index.is_none() { + self.try_parse(|p| { + // read equals sign + let equals = p.parse_punctuation('=', true, &VoidHandler)?; + + // read expression + let expression = p.parse_expression(&VoidHandler)?; + + Ok(VariableDeclarationAssignment { equals, expression }) + }) + .ok() + } else { + None + }; + + match index { + Some((open_bracket, IndexingType::IntegerSize(size), close_bracket)) => { + Ok(VariableDeclaration::Array(ArrayVariableDeclaration { + variable_type, + identifier, + open_bracket, + size, + close_bracket, + assignment, + annotations: VecDeque::new(), + })) + } + Some((open_bracket, IndexingType::None, close_bracket)) => { + match variable_type.keyword { + KeywordKind::Int => Ok(VariableDeclaration::Score(ScoreVariableDeclaration { + int_keyword: variable_type, + criteria: criteria_selection, identifier, - assignment: Some(assignment), + open_bracket, + close_bracket, + assignment: None, annotations: VecDeque::new(), - })) + })), + KeywordKind::Bool => Ok(VariableDeclaration::Tag(TagVariableDeclaration { + bool_keyword: variable_type, + identifier, + open_bracket, + close_bracket, + target_assignment: None, + annotations: VecDeque::new(), + })), + _ => unreachable!(), } } - // SingleVariableDeclaration without Assignment - _ => Ok(VariableDeclaration::Single(SingleVariableDeclaration { + None => Ok(VariableDeclaration::Single(SingleVariableDeclaration { variable_type, identifier, - assignment: None, + assignment, annotations: VecDeque::new(), })), } diff --git a/src/transpile/error.rs b/src/transpile/error.rs index fd9f834..c5b7711 100644 --- a/src/transpile/error.rs +++ b/src/transpile/error.rs @@ -398,6 +398,11 @@ pub enum IllegalIndexingReason { /// The length indexed object. length: usize, }, + /// The index provided is invalid + InvalidIndex { + /// The invalid index + index: Span, + }, } impl Display for IllegalIndexingReason { @@ -421,6 +426,9 @@ impl Display for IllegalIndexingReason { "The index {index} is out of bounds for the expression with length {length}." ) } + Self::InvalidIndex { index } => { + write!(f, "The index {index} is invalid.", index = index.str()) + } } } } diff --git a/src/transpile/expression.rs b/src/transpile/expression.rs index d9060f6..d07171b 100644 --- a/src/transpile/expression.rs +++ b/src/transpile/expression.rs @@ -1225,7 +1225,18 @@ impl Transpiler { .parent() .comptime_member_access(member_access, scope, handler) .map_or_else( - |_| todo!("implement non-comptime member access"), + |_| { + // TODO: implement non-comptime access + + let err = TranspileError::IllegalIndexing(IllegalIndexing { + expression: member_access.member().span(), + reason: IllegalIndexingReason::InvalidIndex { + index: member_access.member().span(), + }, + }); + handler.receive(err.clone()); + Err(err) + }, |value| self.store_comptime_value(&value, target, member_access, handler), ), Primary::Lua(lua) => @@ -1794,7 +1805,18 @@ impl Transpiler { .parent() .comptime_member_access(member_access, scope, handler) .map_or_else( - |_| todo!("implement non-comptime member access"), + |_| { + // TODO: implement non-comptime access + + let err = TranspileError::IllegalIndexing(IllegalIndexing { + expression: member_access.member().span(), + reason: IllegalIndexingReason::InvalidIndex { + index: member_access.member().span(), + }, + }); + handler.receive(err.clone()); + Err(err) + }, |value| match value { ComptimeValue::Boolean(b) => { Ok((Vec::new(), ExtendedCondition::Comptime(b)))