aboutsummaryrefslogtreecommitdiff
path: root/crates/mbe/src/parser.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/mbe/src/parser.rs')
-rw-r--r--crates/mbe/src/parser.rs40
1 files changed, 22 insertions, 18 deletions
diff --git a/crates/mbe/src/parser.rs b/crates/mbe/src/parser.rs
index f3047972d..b90ae7015 100644
--- a/crates/mbe/src/parser.rs
+++ b/crates/mbe/src/parser.rs
@@ -4,7 +4,7 @@
4use smallvec::SmallVec; 4use smallvec::SmallVec;
5use syntax::SmolStr; 5use syntax::SmolStr;
6 6
7use crate::{tt_iter::TtIter, ExpandError, MetaTemplate}; 7use crate::{tt_iter::TtIter, MetaTemplate, ParseError};
8 8
9#[derive(Clone, Debug, PartialEq, Eq)] 9#[derive(Clone, Debug, PartialEq, Eq)]
10pub(crate) enum Op { 10pub(crate) enum Op {
@@ -46,12 +46,12 @@ impl PartialEq for Separator {
46 } 46 }
47} 47}
48 48
49pub(crate) fn parse_template(template: &tt::Subtree) -> Vec<Result<Op, ExpandError>> { 49pub(crate) fn parse_template(template: &tt::Subtree) -> Result<Vec<Op>, ParseError> {
50 parse_inner(&template, Mode::Template) 50 parse_inner(&template, Mode::Template).into_iter().collect()
51} 51}
52 52
53pub(crate) fn parse_pattern(pattern: &tt::Subtree) -> Vec<Result<Op, ExpandError>> { 53pub(crate) fn parse_pattern(pattern: &tt::Subtree) -> Result<Vec<Op>, ParseError> {
54 parse_inner(&pattern, Mode::Pattern) 54 parse_inner(&pattern, Mode::Pattern).into_iter().collect()
55} 55}
56 56
57#[derive(Clone, Copy)] 57#[derive(Clone, Copy)]
@@ -60,7 +60,7 @@ enum Mode {
60 Template, 60 Template,
61} 61}
62 62
63fn parse_inner(tt: &tt::Subtree, mode: Mode) -> Vec<Result<Op, ExpandError>> { 63fn parse_inner(tt: &tt::Subtree, mode: Mode) -> Vec<Result<Op, ParseError>> {
64 let mut src = TtIter::new(&tt); 64 let mut src = TtIter::new(&tt);
65 std::iter::from_fn(move || { 65 std::iter::from_fn(move || {
66 let first = src.next()?; 66 let first = src.next()?;
@@ -71,7 +71,7 @@ fn parse_inner(tt: &tt::Subtree, mode: Mode) -> Vec<Result<Op, ExpandError>> {
71 71
72macro_rules! err { 72macro_rules! err {
73 ($($tt:tt)*) => { 73 ($($tt:tt)*) => {
74 ExpandError::UnexpectedToken 74 ParseError::UnexpectedToken(($($tt)*).to_string())
75 }; 75 };
76} 76}
77 77
@@ -81,7 +81,7 @@ macro_rules! bail {
81 }; 81 };
82} 82}
83 83
84fn next_op<'a>(first: &tt::TokenTree, src: &mut TtIter<'a>, mode: Mode) -> Result<Op, ExpandError> { 84fn next_op<'a>(first: &tt::TokenTree, src: &mut TtIter<'a>, mode: Mode) -> Result<Op, ParseError> {
85 let res = match first { 85 let res = match first {
86 tt::TokenTree::Leaf(leaf @ tt::Leaf::Punct(tt::Punct { char: '$', .. })) => { 86 tt::TokenTree::Leaf(leaf @ tt::Leaf::Punct(tt::Punct { char: '$', .. })) => {
87 // Note that the '$' itself is a valid token inside macro_rules. 87 // Note that the '$' itself is a valid token inside macro_rules.
@@ -93,7 +93,9 @@ fn next_op<'a>(first: &tt::TokenTree, src: &mut TtIter<'a>, mode: Mode) -> Resul
93 tt::TokenTree::Subtree(subtree) => { 93 tt::TokenTree::Subtree(subtree) => {
94 let (separator, kind) = parse_repeat(src)?; 94 let (separator, kind) = parse_repeat(src)?;
95 let delimiter = subtree.delimiter; 95 let delimiter = subtree.delimiter;
96 let tokens = parse_inner(&subtree, mode); 96 let tokens = parse_inner(&subtree, mode)
97 .into_iter()
98 .collect::<Result<Vec<Op>, ParseError>>()?;
97 let subtree = MetaTemplate { tokens, delimiter }; 99 let subtree = MetaTemplate { tokens, delimiter };
98 Op::Repeat { subtree, separator, kind } 100 Op::Repeat { subtree, separator, kind }
99 } 101 }
@@ -102,7 +104,7 @@ fn next_op<'a>(first: &tt::TokenTree, src: &mut TtIter<'a>, mode: Mode) -> Resul
102 static UNDERSCORE: SmolStr = SmolStr::new_inline("_"); 104 static UNDERSCORE: SmolStr = SmolStr::new_inline("_");
103 105
104 if punct.char != '_' { 106 if punct.char != '_' {
105 return Err(ExpandError::UnexpectedToken); 107 return Err(ParseError::Expected("_".to_string()));
106 } 108 }
107 let name = UNDERSCORE.clone(); 109 let name = UNDERSCORE.clone();
108 let kind = eat_fragment_kind(src, mode)?; 110 let kind = eat_fragment_kind(src, mode)?;
@@ -135,7 +137,9 @@ fn next_op<'a>(first: &tt::TokenTree, src: &mut TtIter<'a>, mode: Mode) -> Resul
135 tt::TokenTree::Leaf(tt) => Op::Leaf(tt.clone()), 137 tt::TokenTree::Leaf(tt) => Op::Leaf(tt.clone()),
136 tt::TokenTree::Subtree(subtree) => { 138 tt::TokenTree::Subtree(subtree) => {
137 let delimiter = subtree.delimiter; 139 let delimiter = subtree.delimiter;
138 let tokens = parse_inner(&subtree, mode); 140 let tokens =
141 parse_inner(&subtree, mode).into_iter().collect::<Result<Vec<Op>, ParseError>>()?;
142
139 let subtree = MetaTemplate { tokens, delimiter }; 143 let subtree = MetaTemplate { tokens, delimiter };
140 Op::Subtree(subtree) 144 Op::Subtree(subtree)
141 } 145 }
@@ -143,7 +147,7 @@ fn next_op<'a>(first: &tt::TokenTree, src: &mut TtIter<'a>, mode: Mode) -> Resul
143 Ok(res) 147 Ok(res)
144} 148}
145 149
146fn eat_fragment_kind<'a>(src: &mut TtIter<'a>, mode: Mode) -> Result<Option<SmolStr>, ExpandError> { 150fn eat_fragment_kind<'a>(src: &mut TtIter<'a>, mode: Mode) -> Result<Option<SmolStr>, ParseError> {
147 if let Mode::Pattern = mode { 151 if let Mode::Pattern = mode {
148 src.expect_char(':').map_err(|()| err!("bad fragment specifier 1"))?; 152 src.expect_char(':').map_err(|()| err!("bad fragment specifier 1"))?;
149 let ident = src.expect_ident().map_err(|()| err!("bad fragment specifier 1"))?; 153 let ident = src.expect_ident().map_err(|()| err!("bad fragment specifier 1"))?;
@@ -156,12 +160,12 @@ fn is_boolean_literal(lit: &tt::Literal) -> bool {
156 matches!(lit.text.as_str(), "true" | "false") 160 matches!(lit.text.as_str(), "true" | "false")
157} 161}
158 162
159fn parse_repeat(src: &mut TtIter) -> Result<(Option<Separator>, RepeatKind), ExpandError> { 163fn parse_repeat(src: &mut TtIter) -> Result<(Option<Separator>, RepeatKind), ParseError> {
160 let mut separator = Separator::Puncts(SmallVec::new()); 164 let mut separator = Separator::Puncts(SmallVec::new());
161 for tt in src { 165 for tt in src {
162 let tt = match tt { 166 let tt = match tt {
163 tt::TokenTree::Leaf(leaf) => leaf, 167 tt::TokenTree::Leaf(leaf) => leaf,
164 tt::TokenTree::Subtree(_) => return Err(ExpandError::InvalidRepeat), 168 tt::TokenTree::Subtree(_) => return Err(ParseError::InvalidRepeat),
165 }; 169 };
166 let has_sep = match &separator { 170 let has_sep = match &separator {
167 Separator::Puncts(puncts) => !puncts.is_empty(), 171 Separator::Puncts(puncts) => !puncts.is_empty(),
@@ -169,7 +173,7 @@ fn parse_repeat(src: &mut TtIter) -> Result<(Option<Separator>, RepeatKind), Exp
169 }; 173 };
170 match tt { 174 match tt {
171 tt::Leaf::Ident(_) | tt::Leaf::Literal(_) if has_sep => { 175 tt::Leaf::Ident(_) | tt::Leaf::Literal(_) if has_sep => {
172 return Err(ExpandError::InvalidRepeat) 176 return Err(ParseError::InvalidRepeat)
173 } 177 }
174 tt::Leaf::Ident(ident) => separator = Separator::Ident(ident.clone()), 178 tt::Leaf::Ident(ident) => separator = Separator::Ident(ident.clone()),
175 tt::Leaf::Literal(lit) => separator = Separator::Literal(lit.clone()), 179 tt::Leaf::Literal(lit) => separator = Separator::Literal(lit.clone()),
@@ -182,11 +186,11 @@ fn parse_repeat(src: &mut TtIter) -> Result<(Option<Separator>, RepeatKind), Exp
182 match &mut separator { 186 match &mut separator {
183 Separator::Puncts(puncts) => { 187 Separator::Puncts(puncts) => {
184 if puncts.len() == 3 { 188 if puncts.len() == 3 {
185 return Err(ExpandError::InvalidRepeat); 189 return Err(ParseError::InvalidRepeat);
186 } 190 }
187 puncts.push(punct.clone()) 191 puncts.push(punct.clone())
188 } 192 }
189 _ => return Err(ExpandError::InvalidRepeat), 193 _ => return Err(ParseError::InvalidRepeat),
190 } 194 }
191 continue; 195 continue;
192 } 196 }
@@ -196,5 +200,5 @@ fn parse_repeat(src: &mut TtIter) -> Result<(Option<Separator>, RepeatKind), Exp
196 } 200 }
197 } 201 }
198 } 202 }
199 Err(ExpandError::InvalidRepeat) 203 Err(ParseError::InvalidRepeat)
200} 204}