Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/mbe/src/lib.rs')
-rw-r--r--crates/mbe/src/lib.rs49
1 files changed, 38 insertions, 11 deletions
diff --git a/crates/mbe/src/lib.rs b/crates/mbe/src/lib.rs
index ac107a0d6d..5ef20ff8a9 100644
--- a/crates/mbe/src/lib.rs
+++ b/crates/mbe/src/lib.rs
@@ -19,6 +19,7 @@ mod benchmark;
mod token_map;
use ::tt::token_id as tt;
+use stdx::impl_from;
use std::fmt;
@@ -69,7 +70,7 @@ impl fmt::Display for ParseError {
}
}
-#[derive(Debug, PartialEq, Eq, Clone)]
+#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub enum ExpandError {
BindingError(Box<Box<str>>),
LeftoverTokens,
@@ -77,8 +78,11 @@ pub enum ExpandError {
LimitExceeded,
NoMatchingRule,
UnexpectedToken,
+ CountError(CountError),
}
+impl_from!(CountError for ExpandError);
+
impl ExpandError {
fn binding_error(e: impl Into<Box<str>>) -> ExpandError {
ExpandError::BindingError(Box::new(e.into()))
@@ -94,6 +98,23 @@ impl fmt::Display for ExpandError {
ExpandError::ConversionError => f.write_str("could not convert tokens"),
ExpandError::LimitExceeded => f.write_str("Expand exceed limit"),
ExpandError::LeftoverTokens => f.write_str("leftover tokens"),
+ ExpandError::CountError(e) => e.fmt(f),
+ }
+ }
+}
+
+// FIXME: Showing these errors could be nicer.
+#[derive(Debug, PartialEq, Eq, Clone, Hash)]
+pub enum CountError {
+ OutOfBounds,
+ Misplaced,
+}
+
+impl fmt::Display for CountError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ CountError::OutOfBounds => f.write_str("${count} out of bounds"),
+ CountError::Misplaced => f.write_str("${count} misplaced"),
}
}
}
@@ -104,9 +125,12 @@ impl fmt::Display for ExpandError {
/// and `$()*` have special meaning (see `Var` and `Repeat` data structures)
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct DeclarativeMacro {
- rules: Vec<Rule>,
+ rules: Box<[Rule]>,
/// Highest id of the token we have in TokenMap
shift: Shift,
+ // This is used for correctly determining the behavior of the pat fragment
+ // FIXME: This should be tracked by hygiene of the fragment identifier!
+ is_2021: bool,
}
#[derive(Clone, Debug, PartialEq, Eq)]
@@ -190,7 +214,10 @@ pub enum Origin {
impl DeclarativeMacro {
/// The old, `macro_rules! m {}` flavor.
- pub fn parse_macro_rules(tt: &tt::Subtree) -> Result<DeclarativeMacro, ParseError> {
+ pub fn parse_macro_rules(
+ tt: &tt::Subtree,
+ is_2021: bool,
+ ) -> Result<DeclarativeMacro, ParseError> {
// Note: this parsing can be implemented using mbe machinery itself, by
// matching against `$($lhs:tt => $rhs:tt);*` pattern, but implementing
// manually seems easier.
@@ -211,11 +238,11 @@ impl DeclarativeMacro {
validate(lhs)?;
}
- Ok(DeclarativeMacro { rules, shift: Shift::new(tt) })
+ Ok(DeclarativeMacro { rules: rules.into_boxed_slice(), shift: Shift::new(tt), is_2021 })
}
/// The new, unstable `macro m {}` flavor.
- pub fn parse_macro2(tt: &tt::Subtree) -> Result<DeclarativeMacro, ParseError> {
+ pub fn parse_macro2(tt: &tt::Subtree, is_2021: bool) -> Result<DeclarativeMacro, ParseError> {
let mut src = TtIter::new(tt);
let mut rules = Vec::new();
@@ -244,14 +271,14 @@ impl DeclarativeMacro {
validate(lhs)?;
}
- Ok(DeclarativeMacro { rules, shift: Shift::new(tt) })
+ Ok(DeclarativeMacro { rules: rules.into_boxed_slice(), shift: Shift::new(tt), is_2021 })
}
pub fn expand(&self, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
// apply shift
let mut tt = tt.clone();
self.shift.shift_all(&mut tt);
- expander::expand_rules(&self.rules, &tt)
+ expander::expand_rules(&self.rules, &tt, self.is_2021)
}
pub fn map_id_down(&self, id: tt::TokenId) -> tt::TokenId {
@@ -324,12 +351,12 @@ pub struct ValueResult<T, E> {
}
impl<T, E> ValueResult<T, E> {
- pub fn ok(value: T) -> Self {
- Self { value, err: None }
+ pub fn new(value: T, err: E) -> Self {
+ Self { value, err: Some(err) }
}
- pub fn with_err(value: T, err: E) -> Self {
- Self { value, err: Some(err) }
+ pub fn ok(value: T) -> Self {
+ Self { value, err: None }
}
pub fn only_err(err: E) -> Self