kproc_parser/rust/
ty.rs

1//! Type parser to allow a more flexible
2//! parser.
3use 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
16/// parse the field type as an AST element, and return the type field,
17/// if found, otherwise if the type is a Trait bound return None.
18pub 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    // in the case of the function parameters here  we ca be
32    // at the end of the stream
33    //
34    // In addition the basics types do not need
35    // the generics check, and in the case of EOF
36    // checking the generic will panic the parser.
37    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            // token allowed as stop words for the type parser
54            if ![",", ">", ";"].contains(&sep.to_string().as_str()) && !stream.is_group() {
55                assert!(false, "unexpected separator `{:?}`", sep);
56            }
57            // token to consume, but in this case
58            // we do not consume the `>`
59            // because we are in a recursive call,
60            // and the token is a stop word for the
61            // root recursive call.
62            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        // FIXME: try to understnad how to parse the `TyKind` or if we
78        // really need it.
79        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(); // consume `<``
90        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(); // consume the `>` toks
98    }
99    Ok(types)
100}