rudy_dwarf/parser/
mod.rs

1//! Parser combinator framework for DWARF type resolution
2//!
3//! This module provides a composable way to parse DWARF debug information
4//! and extract type layout information. It aims to replace the brittle
5//! manual field traversal with a more robust and reusable approach.
6
7use crate::{
8    parser::combinators::{Filter, MapWithDbAndEntry},
9    Die, DwarfDb,
10};
11
12// Module structure
13pub mod btreemap;
14pub mod children;
15pub mod combinators;
16pub mod enums;
17pub mod functions;
18pub mod hashmap;
19pub mod option;
20pub mod pointers;
21pub mod primitives;
22pub mod result;
23pub mod vec;
24
25use combinators::{And, Context, Map, MapRes, Then};
26/// Type alias for parser results
27pub type Result<T> = anyhow::Result<T>;
28
29/// Core parser trait that all combinators implement
30pub trait Parser<T> {
31    fn parse(&self, db: &dyn DwarfDb, entry: Die) -> Result<T>;
32
33    /// Combine this parser with another, applying both and combining results
34    fn and<U, P>(self, other: P) -> And<Self, P, T, U>
35    where
36        Self: Sized,
37        P: Parser<U>,
38    {
39        And {
40            first: self,
41            second: other,
42            _marker: std::marker::PhantomData,
43        }
44    }
45
46    /// Turns the input into an optional output
47    /// if the provided parser succeeds
48    fn filter(self) -> Filter<Self>
49    where
50        Self: Sized,
51    {
52        Filter { parser: self }
53    }
54
55    /// Transform the output of this parser
56    ///
57    /// Supports both simple transformations.
58    ///
59    /// For more complex transformations that require access to the database or entry,
60    /// use `map_with_db` or `map_with_db_and_entry`.
61    fn map<U, F>(self, f: F) -> Map<Self, F, T>
62    where
63        Self: Sized,
64        F: Fn(T) -> U,
65    {
66        Map {
67            parser: self,
68            f,
69            _marker: std::marker::PhantomData,
70        }
71    }
72
73    fn map_with_entry<U, F>(self, f: F) -> MapWithDbAndEntry<Self, F, T>
74    where
75        Self: Sized,
76        F: Fn(&dyn DwarfDb, Die, T) -> U,
77    {
78        MapWithDbAndEntry {
79            parser: self,
80            f,
81            _marker: std::marker::PhantomData,
82        }
83    }
84
85    /// Transform the output of this parser
86    fn map_res<U, F>(self, f: F) -> MapRes<Self, F, T>
87    where
88        Self: Sized,
89        F: Fn(T) -> Result<U>,
90    {
91        MapRes {
92            parser: self,
93            f,
94            _marker: std::marker::PhantomData,
95        }
96    }
97
98    /// Chain this parser with another, where the second operates on the first's result
99    fn then<U, P, V>(self, next: P) -> Then<Self, P, V>
100    where
101        Self: Sized + Parser<V>,
102        P: Parser<U>,
103    {
104        Then {
105            first: self,
106            second: next,
107            _marker: std::marker::PhantomData,
108        }
109    }
110
111    /// Add context to errors from this parser
112    fn context<S: Into<String>>(self, ctx: S) -> Context<Self>
113    where
114        Self: Sized,
115    {
116        Context {
117            parser: self,
118            context: ctx.into(),
119        }
120    }
121}
122
123impl<T, P> Parser<T> for &'_ P
124where
125    P: Parser<T>,
126{
127    fn parse(&self, db: &dyn DwarfDb, entry: Die) -> Result<T> {
128        <P as Parser<T>>::parse(self, db, entry)
129    }
130}
131
132pub struct FromFn<F> {
133    f: F,
134}
135
136pub fn from_fn<F>(f: F) -> FromFn<F> {
137    FromFn { f }
138}
139
140// Functions matching the `Parser::parse` signature
141// are automatically parsers
142impl<T, F, E> Parser<T> for FromFn<F>
143where
144    F: Fn(&dyn DwarfDb, Die) -> std::result::Result<T, E>,
145    E: Into<anyhow::Error>,
146{
147    fn parse(&self, db: &dyn DwarfDb, entry: Die) -> Result<T> {
148        (self.f)(db, entry).map_err(Into::into)
149    }
150}