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.
108 lines
3.7 KiB
Rust
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
|
|
}
|
|
}
|