diff options
Diffstat (limited to 'crates/ra_mbe')
-rw-r--r-- | crates/ra_mbe/src/lib.rs | 20 | ||||
-rw-r--r-- | crates/ra_mbe/src/mbe_expander.rs | 14 |
2 files changed, 24 insertions, 10 deletions
diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs index 2c75b7b4f..989308626 100644 --- a/crates/ra_mbe/src/lib.rs +++ b/crates/ra_mbe/src/lib.rs | |||
@@ -42,7 +42,7 @@ pub use crate::syntax_bridge::{ast_to_token_tree, token_tree_to_ast_item_list}; | |||
42 | /// be very confusing is that AST has almost exactly the same shape as | 42 | /// be very confusing is that AST has almost exactly the same shape as |
43 | /// `tt::TokenTree`, but there's a crucial difference: in macro rules, `$ident` | 43 | /// `tt::TokenTree`, but there's a crucial difference: in macro rules, `$ident` |
44 | /// and `$()*` have special meaning (see `Var` and `Repeat` data structures) | 44 | /// and `$()*` have special meaning (see `Var` and `Repeat` data structures) |
45 | #[derive(Debug, PartialEq, Eq)] | 45 | #[derive(Clone, Debug, PartialEq, Eq)] |
46 | pub struct MacroRules { | 46 | pub struct MacroRules { |
47 | pub(crate) rules: Vec<Rule>, | 47 | pub(crate) rules: Vec<Rule>, |
48 | } | 48 | } |
@@ -56,13 +56,13 @@ impl MacroRules { | |||
56 | } | 56 | } |
57 | } | 57 | } |
58 | 58 | ||
59 | #[derive(Debug, PartialEq, Eq)] | 59 | #[derive(Clone, Debug, PartialEq, Eq)] |
60 | pub(crate) struct Rule { | 60 | pub(crate) struct Rule { |
61 | pub(crate) lhs: Subtree, | 61 | pub(crate) lhs: Subtree, |
62 | pub(crate) rhs: Subtree, | 62 | pub(crate) rhs: Subtree, |
63 | } | 63 | } |
64 | 64 | ||
65 | #[derive(Debug, PartialEq, Eq)] | 65 | #[derive(Clone, Debug, PartialEq, Eq)] |
66 | pub(crate) enum TokenTree { | 66 | pub(crate) enum TokenTree { |
67 | Leaf(Leaf), | 67 | Leaf(Leaf), |
68 | Subtree(Subtree), | 68 | Subtree(Subtree), |
@@ -70,7 +70,7 @@ pub(crate) enum TokenTree { | |||
70 | } | 70 | } |
71 | impl_froms!(TokenTree: Leaf, Subtree, Repeat); | 71 | impl_froms!(TokenTree: Leaf, Subtree, Repeat); |
72 | 72 | ||
73 | #[derive(Debug, PartialEq, Eq)] | 73 | #[derive(Clone, Debug, PartialEq, Eq)] |
74 | pub(crate) enum Leaf { | 74 | pub(crate) enum Leaf { |
75 | Literal(Literal), | 75 | Literal(Literal), |
76 | Punct(Punct), | 76 | Punct(Punct), |
@@ -79,37 +79,37 @@ pub(crate) enum Leaf { | |||
79 | } | 79 | } |
80 | impl_froms!(Leaf: Literal, Punct, Ident, Var); | 80 | impl_froms!(Leaf: Literal, Punct, Ident, Var); |
81 | 81 | ||
82 | #[derive(Debug, PartialEq, Eq)] | 82 | #[derive(Clone, Debug, PartialEq, Eq)] |
83 | pub(crate) struct Subtree { | 83 | pub(crate) struct Subtree { |
84 | pub(crate) delimiter: Delimiter, | 84 | pub(crate) delimiter: Delimiter, |
85 | pub(crate) token_trees: Vec<TokenTree>, | 85 | pub(crate) token_trees: Vec<TokenTree>, |
86 | } | 86 | } |
87 | 87 | ||
88 | #[derive(Debug, PartialEq, Eq)] | 88 | #[derive(Clone, Debug, PartialEq, Eq)] |
89 | pub(crate) struct Repeat { | 89 | pub(crate) struct Repeat { |
90 | pub(crate) subtree: Subtree, | 90 | pub(crate) subtree: Subtree, |
91 | pub(crate) kind: RepeatKind, | 91 | pub(crate) kind: RepeatKind, |
92 | pub(crate) separator: Option<char>, | 92 | pub(crate) separator: Option<char>, |
93 | } | 93 | } |
94 | 94 | ||
95 | #[derive(Debug, PartialEq, Eq)] | 95 | #[derive(Clone, Debug, PartialEq, Eq)] |
96 | pub(crate) enum RepeatKind { | 96 | pub(crate) enum RepeatKind { |
97 | ZeroOrMore, | 97 | ZeroOrMore, |
98 | OneOrMore, | 98 | OneOrMore, |
99 | ZeroOrOne, | 99 | ZeroOrOne, |
100 | } | 100 | } |
101 | 101 | ||
102 | #[derive(Debug, PartialEq, Eq)] | 102 | #[derive(Clone, Debug, PartialEq, Eq)] |
103 | pub(crate) struct Literal { | 103 | pub(crate) struct Literal { |
104 | pub(crate) text: SmolStr, | 104 | pub(crate) text: SmolStr, |
105 | } | 105 | } |
106 | 106 | ||
107 | #[derive(Debug, PartialEq, Eq)] | 107 | #[derive(Clone, Debug, PartialEq, Eq)] |
108 | pub(crate) struct Ident { | 108 | pub(crate) struct Ident { |
109 | pub(crate) text: SmolStr, | 109 | pub(crate) text: SmolStr, |
110 | } | 110 | } |
111 | 111 | ||
112 | #[derive(Debug, PartialEq, Eq)] | 112 | #[derive(Clone, Debug, PartialEq, Eq)] |
113 | pub(crate) struct Var { | 113 | pub(crate) struct Var { |
114 | pub(crate) text: SmolStr, | 114 | pub(crate) text: SmolStr, |
115 | pub(crate) kind: Option<SmolStr>, | 115 | pub(crate) kind: Option<SmolStr>, |
diff --git a/crates/ra_mbe/src/mbe_expander.rs b/crates/ra_mbe/src/mbe_expander.rs index 2dd97b665..2dafd68f6 100644 --- a/crates/ra_mbe/src/mbe_expander.rs +++ b/crates/ra_mbe/src/mbe_expander.rs | |||
@@ -155,7 +155,14 @@ fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Result<Bindings, | |||
155 | _ => return Err(ExpandError::UnexpectedToken), | 155 | _ => return Err(ExpandError::UnexpectedToken), |
156 | }, | 156 | }, |
157 | crate::TokenTree::Repeat(crate::Repeat { subtree, kind: _, separator }) => { | 157 | crate::TokenTree::Repeat(crate::Repeat { subtree, kind: _, separator }) => { |
158 | // Dirty hack to make macro-expansion terminate. | ||
159 | // This should be replaced by a propper macro-by-example implementation | ||
160 | let mut limit = 128; | ||
158 | while let Ok(nested) = match_lhs(subtree, input) { | 161 | while let Ok(nested) = match_lhs(subtree, input) { |
162 | limit -= 1; | ||
163 | if limit == 0 { | ||
164 | break; | ||
165 | } | ||
159 | res.push_nested(nested)?; | 166 | res.push_nested(nested)?; |
160 | if let Some(separator) = *separator { | 167 | if let Some(separator) = *separator { |
161 | if !input.is_eof() { | 168 | if !input.is_eof() { |
@@ -196,7 +203,14 @@ fn expand_tt( | |||
196 | crate::TokenTree::Repeat(repeat) => { | 203 | crate::TokenTree::Repeat(repeat) => { |
197 | let mut token_trees = Vec::new(); | 204 | let mut token_trees = Vec::new(); |
198 | nesting.push(0); | 205 | nesting.push(0); |
206 | // Dirty hack to make macro-expansion terminate. | ||
207 | // This should be replaced by a propper macro-by-example implementation | ||
208 | let mut limit = 128; | ||
199 | while let Ok(t) = expand_subtree(&repeat.subtree, bindings, nesting) { | 209 | while let Ok(t) = expand_subtree(&repeat.subtree, bindings, nesting) { |
210 | limit -= 1; | ||
211 | if limit == 0 { | ||
212 | break; | ||
213 | } | ||
200 | let idx = nesting.pop().unwrap(); | 214 | let idx = nesting.pop().unwrap(); |
201 | nesting.push(idx + 1); | 215 | nesting.push(idx + 1); |
202 | token_trees.push(t.into()) | 216 | token_trees.push(t.into()) |