Skip to main content

pliron/
parsable.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) The pliron contributors
3
4//! IR objects that can be parsed from their text representation.
5
6use alloc::{boxed::Box, string::String, vec, vec::Vec};
7use core::any::Any;
8use thiserror::Error;
9
10use crate::{
11    basic_block::BasicBlock,
12    builtin::{
13        op_interfaces::{IsolatedFromAboveInterface, OneResultInterface},
14        ops::ForwardRefOp,
15    },
16    combine::{
17        Parser, Positioned, StreamOnce, choice,
18        easy::{self, Errors, ParseError},
19        error::{StdParseResult2, Tracked},
20        parser::char::string,
21        stream::{
22            self, IteratorStream, buffered,
23            position::{self, SourcePosition},
24            state::Stream,
25        },
26    },
27    context::{Context, Ptr},
28    identifier::Identifier,
29    input_err,
30    irfmt::parsers::{hex_int_parser, int_parser, quoted_string_parser},
31    location::{self, Located, Location, Source},
32    op::op_impls,
33    operation::Operation,
34    result::{self, Result},
35    std_deps::{fs::File, io::BufReader, path::Path, utf8_chars::BufReadCharsExt},
36    utils::table::{
37        HMap,
38        itable::{Entry, IMap},
39    },
40    value::{DefiningEntity, Value},
41};
42
43/// State during parsing of any [Parsable] object.
44/// Every parser implemented using [Parsable] will be passed
45/// a mutable reference (wrapped with [StateStream]) to this state.
46pub struct State<'a> {
47    /// The [Context] in which the parsing is being done.
48    pub ctx: &'a mut Context,
49    /// The [NameTracker] for this parsing session.
50    pub(crate) name_tracker: NameTracker,
51    /// The [Source] from which the input is being read.
52    pub src: Source,
53    /// Aribtrary state data that different parsers may want to use.
54    pub aux_data: HMap<Identifier, Box<dyn Any>>,
55}
56
57impl<'a> State<'a> {
58    /// Create a new empty [State].
59    pub fn new(ctx: &'a mut Context, src: Source) -> State<'a> {
60        State {
61            ctx,
62            name_tracker: NameTracker::default(),
63            src,
64            aux_data: HMap::default(),
65        }
66    }
67}
68
69/// A wrapper around any [char] [Iterator] object.
70/// Buffering and positioning are automatically handled hereafter.
71pub struct CharIterator<'a>(Box<dyn Iterator<Item = char> + 'a>);
72
73impl Iterator for CharIterator<'_> {
74    type Item = char;
75
76    fn next(&mut self) -> Option<Self::Item> {
77        self.0.next()
78    }
79}
80
81/// A [State]ful [Stream]. Every [Parsable::parser] gets this as input,
82/// allowing for the parser to have access to a state.
83pub type StateStream<'a> = Stream<
84    buffered::Stream<
85        easy::Stream<
86            stream::position::Stream<stream::IteratorStream<CharIterator<'a>>, SourcePosition>,
87        >,
88    >,
89    State<'a>,
90>;
91
92impl Located for StateStream<'_> {
93    fn loc(&self) -> location::Location {
94        location::Location::SrcPos {
95            src: self.state.src,
96            pos: self.position(),
97        }
98    }
99
100    fn set_loc(&mut self, _loc: Location) {
101        panic!("Cannot set location of parser");
102    }
103}
104
105pub type ParseResult<'a, T> = StdParseResult2<T, <StateStream<'a> as StreamOnce>::Error>;
106
107/// Any object that can be parsed from its [Printable](crate::printable::Printable) text.
108///
109/// Implement [parse](Parsable::parse) and call [parser](Parsable::parser)
110/// to get a parser combinator that can be combined with any other parser
111/// from the [combine] library.
112///
113/// The [parse](Parsable::parse) function may take arguments whose type is
114/// specified and constrained by the associated type [Parsable::Arg].
115/// Example:
116/// ```
117/// use pliron::combine::{
118///     Parser, Stream, StreamOnce, easy, stream::position,
119///     parser::char::digit, many1
120/// };
121/// use pliron::{context::Context, parsable::
122///     { state_stream_from_iterator, StateStream, Parsable, State, ParseResult},
123///     location::Source,
124/// };
125/// #[derive(PartialEq, Eq)]
126/// struct Number { n: u64 }
127/// impl Parsable for Number {
128///     type Arg = ();
129///     type Parsed = Number;
130///     fn parse<'a>(
131///         state_stream: &mut StateStream<'a>,
132///         arg: Self::Arg,
133///     ) -> ParseResult<'a, Self::Parsed> {
134///         many1::<String, _, _>(digit())
135///         .map(|digits| {
136///             let _ : &mut Context = state_stream.state.ctx;
137///             Number { n: digits.parse::<u64>().unwrap() }
138///         })
139///         .parse_stream(&mut state_stream.stream).into()
140///     }
141/// }
142/// let mut ctx = Context::new();
143/// let state_stream = state_stream_from_iterator("100".chars(), State::new(&mut ctx, Source::InMemory));
144/// assert!(Number::parser(()).parse(state_stream).unwrap().0 == Number { n: 100 });
145///
146/// ```
147pub trait Parsable {
148    /// Type of the argument that must be passed to the parser.
149    type Arg: Clone + 'static;
150    /// The type of the parsed entity.
151    type Parsed;
152
153    /// Define a parser using existing combinators and call
154    /// `into` on [Parser::parse_stream] to get the final [ParseResult].
155    /// Use [state_stream.state](StateStream::state) as necessary.
156    fn parse<'a>(
157        state_stream: &mut StateStream<'a>,
158        arg: Self::Arg,
159    ) -> ParseResult<'a, Self::Parsed>;
160
161    /// Get a parser combinator that can work on [StateStream] as its input.
162    fn parser<'a>(
163        arg: Self::Arg,
164    ) -> Box<dyn Parser<StateStream<'a>, Output = Self::Parsed, PartialState = ()> + 'a>
165    where
166        Self::Parsed: 'a,
167    {
168        parser_combinator(Self::parse, arg)
169    }
170}
171
172/// Build a parser combinator from a [Parsable::parse] function and its argument.
173#[inline(never)]
174pub fn parser_combinator<'a, Arg: Clone + 'static, Output: 'a>(
175    parse: fn(&mut StateStream<'a>, Arg) -> ParseResult<'a, Output>,
176    args: Arg,
177) -> Box<dyn Parser<StateStream<'a>, Output = Output, PartialState = ()> + 'a> {
178    combine::parser(move |state_stream| parse(state_stream, args.clone())).boxed()
179}
180
181/// Build a [StateStream] from an iterator, for use with [Parsable].
182///
183/// Examples:
184///
185/// 1. Creating a [StateStream] from a string input:
186/// ```
187/// use pliron::{
188///     combine::Parser,
189///     context::{Context, Ptr},
190///     location::Source,
191///     operation::Operation,
192///     parsable::{state_stream_from_iterator, State},
193/// };
194///
195/// let mut ctx = Context::new();
196/// let source = Source::InMemory;
197/// let input = "builtin.module @m {}";
198/// let state_stream =
199///     state_stream_from_iterator(input.chars(), State::new(&mut ctx, source));
200/// let (_parsed_res, _): (Ptr<Operation>, _) =
201///     Operation::top_level_parser().parse(state_stream).unwrap();
202/// ```
203///
204/// 2. Creating a [StateStream] from a file input:
205/// ```no_run
206/// use pliron::{
207///     combine::Parser,
208///     context::{Context, Ptr},
209///     location::Source,
210///     operation::Operation,
211///     parsable::{state_stream_from_iterator, State},
212/// };
213///
214/// fn main() {
215///     let mut ctx = Context::new();
216///     let plir_path = std::path::PathBuf::from("input.plir");
217///     let plir_file = std::fs::File::open(&plir_path).unwrap();
218///     let mut plir_file = std::io::BufReader::new(plir_file);
219///
220///     // Use the `BufReadCharsExt` trait to read chars from the file.
221///     use utf8_chars::BufReadCharsExt;
222///     let chars_iter = plir_file.chars().map(|c| {
223///         c.inspect_err(|e| eprint!("Error reading chars from file: {e}"))
224///             .unwrap()
225///     });
226///
227///     let source = Source::new_from_file(&ctx, plir_path);
228///     let state_stream = state_stream_from_iterator(chars_iter, State::new(&mut ctx, source));
229///     let (_parsed_res, _) : (Ptr<Operation>, _) =
230///         Operation::top_level_parser().parse(state_stream).unwrap();
231/// }
232/// ```
233pub fn state_stream_from_iterator<'a, T: Iterator<Item = char> + 'a>(
234    input: T,
235    state: State<'a>,
236) -> StateStream<'a> {
237    StateStream {
238        stream: buffered::Stream::new(
239            easy::Stream::from(position::Stream::with_positioner(
240                IteratorStream::new(CharIterator(Box::new(input))),
241                SourcePosition::default(),
242            )),
243            100,
244        ),
245        state,
246    }
247}
248
249/// Run a [Parser] on a string input.
250/// Example:
251/// ```
252/// use pliron::{context::Context, parsable::{parse_from_str, Parsable}};
253/// use pliron::derive::format;
254/// #[format("$n")]
255/// struct Number { n: u64 }
256/// let mut ctx = Context::new();
257/// let parsed_res = parse_from_str(Number::parser(()), &mut ctx, "100").unwrap();
258/// assert!(parsed_res.n == 100);
259/// ```
260pub fn parse_from_str<'a, P: Parser<StateStream<'a>>>(
261    mut parser: P,
262    ctx: &'a mut Context,
263    input: &'a str,
264) -> Result<P::Output> {
265    let source = location::Source::InMemory;
266    let state_stream = state_stream_from_iterator(input.chars(), State::new(ctx, source));
267    match parser.parse(state_stream) {
268        Ok((parsed_res, _)) => Ok(parsed_res),
269        Err(err) => {
270            let loc = Location::SrcPos {
271                src: source,
272                pos: err.position,
273            };
274            input_err!(loc, err)
275        }
276    }
277}
278
279/// Run a [Parser] on a file input.
280/// Example:
281/// ```no_run
282/// use pliron::{context::Context, parsable::{parse_from_file, Parsable}, std_deps::path::PathBuf};
283/// use pliron::derive::format;
284/// #[format("$n")]
285/// struct Number { n: u64 }
286/// let mut ctx = Context::new();
287/// let parsed_res = parse_from_file(
288///     Number::parser(()),
289///     &mut ctx,
290///     &PathBuf::from("input.plir"),
291/// ).unwrap();
292/// assert!(parsed_res.n == 100);
293/// ```
294pub fn parse_from_file<'a, P: Parser<StateStream<'a>>>(
295    mut parser: P,
296    ctx: &'a mut Context,
297    path: &'a Path,
298) -> Result<P::Output> {
299    let source = location::Source::new_from_file(ctx, path);
300
301    // An owned iterator over the file's chars, to please the borrow checker.
302    struct FileChars<'a> {
303        reader: BufReader<File>,
304        path: &'a Path,
305    }
306
307    impl Iterator for FileChars<'_> {
308        type Item = char;
309
310        fn next(&mut self) -> Option<char> {
311            self.reader
312                .read_char()
313                .inspect_err(|e| {
314                    log::error!(
315                        "Error reading chars from file {}: {}",
316                        self.path.display(),
317                        e
318                    )
319                })
320                .unwrap()
321        }
322    }
323
324    // Parse the plir file and verify it.
325    let plir_file = File::open(path).unwrap();
326    let chars_iter = FileChars {
327        reader: BufReader::new(plir_file),
328        path,
329    };
330
331    let state_stream = state_stream_from_iterator(chars_iter, State::new(ctx, source));
332
333    match parser.parse(state_stream) {
334        Ok((parsed_res, _)) => Ok(parsed_res),
335        Err(err) => {
336            let loc = Location::SrcPos {
337                src: source,
338                pos: err.position,
339            };
340            input_err!(loc, err)
341        }
342    }
343}
344
345/// Convert [Result] into [StdParseResult2].
346/// Enables using `?` on [Result] during parsing.
347pub trait IntoParseResult<'a, T> {
348    fn into_parse_result(self) -> StdParseResult2<T, <StateStream<'a> as StreamOnce>::Error>;
349}
350
351impl<'a, T> IntoParseResult<'a, T> for Result<T> {
352    fn into_parse_result(self) -> StdParseResult2<T, <StateStream<'a> as StreamOnce>::Error> {
353        match self {
354            Ok(t) => combine::ParseResult::CommitOk(t),
355            Err(e) => combine::ParseResult::CommitErr(e.into()),
356        }
357        .into()
358    }
359}
360
361impl From<result::Error> for ParseError<StateStream<'_>> {
362    fn from(value: result::Error) -> Self {
363        let position = if let Location::SrcPos { pos, .. } = value.loc {
364            pos
365        } else {
366            SourcePosition::default()
367        };
368        easy::Errors::from_errors(position, vec![easy::Error::Other(value.err)])
369    }
370}
371
372impl From<result::Error> for combine::error::Commit<Tracked<Errors<char, char, SourcePosition>>> {
373    fn from(value: result::Error) -> Self {
374        let res: StdParseResult2<(), ParseError<StateStream<'_>>> =
375            combine::ParseResult::CommitErr(value.into()).into();
376        res.err().unwrap()
377    }
378}
379
380/// Serves a similar purpose to what [ForwardRefOp] serves for SSA names.
381enum LabelRef {
382    ForwardRef(Ptr<BasicBlock>),
383    Defined(Ptr<BasicBlock>),
384}
385
386impl LabelRef {
387    fn get_label(&self) -> Ptr<BasicBlock> {
388        match self {
389            LabelRef::ForwardRef(label) => *label,
390            LabelRef::Defined(label) => *label,
391        }
392    }
393}
394
395/// Utility for parsing SSA names and block labels.
396#[derive(Default)]
397pub(crate) struct NameTracker {
398    ssa_name_scope: Vec<IMap<Identifier, Value>>,
399    block_label_scope: Vec<IMap<Identifier, LabelRef>>,
400}
401
402#[derive(Error, Debug)]
403#[error("Identifier {0} was not resolved to any definition in the scope")]
404pub struct UnresolvedReference(Identifier);
405
406#[derive(Error, Debug)]
407pub enum ParserNameTrackerError {
408    #[error("Identifier {0} defined more than once in the scope")]
409    MultipleDefinitions(Identifier),
410    #[error("Regions in a top-level operation must be IsolatedFromAbove")]
411    TopLevelOpRegionNotIsolatedFromAbove,
412}
413
414impl NameTracker {
415    /// An SSA use is seen. Get its [definition value][Value]
416    /// or return a [forward reference][ForwardRefOp] that will
417    /// be updated when the actual definition is seen.
418    pub(crate) fn ssa_use(&mut self, ctx: &mut Context, id: &Identifier) -> Value {
419        let scope = self
420            .ssa_name_scope
421            .last_mut()
422            .expect("NameTracker doesn't have an active scope.");
423        match scope.entry(id.clone()) {
424            Entry::Occupied(occ) => *occ.get(),
425            Entry::Vacant(vac) => {
426                // Insert a forward reference.
427                let forward_def = ForwardRefOp::new(ctx).get_result(ctx);
428                vac.insert(forward_def);
429                forward_def
430            }
431        }
432    }
433
434    /// Register an SSA definition. If `id` is already associated with a
435    /// [forward reference][ForwardRefOp], update and replace all uses with `def`.
436    pub(crate) fn ssa_def(
437        &mut self,
438        ctx: &mut Context,
439        id: &(Identifier, Location),
440        def: Value,
441    ) -> Result<()> {
442        let scope = self
443            .ssa_name_scope
444            .last_mut()
445            .expect("NameTracker doesn't have an active scope.");
446
447        match scope.entry(id.0.clone()) {
448            Entry::Occupied(mut occ) => match occ.get_mut().defining_entity() {
449                DefiningEntity::Op(op) => {
450                    let fref_opt =
451                        Operation::get_op::<ForwardRefOp>(op, ctx).map(|op| op.get_result(ctx));
452                    if let Some(fref) = fref_opt {
453                        // If there's already a def and its a forward ref, replace that.
454                        fref.replace_some_uses_with(ctx, |_, _| true, &def);
455                        Operation::erase(op, ctx);
456                        occ.insert(def);
457                    } else {
458                        // There's another def and it isn't a forward ref.
459                        input_err!(
460                            id.1.clone(),
461                            ParserNameTrackerError::MultipleDefinitions(id.0.clone())
462                        )?
463                    }
464                }
465                DefiningEntity::Block(_) => {
466                    // There's another def and it isn't a forward ref.
467                    input_err!(
468                        id.1.clone(),
469                        ParserNameTrackerError::MultipleDefinitions(id.0.clone())
470                    )?
471                }
472            },
473            Entry::Vacant(vac) => {
474                vac.insert(def);
475            }
476        }
477        Ok(())
478    }
479
480    /// A [BasicBlock] use is seen. Get the actual block it refers to.
481    /// If the block wasn't seen yet, create one now. When exiting the scope,
482    /// if the block ends up not being seen, an undefined reference error is returned.
483    pub(crate) fn block_use(&mut self, ctx: &mut Context, id: &Identifier) -> Ptr<BasicBlock> {
484        let scope = self
485            .block_label_scope
486            .last_mut()
487            .expect("NameTracker doesn't have an active scope.");
488        match scope.entry(id.clone()) {
489            Entry::Occupied(occ) => occ.get().get_label(),
490            Entry::Vacant(vac) => {
491                // Insert a forward reference.
492                let block_forward = BasicBlock::new(ctx, Some(id.clone()), vec![]);
493                vac.insert(LabelRef::ForwardRef(block_forward));
494                block_forward
495            }
496        }
497    }
498
499    /// A [BasicBlock] def is seen. If refs was seen earlier,
500    /// they are all updated now to refer to the provided block instead.
501    pub(crate) fn block_def(
502        &mut self,
503        ctx: &mut Context,
504        id: &(Identifier, Location),
505        block: Ptr<BasicBlock>,
506    ) -> Result<()> {
507        let scope = self
508            .block_label_scope
509            .last_mut()
510            .expect("NameTracker doesn't have an active scope.");
511        match scope.entry(id.0.clone()) {
512            Entry::Occupied(mut occ) => match occ.get_mut() {
513                LabelRef::ForwardRef(fref) => {
514                    fref.retarget_some_preds_to(ctx, |_, _| true, block);
515                    BasicBlock::erase(*fref, ctx);
516                    occ.insert(LabelRef::Defined(block));
517                }
518                LabelRef::Defined(_) => input_err!(
519                    id.1.clone(),
520                    ParserNameTrackerError::MultipleDefinitions(id.0.clone())
521                )?,
522            },
523            Entry::Vacant(vac) => {
524                vac.insert(LabelRef::Defined(block));
525            }
526        }
527        Ok(())
528    }
529
530    /// Enter a new region.
531    /// - If the parent op is [IsolatedFromAboveInterface],
532    ///   then a new independent SSA name scope is created.
533    /// - A new independent block label scope is always created.
534    pub(crate) fn enter_region(&mut self, ctx: &Context, parent_op: Ptr<Operation>) -> Result<()> {
535        if op_impls::<dyn IsolatedFromAboveInterface>(
536            Operation::get_op_dyn(parent_op, ctx).as_ref(),
537        ) {
538            self.ssa_name_scope.push(IMap::default());
539        } else if self.ssa_name_scope.is_empty() {
540            input_err!(
541                parent_op.deref(ctx).loc(),
542                ParserNameTrackerError::TopLevelOpRegionNotIsolatedFromAbove
543            )?
544        }
545        self.block_label_scope.push(IMap::default());
546        Ok(())
547    }
548
549    /// Exit a region.
550    /// - If the parent op is [IsolatedFromAboveInterface], then the top SSA name scope is popped.
551    /// - The top block label scope is popped.
552    pub(crate) fn exit_region(
553        &mut self,
554        ctx: &Context,
555        parent_op: Ptr<Operation>,
556        loc: Location,
557    ) -> Result<()> {
558        if op_impls::<dyn IsolatedFromAboveInterface>(
559            Operation::get_op_dyn(parent_op, ctx).as_ref(),
560        ) {
561            // Check if there are any [ForwardRefOp].
562            let ssa_scope = self
563                .ssa_name_scope
564                .pop()
565                .expect("Exiting an isolated-from-above region which wasn't entered into.");
566            for (id, value) in ssa_scope {
567                if let DefiningEntity::Op(op) = value.defining_entity()
568                    && Operation::is_op::<ForwardRefOp>(op, ctx)
569                {
570                    input_err!(loc.clone(), UnresolvedReference(id.clone()))?
571                }
572            }
573        }
574
575        let label_scope = self
576            .block_label_scope
577            .pop()
578            .expect("Exiting an isolated-from-above region which wasn't entered into.");
579
580        // Check if there are any unresolved forward label references.
581        for (id, op) in label_scope {
582            if matches!(op, LabelRef::ForwardRef(_)) {
583                input_err!(loc.clone(), UnresolvedReference(id.clone()))?
584            }
585        }
586
587        Ok(())
588    }
589}
590
591impl Parsable for usize {
592    type Arg = ();
593    type Parsed = usize;
594
595    fn parse<'a>(
596        state_stream: &mut StateStream<'a>,
597        _arg: Self::Arg,
598    ) -> ParseResult<'a, Self::Parsed> {
599        int_parser::<usize>().parse_stream(state_stream).into()
600    }
601}
602impl Parsable for u64 {
603    type Arg = ();
604    type Parsed = u64;
605
606    fn parse<'a>(
607        state_stream: &mut StateStream<'a>,
608        _arg: Self::Arg,
609    ) -> ParseResult<'a, Self::Parsed> {
610        int_parser::<u64>().parse_stream(state_stream).into()
611    }
612}
613
614impl Parsable for u32 {
615    type Arg = ();
616    type Parsed = u32;
617
618    fn parse<'a>(
619        state_stream: &mut StateStream<'a>,
620        _arg: Self::Arg,
621    ) -> ParseResult<'a, Self::Parsed> {
622        int_parser::<u32>().parse_stream(state_stream).into()
623    }
624}
625
626impl Parsable for u16 {
627    type Arg = ();
628    type Parsed = u16;
629
630    fn parse<'a>(
631        state_stream: &mut StateStream<'a>,
632        _arg: Self::Arg,
633    ) -> ParseResult<'a, Self::Parsed> {
634        int_parser::<u16>().parse_stream(state_stream).into()
635    }
636}
637
638impl Parsable for u8 {
639    type Arg = ();
640    type Parsed = u8;
641
642    fn parse<'a>(
643        state_stream: &mut StateStream<'a>,
644        _arg: Self::Arg,
645    ) -> ParseResult<'a, Self::Parsed> {
646        int_parser::<u8>().parse_stream(state_stream).into()
647    }
648}
649
650impl Parsable for i8 {
651    type Arg = ();
652    type Parsed = i8;
653
654    fn parse<'a>(
655        state_stream: &mut StateStream<'a>,
656        _arg: Self::Arg,
657    ) -> ParseResult<'a, Self::Parsed> {
658        int_parser::<i8>().parse_stream(state_stream).into()
659    }
660}
661
662impl Parsable for i16 {
663    type Arg = ();
664    type Parsed = i16;
665
666    fn parse<'a>(
667        state_stream: &mut StateStream<'a>,
668        _arg: Self::Arg,
669    ) -> ParseResult<'a, Self::Parsed> {
670        int_parser::<i16>().parse_stream(state_stream).into()
671    }
672}
673
674impl Parsable for i32 {
675    type Arg = ();
676    type Parsed = i32;
677
678    fn parse<'a>(
679        state_stream: &mut StateStream<'a>,
680        _arg: Self::Arg,
681    ) -> ParseResult<'a, Self::Parsed> {
682        int_parser::<i32>().parse_stream(state_stream).into()
683    }
684}
685
686impl Parsable for i64 {
687    type Arg = ();
688    type Parsed = i64;
689
690    fn parse<'a>(
691        state_stream: &mut StateStream<'a>,
692        _arg: Self::Arg,
693    ) -> ParseResult<'a, Self::Parsed> {
694        int_parser::<i64>().parse_stream(state_stream).into()
695    }
696}
697
698impl Parsable for bool {
699    type Arg = ();
700    type Parsed = bool;
701
702    fn parse<'a>(
703        state_stream: &mut StateStream<'a>,
704        _arg: Self::Arg,
705    ) -> ParseResult<'a, Self::Parsed> {
706        // Choose b/w true/false
707        let mut bool_parser =
708            choice((string("true").map(|_| true), string("false").map(|_| false)));
709
710        bool_parser.parse_stream(state_stream).into()
711    }
712}
713
714impl Parsable for String {
715    type Arg = ();
716
717    type Parsed = Self;
718
719    fn parse<'a>(
720        state_stream: &mut StateStream<'a>,
721        _arg: Self::Arg,
722    ) -> ParseResult<'a, Self::Parsed> {
723        quoted_string_parser().parse_stream(state_stream).into()
724    }
725}
726
727impl Parsable for *const () {
728    type Arg = ();
729
730    type Parsed = Self;
731
732    fn parse<'a>(
733        state_stream: &mut StateStream<'a>,
734        _arg: Self::Arg,
735    ) -> ParseResult<'a, Self::Parsed> {
736        hex_int_parser::<usize>()
737            .parse_stream(state_stream)
738            .map(|n| n as *const ())
739            .into()
740    }
741}
742
743impl Parsable for *mut () {
744    type Arg = ();
745
746    type Parsed = Self;
747
748    fn parse<'a>(
749        state_stream: &mut StateStream<'a>,
750        _arg: Self::Arg,
751    ) -> ParseResult<'a, Self::Parsed> {
752        hex_int_parser::<usize>()
753            .parse_stream(state_stream)
754            .map(|n| n as *mut ())
755            .into()
756    }
757}