change syntax of array declaration: move brackets from after name to after type

This commit is contained in:
Moritz Hölting 2025-08-13 12:58:35 +02:00
parent 3271ca514c
commit d9ae985282
4 changed files with 93 additions and 82 deletions

View File

@ -99,7 +99,7 @@ FunctionParameterList:
```ebnf
ArrayVariableDeclaration:
('int' | 'bool') identifier '[' integer ']' VariableDeclarationAssignment?
('int' | 'bool') '[' integer ']' identifier VariableDeclarationAssignment?
```
## ComptimeValueDeclaration

View File

@ -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<VariableDeclarationAssignment>,
@ -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,10 +1090,18 @@ impl Parser<'_> {
let close_bracket = tree.close;
let inner = tree.tree?;
match inner {
IndexingType::IntegerSize(size) => {
let assignment = self
.try_parse(|p| {
Some((open_bracket, inner, close_bracket))
}
_ => None,
};
// 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)?;
@ -1106,8 +1110,13 @@ impl Parser<'_> {
Ok(VariableDeclarationAssignment { equals, expression })
})
.ok();
.ok()
} else {
None
};
match index {
Some((open_bracket, IndexingType::IntegerSize(size), close_bracket)) => {
Ok(VariableDeclaration::Array(ArrayVariableDeclaration {
variable_type,
identifier,
@ -1118,9 +1127,9 @@ impl Parser<'_> {
annotations: VecDeque::new(),
}))
}
IndexingType::None => match variable_type.keyword {
KeywordKind::Int => {
Ok(VariableDeclaration::Score(ScoreVariableDeclaration {
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,
@ -1128,8 +1137,7 @@ impl Parser<'_> {
close_bracket,
assignment: None,
annotations: VecDeque::new(),
}))
}
})),
KeywordKind::Bool => Ok(VariableDeclaration::Tag(TagVariableDeclaration {
bool_keyword: variable_type,
identifier,
@ -1139,39 +1147,12 @@ impl Parser<'_> {
annotations: VecDeque::new(),
})),
_ => unreachable!(),
},
}
}
// 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 };
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 {
None => Ok(VariableDeclaration::Single(SingleVariableDeclaration {
variable_type,
identifier,
assignment: Some(assignment),
annotations: VecDeque::new(),
}))
}
}
// SingleVariableDeclaration without Assignment
_ => Ok(VariableDeclaration::Single(SingleVariableDeclaration {
variable_type,
identifier,
assignment: None,
assignment,
annotations: VecDeque::new(),
})),
}

View File

@ -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())
}
}
}
}

View File

@ -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)))