rott/rottlib/src/parser/grammar/function/params.rs
dkanus 588790b9b4 Refactor everything
Huge dump of refactored code. Still in the middle of the changes that
are to be squashed later in a one huge monster commit, because there is
no value in anything atomic here.
2026-04-05 20:32:11 +07:00

108 lines
3.7 KiB
Rust

use crate::arena::ArenaVec;
use crate::ast::{AstSpan, Parameter, ParameterModifier, ParameterModifierKind, ParameterRef};
use crate::lexer::{Keyword, Token};
use crate::parser::{ParseErrorKind, ResultRecoveryExt, SyncLevel};
impl<'src, 'arena> crate::parser::Parser<'src, 'arena> {
// allowed to switch to result returning
pub(crate) fn parse_parameter_list(&mut self) -> ArenaVec<'arena, ParameterRef<'src, 'arena>> {
let mut params = self.arena.vec();
if matches!(self.peek_token(), Some(Token::RightParenthesis)) {
return params;
}
loop {
let start_pos = self.last_consumed_position_or_start();
let mut modifiers = self.arena.vec();
while let Some((next_keyword, next_position)) = self.peek_keyword_and_position() {
match next_keyword {
Keyword::Optional => {
modifiers.push(ParameterModifier {
kind: ParameterModifierKind::Optional,
position: next_position,
});
self.advance();
}
Keyword::Out => {
modifiers.push(ParameterModifier {
kind: ParameterModifierKind::Out,
position: next_position,
});
self.advance();
}
Keyword::Coerce => {
modifiers.push(ParameterModifier {
kind: ParameterModifierKind::Coerce,
position: next_position,
});
self.advance();
}
Keyword::Skip => {
modifiers.push(ParameterModifier {
kind: ParameterModifierKind::Skip,
position: next_position,
});
self.advance();
}
_ => break,
}
}
let type_spec = match self.parse_type_specifier() {
Ok(t) => t,
Err(e) => {
self.report_error(e);
self.recover_until(SyncLevel::ListSeparator);
if self.eat(Token::Comma) {
continue;
}
break;
}
};
let name = self
.parse_identifier(ParseErrorKind::ParamMissingIdentifier)
.unwrap_or_fallback(self);
let array_len = match self.parse_array_len_expr() {
Ok(v) => v,
Err(e) => {
self.report_error(e);
self.recover_until(SyncLevel::CloseBracket);
let _ = self.eat(Token::RightBracket);
None
}
};
let default_value = if self.eat(Token::Assign) {
Some(self.parse_expression())
} else {
None
};
let span = AstSpan::range(start_pos, self.last_consumed_position_or_start());
params.push(self.arena.alloc_node(
Parameter {
modifiers,
type_specifier: type_spec,
name,
array_size: array_len,
default_value,
},
span,
));
if !self.eat(Token::Comma) || matches!(self.peek_token(), Some(Token::RightParenthesis))
{
break;
}
self.ensure_forward_progress(start_pos);
}
params
}
}