1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
//! Traits and types that provide the different aspects of `Parser`s' //! functionality. use core::ops::Deref; use crate::{Datum, DerefTryMut, Combiner, Text, Error}; use crate::combiner::{OpFn, ApFn}; /// Implementations provided for ready use. pub mod premade { mod default_classifier; pub use default_classifier::DefaultCharClassifier; mod slice_alloc; pub use slice_alloc::SliceDatumAllocator; mod empty_bindings; pub use empty_bindings::EmptyOperatorBindings; mod pair_bindings; pub use pair_bindings::PairOperatorBindings; } /// The possible errors that might be returned by a parser's `Datum` allocator. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum AllocError { /// No more free AllocExhausted, } impl<Pos, CE> From<AllocError> for Error<Pos, CE> { fn from(ae: AllocError) -> Self { Error::FailedAlloc(ae) } } /// Classifier of `char`s that determines which are a `Parser`'s special /// delimiters. /// /// Enables different applications to use different sets of delimiters. /// E.g. URI-friendly characters might be used instead. /// /// Do not make more than one of the predicate methods return `true` for the /// same `char`. pub trait CharClassifier { /// Predicate that determines the character(s) used to delimit the start of /// our nesting form. fn is_nest_start(&self, c: char) -> bool; /// Predicate that determines the character(s) used to delimit the end of /// our nesting form. fn is_nest_end(&self, c: char) -> bool; /// Predicate that determines the character(s) used to escape the delimiter /// characters of our nesting form. fn is_nest_escape(&self, c: char) -> bool; /// Predicate that determines the character(s) considered to be whitespace, /// which affects the delimiting of operator and operands in our nesting /// form. fn is_whitespace(&self, c: char) -> bool; } /// Allocator of space for `Datum` values that a `Parser` constructs. /// /// Enables the parsing logic to be generic over this aspect so that various /// approaches may be chosen depending on the application. E.g. heap vs. stack /// allocation. pub trait DatumAllocator { /// The `Text` type for our `Datum` type. It should also implement /// `TextConcat<Self>` so it supports concatenation which the parsing /// requires. /// /// Such a bound is not required here, to avoid difficulties that otherwise /// would happen with needing to have the bound where not really needed and /// where unresolvable mutually-recursive bounds would result. The bound is /// instead placed on the methods of `ParseIter` and `SourceStream` /// implementations where it's really needed. type TT: Text; /// The ["extra" type](enum.Datum.html#variant.Extra) for our `Datum` type. type ET; /// The type of references to [`Datum`s](enum.Datum.html) yielded by our /// parsing. type DR: DerefTryMut<Target = Datum<Self::TT, Self::ET, Self::DR>>; /// Allocate a fresh [`Datum`](enum.Datum.html), in whatever way the /// particular implementation wants, and set its initial value to that of /// the `from` argument. An [`AllocError`](enum.AllocError.html) is /// returned if allocation fails for any reason. fn new_datum(&mut self, from: Datum<Self::TT, Self::ET, Self::DR>) -> Result<Self::DR, AllocError>; } /// Environment of bindings of operator sub-forms to macro functions that /// substitute forms in a `Parser`'s returned AST. /// /// Enables different applications to use different sets or none at all. pub trait OperatorBindings<DA> where DA: DatumAllocator, { /// The type of references to /// [`Operative`](enum.Combiner.html#variant.Operative) macro functions. type OR: Deref<Target = OpFn<DA, Self::CE>>; /// The type of references to /// [`Applicative`](enum.Combiner.html#variant.Applicative) macro functions. type AR: Deref<Target = ApFn<DA, Self::CE>>; /// The [combiner error extension](enum.Error.html#variant.FailedCombiner) /// type. type CE; /// Look-up any binding we might have associated with the given datum, /// referenced by the `operator` argument, which was found in operator /// (first, "head") position of a nested form. If we do have a binding for /// it, return the "combiner" function that determines the semantics of the /// entire form and further parses and processes it in possibly arbitrary /// ways. Else if we do not have a binding, return `None` to indicate that /// the form should not be handled according to the operator and that the /// operands should simply be recursively parsed. fn lookup(&self, operator: &Datum<DA::TT, DA::ET, DA::DR>) -> Option<&Combiner<Self::OR, Self::AR>>; }