kproc_parser/rust/
kstruct.rs

1//! API to parse the rust struct provided as
2//! TokenStream.
3use std::collections::HashMap;
4
5use crate::kparser::{KParserError, KParserTracer};
6use crate::kproc_macros::KTokenStream;
7use crate::rust::ast_nodes::{FieldToken, StructToken};
8use crate::rust::ty::parse_ty;
9use crate::{build_error, check, parse_visibility, trace};
10
11use super::core::*;
12use super::kattr::check_and_parse_cond_attribute;
13
14/// parsing a rust data structure inside a AST that will be easy to
15/// manipulate and use by a compiler
16pub fn parse_struct(
17    stream: &mut KTokenStream,
18    tracer: &dyn KParserTracer,
19) -> Result<StructToken, KParserError> {
20    let attrs = check_and_parse_cond_attribute(stream, tracer);
21    let visibility = parse_visibility!(stream);
22    let tok = stream.advance();
23    check!("struct", tok)?;
24
25    let name = stream.advance();
26    let generics = check_and_parse_generics_params(stream, tracer)?;
27
28    let mut group = stream.to_ktoken_stream();
29    let fields = parse_struct_fields(&mut group, tracer)?;
30
31    let struct_tok = StructToken {
32        attrs,
33        visibility,
34        name,
35        fields,
36        generics,
37    };
38    trace!(tracer, "`parse_struct` result {:#?}", struct_tok);
39    Ok(struct_tok)
40}
41
42pub fn parse_struct_fields(
43    ast: &mut KTokenStream,
44    tracer: &dyn KParserTracer,
45) -> Result<Vec<FieldToken>, KParserError> {
46    let mut fields = vec![];
47    while !ast.is_end() {
48        let attr = check_and_parse_cond_attribute(ast, tracer);
49        trace!(tracer, "after token {:?}", ast.peek());
50        let mut field = parse_struct_ty(ast, tracer)?;
51        field.attrs.extend(attr);
52        fields.push(field);
53    }
54    Ok(fields)
55}
56
57pub fn parse_struct_ty(
58    ast: &mut KTokenStream,
59    tracer: &dyn KParserTracer,
60) -> Result<FieldToken, KParserError> {
61    // name filed
62    let visibility = parse_visibility!(ast);
63    let field_name = ast.advance();
64    let separator = ast.advance();
65    check!(":", separator)?;
66
67    let ty = parse_ty(ast, tracer)?.ok_or(build_error!(
68        separator,
69        "failing to parse a type, it may be a Trait Bound so please report a bug"
70    ))?;
71    trace!(tracer, "top type field: {ty}");
72
73    let field = FieldToken {
74        visibility,
75        identifier: field_name,
76        ty,
77        attrs: HashMap::new(),
78    };
79    Ok(field)
80}