use super::super::*;
use super::pack::TypeParameters;
impl<'source, 'ast, 'name, 'names> Parser<'source, 'ast, 'name, 'names>
where
'name: 'ast,
{
pub(in crate::parser) fn parse_optional_generic_parameters(
&mut self,
with_default_values: bool,
) -> Result<ParsedGenericParameters<'ast>> {
if self.current.kind() == TokenKind::Less {
if self.cst.enabled() {
self.parse_generic_parameters_with_cst(with_default_values)
} else {
self.parse_generic_parameters(with_default_values)
}
} else {
Ok(ParsedGenericParameters::default())
}
}
pub(in crate::parser) fn parse_generic_parameters_with_cst(
&mut self,
with_default_values: bool,
) -> Result<ParsedGenericParameters<'ast>> {
let less_location = self.current_location();
let open = self.current_position();
let mut commas = self.temp_positions();
self.expect_and_consume(Token::Less, "generic parameters");
let mut seen_pack = false;
let mut seen_default = false;
let mut types = self.temp_generic_types();
let mut type_packs = self.temp_generic_type_packs();
loop {
let name_location = self.current_token_location();
let name = if let Token::Ident(name) = self.current {
self.advance();
name
} else {
self.report_parse_error(self.generic_parameter_name_error());
self.name_error
};
let is_pack = self.current.kind() == TokenKind::Ellipsis;
if is_pack || seen_pack {
let mut ellipsis = Position::missing();
if !is_pack {
self.report_parse_error(
self.located("Generic types come before generic type packs"),
);
} else {
ellipsis = self.current_position();
self.advance();
}
seen_pack = true;
let mut default_equals = None;
let default_value =
if with_default_values && self.current.kind() == TokenKind::Equal {
seen_default = true;
let equals = self.current_position();
default_equals = Some(equals);
self.advance();
self.parse_generic_type_pack_default()?
} else if seen_default {
self.report_parse_error(
self.located("Expected default type pack after type pack name"),
);
None
} else {
None
};
type_packs.push_back(self.alloc_generic_type_pack_with_cst(
GenericTypePack {
location: name_location,
name,
default_value,
},
self.cst_node(|| {
CstNode::GenericTypePack(CstGenericTypePack {
ellipsis,
default_equals,
})
}),
));
} else if with_default_values && self.current.kind() == TokenKind::Equal {
seen_default = true;
let equals = self.current_position();
self.advance();
let default_value = self.parse_type_annotation()?;
types.push_back(self.alloc_generic_type_with_cst(
GenericType {
location: name_location,
name,
default_value: Some(default_value),
},
self.cst_node(|| {
CstNode::GenericType(CstGenericType {
default_equals: Some(equals),
})
}),
));
} else if seen_default {
self.report_parse_error(self.located("Expected default type after type name"));
types.push_back(self.alloc_generic_type_with_cst(
GenericType {
location: name_location,
name,
default_value: None,
},
self.cst_node(|| {
CstNode::GenericType(CstGenericType {
default_equals: None,
})
}),
));
} else {
types.push_back(self.alloc_generic_type_with_cst(
GenericType {
location: name_location,
name,
default_value: None,
},
self.cst_node(|| {
CstNode::GenericType(CstGenericType {
default_equals: None,
})
}),
));
}
match self.current {
Token::Comma => {
commas.push_back(self.current_position());
self.advance();
if self.current.kind() == TokenKind::Greater {
self.report_parse_error(
self.located("Expected type after ',' but got '>' instead"),
);
let close = self.current_position();
self.advance();
return Ok(ParsedGenericParameters {
types: types.as_slice().to_vec(),
type_packs: type_packs.as_slice().to_vec(),
open,
commas: commas.as_slice().to_vec(),
close,
});
}
}
Token::Greater => {
let close = self.current_position();
self.advance();
return Ok(ParsedGenericParameters {
types: types.as_slice().to_vec(),
type_packs: type_packs.as_slice().to_vec(),
open,
commas: commas.as_slice().to_vec(),
close,
});
}
_ => {
let close = if self.expect_match_token(
Token::Greater,
">",
"<",
less_location,
false,
) {
self.previous_token_location().begin
} else {
Position::missing()
};
return Ok(ParsedGenericParameters {
types: types.as_slice().to_vec(),
type_packs: type_packs.as_slice().to_vec(),
open,
commas: commas.as_slice().to_vec(),
close,
});
}
}
}
}
pub(in crate::parser) fn parse_generic_parameters(
&mut self,
with_default_values: bool,
) -> Result<ParsedGenericParameters<'ast>> {
let less_location = self.current_location();
self.expect_and_consume(Token::Less, "generic parameters");
let mut seen_pack = false;
let mut seen_default = false;
let mut types = self.temp_generic_types();
let mut type_packs = self.temp_generic_type_packs();
loop {
let name_location = self.current_token_location();
let name = if let Token::Ident(name) = self.current {
self.advance();
name
} else {
self.report_parse_error(self.generic_parameter_name_error());
self.name_error
};
let is_pack = self.current.kind() == TokenKind::Ellipsis;
if is_pack || seen_pack {
if !is_pack {
self.report_parse_error(
self.located("Generic types come before generic type packs"),
);
} else {
self.advance();
}
seen_pack = true;
let default_value =
if with_default_values && self.current.kind() == TokenKind::Equal {
seen_default = true;
self.advance();
self.parse_generic_type_pack_default()?
} else if seen_default {
self.report_parse_error(
self.located("Expected default type pack after type pack name"),
);
None
} else {
None
};
type_packs.push_back(self.alloc_generic_type_pack_with_cst(
GenericTypePack {
location: name_location,
name,
default_value,
},
None,
));
} else if with_default_values && self.current.kind() == TokenKind::Equal {
seen_default = true;
self.advance();
let default_value = self.parse_type_annotation()?;
types.push_back(self.alloc_generic_type_with_cst(
GenericType {
location: name_location,
name,
default_value: Some(default_value),
},
None,
));
} else if seen_default {
self.report_parse_error(self.located("Expected default type after type name"));
types.push_back(self.alloc_generic_type_with_cst(
GenericType {
location: name_location,
name,
default_value: None,
},
None,
));
} else {
types.push_back(self.alloc_generic_type_with_cst(
GenericType {
location: name_location,
name,
default_value: None,
},
None,
));
}
match self.current {
Token::Comma => {
self.advance();
if self.current.kind() == TokenKind::Greater {
self.report_parse_error(
self.located("Expected type after ',' but got '>' instead"),
);
self.advance();
return Ok(ParsedGenericParameters {
types: types.as_slice().to_vec(),
type_packs: type_packs.as_slice().to_vec(),
open: Position::missing(),
commas: Vec::new(),
close: Position::missing(),
});
}
}
Token::Greater => {
self.advance();
return Ok(ParsedGenericParameters {
types: types.as_slice().to_vec(),
type_packs: type_packs.as_slice().to_vec(),
open: Position::missing(),
commas: Vec::new(),
close: Position::missing(),
});
}
_ => {
self.expect_match_token(Token::Greater, ">", "<", less_location, false);
return Ok(ParsedGenericParameters {
types: types.as_slice().to_vec(),
type_packs: type_packs.as_slice().to_vec(),
open: Position::missing(),
commas: Vec::new(),
close: Position::missing(),
});
}
}
}
}
pub(in crate::parser) fn parse_generic_type_pack_default(
&mut self,
) -> Result<Option<TypePack<'ast>>> {
let ident_starts_type_pack =
matches!(self.current, Token::Ident(_)) && self.peek().kind() == TokenKind::Ellipsis;
match self.current {
Token::Ellipsis => {
let annotation = self.parse_type_pack()?;
Ok(Some(annotation))
}
Token::Ident(_) if ident_starts_type_pack => {
let annotation = self.parse_type_pack()?;
Ok(Some(annotation))
}
Token::Greater => {
let start = self.previous_token_end_position();
self.report_parse_error(self.error_at(
Location::new(start, self.current_token_location().end),
"Expected type, got '>'",
));
let message_index = self.report_parse_error(self.error_at(
Location::new(start, self.current_position()),
"Expected type pack after '=', got type",
));
let _ = message_index;
Ok(None)
}
_ => match self.parse_simple_type_or_pack()? {
TypeOrPack::Pack(pack) => Ok(Some(pack)),
TypeOrPack::Type(annotation) => {
self.report_parse_error(self.error_at(
annotation.location,
"Expected type pack after '=', got type",
));
Ok(None)
}
},
}
}
pub(in crate::parser) fn parse_explicit_type_instantiation(
&mut self,
) -> Result<ExplicitTypeInstantiation<'ast>> {
let begin = self.current_token_location();
let mut instantiation = self.cst.enabled().then(|| CstTypeInstantiation {
left_arrow_1: self.current_position(),
..CstTypeInstantiation::default()
});
self.advance();
let TypeParameters {
arguments,
open,
commas,
close,
} = self.parse_type_parameters_with_cst()?;
let end_location = self.current_token_location();
if let Some(instantiation) = &mut instantiation {
instantiation.left_arrow_2 = open;
instantiation.comma_positions = commas;
instantiation.right_arrow_1 = close;
if self.current.kind() == TokenKind::Greater {
instantiation.right_arrow_2 = self.current_position();
}
}
self.expect_match_token(Token::Greater, ">", "<", begin, false);
Ok(ExplicitTypeInstantiation {
arguments,
cst: instantiation,
end_location,
})
}
}
pub(in crate::parser) struct ExplicitTypeInstantiation<'ast> {
pub(in crate::parser) arguments: Vec<TypeOrPack<'ast>>,
pub(in crate::parser) cst: Option<CstTypeInstantiation>,
pub(in crate::parser) end_location: Location,
}