Skip to main content

xidl_parser/typed_ast/
union.rs

1use super::*;
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Parser, Serialize, Deserialize)]
5pub struct EnumDcl {
6    pub ident: Identifier,
7    pub member: Vec<Enumerator>,
8}
9
10#[derive(Debug, Serialize, Deserialize)]
11pub struct Enumerator {
12    pub annotations: Vec<AnnotationAppl>,
13    pub ident: Identifier,
14}
15
16impl<'a> crate::parser::FromTreeSitter<'a> for Enumerator {
17    fn from_node(
18        node: tree_sitter::Node<'a>,
19        ctx: &mut crate::parser::ParseContext<'a>,
20    ) -> crate::error::ParserResult<Self> {
21        assert_eq!(node.kind_id(), xidl_parser_derive::node_id!("enumerator"));
22        let mut annotations = Vec::new();
23        let mut ident = None;
24        for ch in node.children(&mut node.walk()) {
25            match ch.kind_id() {
26                xidl_parser_derive::node_id!("annotation_appl")
27                | xidl_parser_derive::node_id!("extend_annotation_appl") => {
28                    annotations.push(AnnotationAppl::from_node(ch, ctx)?);
29                }
30                xidl_parser_derive::node_id!("identifier") => {
31                    ident = Some(Identifier::from_node(ch, ctx)?);
32                }
33                _ => {}
34            }
35        }
36        if let Some(doc) = ctx.take_doc_comment(&node) {
37            annotations.insert(0, AnnotationAppl::doc(doc));
38        }
39        Ok(Self {
40            annotations,
41            ident: ident.ok_or_else(|| {
42                crate::error::ParseError::UnexpectedNode(format!(
43                    "parent: {}, got: missing identifier",
44                    node.kind()
45                ))
46            })?,
47        })
48    }
49}
50
51#[derive(Debug, Parser, Serialize, Deserialize)]
52pub enum UnionDcl {
53    UnionDef(UnionDef),
54    UnionForwardDcl(UnionForwardDcl),
55}
56
57#[derive(Debug, Parser, Serialize, Deserialize)]
58pub struct UnionDef {
59    pub ident: Identifier,
60    pub switch_type_spec: SwitchTypeSpec,
61    pub case: Vec<Case>,
62}
63#[derive(Debug, Parser, Serialize, Deserialize)]
64pub struct UnionForwardDcl(pub Identifier);
65
66#[derive(Debug, Parser, Serialize, Deserialize)]
67pub struct Case {
68    pub label: Vec<CaseLabel>,
69    pub element: ElementSpec,
70}
71
72#[derive(Debug, Serialize, Deserialize)]
73pub enum CaseLabel {
74    Case(ConstExpr),
75    Default,
76}
77
78impl<'a> crate::parser::FromTreeSitter<'a> for CaseLabel {
79    fn from_node(
80        node: tree_sitter::Node<'a>,
81        ctx: &mut crate::parser::ParseContext<'a>,
82    ) -> crate::error::ParserResult<Self> {
83        assert_eq!(node.kind_id(), xidl_parser_derive::node_id!("case_label"));
84        for ch in node.children(&mut node.walk()) {
85            if ch.kind_id() == xidl_parser_derive::node_id!("const_expr") {
86                return Ok(Self::Case(ConstExpr::from_node(ch, ctx)?));
87            }
88        }
89
90        let text = ctx.node_text(&node)?.trim();
91        if text.starts_with("default") {
92            return Ok(Self::Default);
93        }
94
95        Err(crate::error::ParseError::UnexpectedNode(format!(
96            "parent: {}, got: missing case label",
97            node.kind()
98        )))
99    }
100}
101
102#[derive(Debug, Serialize, Deserialize)]
103pub struct ElementSpec {
104    pub annotations: Vec<AnnotationAppl>,
105    pub ty: ElementSpecTy,
106    pub value: Declarator,
107}
108
109impl<'a> crate::parser::FromTreeSitter<'a> for ElementSpec {
110    fn from_node(
111        node: tree_sitter::Node<'a>,
112        ctx: &mut crate::parser::ParseContext<'a>,
113    ) -> crate::error::ParserResult<Self> {
114        assert_eq!(node.kind_id(), xidl_parser_derive::node_id!("element_spec"));
115        let mut annotations = vec![];
116        let mut ty = None;
117        let mut value = None;
118        for ch in node.children(&mut node.walk()) {
119            match ch.kind_id() {
120                xidl_parser_derive::node_id!("annotation_appl")
121                | xidl_parser_derive::node_id!("extend_annotation_appl") => {
122                    annotations.push(AnnotationAppl::from_node(ch, ctx)?);
123                }
124                xidl_parser_derive::node_id!("type_spec")
125                | xidl_parser_derive::node_id!("constr_type_dcl") => {
126                    ty = Some(crate::parser::FromTreeSitter::from_node(ch, ctx)?);
127                }
128                xidl_parser_derive::node_id!("declarator") => {
129                    value = Some(crate::parser::FromTreeSitter::from_node(ch, ctx)?);
130                }
131                _ => {}
132            }
133        }
134        if let Some(doc) = ctx.take_doc_comment(&node) {
135            annotations.insert(0, AnnotationAppl::doc(doc));
136        }
137        Ok(Self {
138            annotations,
139            ty: ty.unwrap(),
140            value: value.unwrap(),
141        })
142    }
143}
144
145#[derive(Debug, Parser, Serialize, Deserialize)]
146#[ts(transparent)]
147pub enum ElementSpecTy {
148    TypeSpec(TypeSpec),
149    ConstrTypeDcl(ConstrTypeDcl),
150}
151
152#[derive(Debug, Parser, Serialize, Deserialize)]
153pub enum SwitchTypeSpec {
154    IntegerType(IntegerType),
155    CharType(CharType),
156    WideCharType(WideCharType),
157    BooleanType(BooleanType),
158    ScopedName(ScopedName),
159    OctetType(OctetType),
160}