xidl-parser 0.69.2

A IDL codegen.
Documentation
use serde::{Deserialize, Serialize};
use xidl_parser_derive::Parser;

use crate::typed_ast::Identifier;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConstExpr(pub OrExpr);

impl<'a> crate::parser::FromTreeSitter<'a> for ConstExpr {
    fn from_node(
        node: tree_sitter::Node<'a>,
        ctx: &mut crate::parser::ParseContext<'a>,
    ) -> crate::error::ParserResult<Self> {
        assert_eq!(node.kind_id(), xidl_parser_derive::node_id!("const_expr"));
        let value = node
            .named_children(&mut node.walk())
            .find(|child| child.kind_id() == xidl_parser_derive::node_id!("or_expr"))
            .ok_or_else(|| {
                crate::error::ParseError::UnexpectedNode("const_expr missing or_expr".to_string())
            })?;
        Ok(Self(OrExpr::from_node(value, ctx)?))
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum OrExpr {
    XorExpr(XorExpr),
    OrExpr(Box<OrExpr>, XorExpr),
}

impl<'a> crate::parser::FromTreeSitter<'a> for OrExpr {
    fn from_node(
        node: tree_sitter::Node<'a>,
        ctx: &mut crate::parser::ParseContext<'a>,
    ) -> crate::error::ParserResult<Self> {
        assert_eq!(node.kind_id(), xidl_parser_derive::node_id!("or_expr"));
        let mut values = node
            .named_children(&mut node.walk())
            .filter(|child| child.is_named())
            .collect::<Vec<_>>();
        match values.len() {
            1 => Ok(Self::XorExpr(XorExpr::from_node(values.remove(0), ctx)?)),
            2 => Ok(Self::OrExpr(
                Box::new(OrExpr::from_node(values.remove(0), ctx)?),
                XorExpr::from_node(values.remove(0), ctx)?,
            )),
            _ => Err(crate::error::ParseError::UnexpectedNode(format!(
                "parent: {}, got: {}",
                node.kind(),
                ctx.node_text(&node)?
            ))),
        }
    }
}

#[derive(Debug, Clone, Parser, Serialize, Deserialize)]
pub enum XorExpr {
    AndExpr(AndExpr),
    XorExpr(Box<XorExpr>, AndExpr),
}

#[derive(Debug, Clone, Parser, Serialize, Deserialize)]
pub enum AndExpr {
    ShiftExpr(ShiftExpr),
    AndExpr(Box<AndExpr>, ShiftExpr),
}

#[derive(Debug, Clone, Parser, Serialize, Deserialize)]
pub enum ShiftExpr {
    AddExpr(AddExpr),
    LeftShiftExpr(Box<ShiftExpr>, AddExpr),
    RightShiftExpr(Box<ShiftExpr>, AddExpr),
}

#[derive(Debug, Clone, Parser, Serialize, Deserialize)]
pub enum AddExpr {
    MultExpr(MultExpr),
    AddExpr(Box<AddExpr>, MultExpr),
    SubExpr(Box<AddExpr>, MultExpr),
}

#[derive(Debug, Clone, Parser, Serialize, Deserialize)]
pub enum MultExpr {
    UnaryExpr(UnaryExpr),
    MultExpr(Box<MultExpr>, UnaryExpr),
    DivExpr(Box<MultExpr>, UnaryExpr),
    ModExpr(Box<MultExpr>, UnaryExpr),
}

#[derive(Debug, Clone, Parser, Serialize, Deserialize)]
pub enum UnaryExpr {
    UnaryExpr(UnaryOperator, PrimaryExpr),
    PrimaryExpr(PrimaryExpr),
}

#[derive(Debug, Clone, Parser, Serialize, Deserialize)]
pub enum PrimaryExpr {
    ScopedName(ScopedName),
    Literal(Literal),
    ConstExpr(Box<ConstExpr>),
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum UnaryOperator {
    Add,
    Sub,
    Not,
}

impl<'a> crate::parser::FromTreeSitter<'a> for UnaryOperator {
    fn from_node(
        node: tree_sitter::Node<'a>,
        ctx: &mut crate::parser::ParseContext<'a>,
    ) -> crate::error::ParserResult<Self> {
        #[allow(clippy::never_loop)]
        for ch in node.children(&mut node.walk()) {
            return match ctx.node_text(&ch)? {
                "+" => Ok(Self::Add),
                "-" => Ok(Self::Sub),
                "~" => Ok(Self::Not),
                _ => Err(crate::error::ParseError::UnexpectedNode(format!(
                    "parent: {}, got: {}",
                    node.kind(),
                    ch.kind()
                ))),
            };
        }
        unreachable!()
    }
}

#[derive(Debug, Clone, Parser, Serialize, Deserialize)]
pub struct ScopedName {
    #[ts(id = "scoped_name")]
    pub scoped_name: Option<Box<ScopedName>>,
    pub identifier: Identifier,
    #[ts(id = "-", text)]
    pub node_text: String,
}

#[derive(Debug, Clone, Parser, Serialize, Deserialize)]
pub enum Literal {
    IntegerLiteral(IntegerLiteral),
    FloatingPtLiteral(FloatingPtLiteral),
    // FixedPtLiteral,
    CharLiteral(String),
    WideCharacterLiteral(String),
    StringLiteral(String),
    WideStringLiteral(String),
    BooleanLiteral(BooleanLiteral),
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum BooleanLiteral {
    True,
    False,
}

impl BooleanLiteral {
    pub fn as_bool(&self) -> bool {
        matches!(self, Self::True)
    }
}

impl<'a> crate::parser::FromTreeSitter<'a> for BooleanLiteral {
    fn from_node(
        node: tree_sitter::Node<'a>,
        ctx: &mut crate::parser::ParseContext<'a>,
    ) -> crate::error::ParserResult<Self> {
        match ctx.node_text(&node)?.to_ascii_lowercase().as_str() {
            "true" => Ok(Self::True),
            "false" => Ok(Self::False),
            value => Err(crate::error::ParseError::UnexpectedNode(format!(
                "parent: {}, got: {}",
                node.kind(),
                value
            ))),
        }
    }
}

#[derive(Debug, Clone, Parser, Serialize, Deserialize)]
pub enum IntegerLiteral {
    BinNumber(String),
    OctNumber(String),
    DecNumber(String),
    HexNumber(String),
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FloatingPtLiteral {
    pub sign: Option<IntegerSign>,
    pub integer: DecNumber,
    pub fraction: DecNumber,
}

impl<'a> crate::parser::FromTreeSitter<'a> for FloatingPtLiteral {
    fn from_node(
        node: tree_sitter::Node<'a>,
        ctx: &mut crate::parser::ParseContext<'a>,
    ) -> crate::error::ParserResult<Self> {
        assert_eq!(
            node.kind_id(),
            xidl_parser_derive::node_id!("floating_pt_literal")
        );
        let mut sign = None;
        let mut integer = None;
        let mut fraction = None;
        for ch in node.children(&mut node.walk()) {
            match ch.kind_id() {
                xidl_parser_derive::node_id!("integer_sign") => {
                    sign = Some(crate::parser::FromTreeSitter::from_node(ch, ctx)?);
                }
                xidl_parser_derive::node_id!("dec_number") => {
                    let inter = crate::parser::FromTreeSitter::from_node(ch, ctx)?;
                    if integer.is_none() {
                        integer = Some(inter);
                    } else {
                        fraction = Some(inter);
                    }
                }

                _ => {}
            }
        }
        Ok(Self {
            sign,
            integer: integer.unwrap(),
            fraction: fraction.unwrap(),
        })
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum IntegerSign {
    Plus,
    Minus,
}

impl IntegerSign {
    pub fn as_str(&self) -> &'static str {
        match self {
            Self::Plus => "+",
            Self::Minus => "-",
        }
    }
}

impl<'a> crate::parser::FromTreeSitter<'a> for IntegerSign {
    fn from_node(
        node: tree_sitter::Node<'a>,
        ctx: &mut crate::parser::ParseContext<'a>,
    ) -> crate::error::ParserResult<Self> {
        let text = ctx.node_text(&node)?;
        match text {
            "+" => Ok(Self::Plus),
            "-" => Ok(Self::Minus),
            _ => Err(crate::error::ParseError::UnexpectedNode(format!(
                "parent: {}, got: {}",
                node.kind(),
                text
            ))),
        }
    }
}

#[derive(Debug, Clone, Parser, Serialize, Deserialize)]
#[ts(transparent)]
pub struct DecNumber(pub String);