1use super::ast_nodes::TyToken;
4use crate::build_error;
5use crate::kparser;
6use crate::kparser::{KParserError, KParserTracer};
7use crate::kproc_macros::KTokenStream;
8use crate::rust::ast_nodes::LifetimeParam;
9use crate::rust::ast_nodes::TyKind;
10use crate::rust::core::check_and_parse_dyn;
11use crate::rust::core::check_and_parse_lifetime;
12use crate::rust::core::check_and_parse_mut;
13use crate::rust::core::check_and_parse_ref;
14use crate::trace;
15
16pub fn parse_ty(
19 stream: &mut KTokenStream,
20 tracer: &dyn KParserTracer,
21) -> kparser::Result<Option<TyToken>> {
22 let ref_tok = check_and_parse_ref(stream);
23 let lifetime = check_and_parse_lifetime(stream).map(|lifetime| LifetimeParam {
24 lifetime_or_label: lifetime,
25 bounds: Vec::new(),
26 });
27 let dyn_tok = check_and_parse_dyn(stream);
28 let mut_tok = check_and_parse_mut(stream);
29 let identifier = stream.advance();
30 trace!(tracer, "type `{identifier}`");
31 let mut generics: Option<Vec<TyToken>> = None;
38 if !stream.is_end() {
39 trace!(
40 tracer,
41 "parsing generics `{identifier}<...>`, next tok {}",
42 stream.peek()
43 );
44 let subtypes = parse_recursive_ty(stream, tracer)?;
45 trace!(tracer, "finish parsing recursive ty: {:?}", subtypes);
46 if !subtypes.is_empty() {
47 generics = Some(subtypes);
48 }
49
50 if !stream.is_end() {
51 let sep = stream.peek().to_owned();
52
53 if ![",", ">", ";"].contains(&sep.to_string().as_str()) && !stream.is_group() {
55 assert!(false, "unexpected separator `{:?}`", sep);
56 }
57 if [","].contains(&sep.to_string().as_str()) {
63 stream.next();
64 }
65 }
66 }
67
68 trace!(tracer, "Type `{identifier} with generic `{:?}`", generics);
69 Ok(Some(TyToken {
70 identifier,
71 dyn_tok,
72 ref_tok,
73 mut_tok,
74 lifetime,
75 generics,
76 bounds: vec![],
77 kind: TyKind::NeverType,
80 }))
81}
82
83pub fn parse_recursive_ty(
84 ast: &mut KTokenStream,
85 tracer: &dyn KParserTracer,
86) -> kparser::Result<Vec<TyToken>> {
87 let mut types: Vec<TyToken> = vec![];
88 if ast.match_tok("<") {
89 ast.next(); while !ast.match_tok(">") {
91 let ty = parse_ty(ast, tracer)?.ok_or(build_error!(
92 ast.peek().clone(),
93 "failing to parse the type, this is a bug, please report it"
94 ))?;
95 types.push(ty);
96 }
97 ast.next(); }
99 Ok(types)
100}