rsleigh 0.4.1

SLEIGH (.slaspec) parser and Rust decoder/P-code emitter codegen — Ghidra-compatible disassembly in pure Rust
Documentation
use nom::combinator::{cut, map, opt};
use nom::multi::many0;
use nom::sequence::{delimited, preceded, terminated, tuple};
use nom::IResult;

use crate::preprocessor::token::Token as ParserToken;

use crate::syntax::define::Endian;
use crate::syntax::parser::{ident, number, this_ident};
use crate::syntax::BitRangeLsbMsb;
use crate::{NumberUnsigned, SleighError, Span};

use super::parse_endian;

#[derive(Clone, Debug)]
pub struct Token {
    pub name: String,
    pub src: Span,
    pub size: NumberUnsigned,
    pub endian: Option<Endian>,
    pub token_fields: Vec<TokenField>,
}

impl Token {
    pub fn parse(input: &[ParserToken]) -> IResult<&[ParserToken], Self, Box<SleighError>> {
        map(
            preceded(
                this_ident("token"),
                cut(tuple((
                    ident,
                    delimited(tag!("("), number, tag!(")")),
                    opt(parse_endian),
                    many0(TokenField::parse),
                ))),
            ),
            |((name, name_span), (size, _), endian, token_fields)| Token {
                name,
                src: name_span.clone(),
                size,
                endian,
                token_fields,
            },
        )(input)
    }
}

#[derive(Clone, Debug)]
pub struct TokenField {
    pub name: String,
    pub name_span: Span,
    pub range: BitRangeLsbMsb,
    pub attributes: Vec<TokenFieldAttribute>,
}

impl TokenField {
    pub fn parse(input: &[ParserToken]) -> IResult<&[ParserToken], Self, Box<SleighError>> {
        map(
            tuple((
                terminated(ident, tag!("=")),
                BitRangeLsbMsb::parse,
                many0(TokenFieldAttribute::parse),
            )),
            |((name, name_span), range, attributes)| TokenField {
                name,
                name_span: name_span.clone(),
                range,
                attributes,
            },
        )(input)
    }
}

#[derive(Clone, Debug, Copy)]
pub enum TokenFieldAttribute {
    Hex,
    Dec,
    Signed,
}

impl TokenFieldAttribute {
    pub(crate) fn from_str(name: &str) -> Option<Self> {
        match name {
            "signed" => Some(Self::Signed),
            "hex" => Some(Self::Hex),
            "dec" => Some(Self::Dec),
            _ => None,
        }
    }
    fn parse(
        input_ori: &[ParserToken],
    ) -> IResult<&[ParserToken], TokenFieldAttribute, Box<SleighError>> {
        let (input, (att, span)) = ident(input_ori)?;
        Self::from_str(&att)
            .map(|att| (input, att))
            .ok_or(nom::Err::Error(Box::new(SleighError::StatementInvalid(
                span.clone(),
            ))))
    }
}