use super::ast_nodes::TyToken;
use crate::build_error;
use crate::kparser;
use crate::kparser::{KParserError, KParserTracer};
use crate::kproc_macros::KTokenStream;
use crate::rust::ast_nodes::LifetimeParam;
use crate::rust::ast_nodes::TyKind;
use crate::rust::core::check_and_parse_dyn;
use crate::rust::core::check_and_parse_lifetime;
use crate::rust::core::check_and_parse_mut;
use crate::rust::core::check_and_parse_ref;
use crate::trace;
pub fn parse_ty(
stream: &mut KTokenStream,
tracer: &dyn KParserTracer,
) -> kparser::Result<Option<TyToken>> {
let ref_tok = check_and_parse_ref(stream);
let lifetime = check_and_parse_lifetime(stream).map(|lifetime| LifetimeParam {
lifetime_or_label: lifetime,
bounds: Vec::new(),
});
let dyn_tok = check_and_parse_dyn(stream);
let mut_tok = check_and_parse_mut(stream);
let identifier = stream.advance();
trace!(tracer, "type `{identifier}`");
let mut generics: Option<Vec<TyToken>> = None;
if !stream.is_end() {
trace!(
tracer,
"parsing generics `{identifier}<...>`, next tok {}",
stream.peek()
);
let subtypes = parse_recursive_ty(stream, tracer)?;
trace!(tracer, "finish parsing recursive ty: {:?}", subtypes);
if !subtypes.is_empty() {
generics = Some(subtypes);
}
if !stream.is_end() {
let sep = stream.peek().to_owned();
if ![",", ">", ";"].contains(&sep.to_string().as_str()) && !stream.is_group() {
assert!(false, "unexpected separator `{:?}`", sep);
}
if [","].contains(&sep.to_string().as_str()) {
stream.next();
}
}
}
trace!(tracer, "Type `{identifier} with generic `{:?}`", generics);
Ok(Some(TyToken {
identifier,
dyn_tok,
ref_tok,
mut_tok,
lifetime,
generics,
bounds: vec![],
kind: TyKind::NeverType,
}))
}
pub fn parse_recursive_ty(
ast: &mut KTokenStream,
tracer: &dyn KParserTracer,
) -> kparser::Result<Vec<TyToken>> {
let mut types: Vec<TyToken> = vec![];
if ast.match_tok("<") {
ast.next(); while !ast.match_tok(">") {
let ty = parse_ty(ast, tracer)?.ok_or(build_error!(
ast.peek().clone(),
"failing to parse the type, this is a bug, please report it"
))?;
types.push(ty);
}
ast.next(); }
Ok(types)
}