Skip to content

Commit 9421d2a

Browse files
bors[bot]matklad
andauthored
Merge #1858
1858: use usual token tree for macro expansions r=matklad a=matklad Co-authored-by: Aleksey Kladov <[email protected]>
2 parents 8eb2697 + 4551182 commit 9421d2a

File tree

10 files changed

+753
-933
lines changed

10 files changed

+753
-933
lines changed

crates/ra_mbe/src/lib.rs

Lines changed: 61 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -3,30 +3,19 @@
33
/// interface, although it contains some code to bridge `SyntaxNode`s and
44
/// `TokenTree`s as well!
55
6-
macro_rules! impl_froms {
7-
($e:ident: $($v:ident), *) => {
8-
$(
9-
impl From<$v> for $e {
10-
fn from(it: $v) -> $e {
11-
$e::$v(it)
12-
}
13-
}
14-
)*
15-
}
16-
}
17-
18-
mod mbe_parser;
6+
mod parser;
197
mod mbe_expander;
208
mod syntax_bridge;
21-
mod tt_cursor;
9+
mod tt_iter;
2210
mod subtree_source;
23-
mod subtree_parser;
24-
25-
use ra_syntax::SmolStr;
26-
use smallvec::SmallVec;
2711

2812
pub use tt::{Delimiter, Punct};
2913

14+
use crate::{
15+
parser::{parse_pattern, Op},
16+
tt_iter::TtIter,
17+
};
18+
3019
#[derive(Debug, PartialEq, Eq)]
3120
pub enum ParseError {
3221
Expected(String),
@@ -38,6 +27,7 @@ pub enum ExpandError {
3827
UnexpectedToken,
3928
BindingError(String),
4029
ConversionError,
30+
InvalidRepeat,
4131
}
4232

4333
pub use crate::syntax_bridge::{
@@ -54,97 +44,72 @@ pub struct MacroRules {
5444
pub(crate) rules: Vec<Rule>,
5545
}
5646

47+
#[derive(Clone, Debug, PartialEq, Eq)]
48+
pub(crate) struct Rule {
49+
pub(crate) lhs: tt::Subtree,
50+
pub(crate) rhs: tt::Subtree,
51+
}
52+
5753
impl MacroRules {
5854
pub fn parse(tt: &tt::Subtree) -> Result<MacroRules, ParseError> {
59-
mbe_parser::parse(tt)
55+
let mut src = TtIter::new(tt);
56+
let mut rules = Vec::new();
57+
while src.len() > 0 {
58+
let rule = Rule::parse(&mut src)?;
59+
rules.push(rule);
60+
if let Err(()) = src.expect_char(';') {
61+
if src.len() > 0 {
62+
return Err(ParseError::Expected("expected `:`".to_string()));
63+
}
64+
break;
65+
}
66+
}
67+
Ok(MacroRules { rules })
6068
}
6169
pub fn expand(&self, tt: &tt::Subtree) -> Result<tt::Subtree, ExpandError> {
6270
mbe_expander::expand(self, tt)
6371
}
6472
}
6573

66-
#[derive(Clone, Debug, PartialEq, Eq)]
67-
pub(crate) struct Rule {
68-
pub(crate) lhs: Subtree,
69-
pub(crate) rhs: Subtree,
70-
}
71-
72-
#[derive(Clone, Debug, PartialEq, Eq)]
73-
pub(crate) enum TokenTree {
74-
Leaf(Leaf),
75-
Subtree(Subtree),
76-
Repeat(Repeat),
77-
}
78-
impl_froms!(TokenTree: Leaf, Subtree, Repeat);
79-
80-
#[derive(Clone, Debug, PartialEq, Eq)]
81-
pub(crate) enum Leaf {
82-
Literal(Literal),
83-
Punct(Punct),
84-
Ident(Ident),
85-
Var(Var),
86-
}
87-
impl_froms!(Leaf: Literal, Punct, Ident, Var);
88-
89-
#[derive(Clone, Debug, PartialEq, Eq)]
90-
pub(crate) struct Subtree {
91-
pub(crate) delimiter: Delimiter,
92-
pub(crate) token_trees: Vec<TokenTree>,
93-
}
94-
95-
#[derive(Clone, Debug, Eq)]
96-
pub(crate) enum Separator {
97-
Literal(tt::Literal),
98-
Ident(tt::Ident),
99-
Puncts(SmallVec<[tt::Punct; 3]>),
74+
impl Rule {
75+
fn parse(src: &mut TtIter) -> Result<Rule, ParseError> {
76+
let mut lhs = src
77+
.expect_subtree()
78+
.map_err(|()| ParseError::Expected("expected subtree".to_string()))?
79+
.clone();
80+
validate(&lhs)?;
81+
lhs.delimiter = tt::Delimiter::None;
82+
src.expect_char('=').map_err(|()| ParseError::Expected("expected `=`".to_string()))?;
83+
src.expect_char('>').map_err(|()| ParseError::Expected("expected `>`".to_string()))?;
84+
let mut rhs = src
85+
.expect_subtree()
86+
.map_err(|()| ParseError::Expected("expected subtree".to_string()))?
87+
.clone();
88+
rhs.delimiter = tt::Delimiter::None;
89+
Ok(crate::Rule { lhs, rhs })
90+
}
10091
}
10192

102-
// Note that when we compare a Separator, we just care about its textual value.
103-
impl PartialEq for crate::Separator {
104-
fn eq(&self, other: &crate::Separator) -> bool {
105-
use crate::Separator::*;
106-
107-
match (self, other) {
108-
(Ident(ref a), Ident(ref b)) => a.text == b.text,
109-
(Literal(ref a), Literal(ref b)) => a.text == b.text,
110-
(Puncts(ref a), Puncts(ref b)) if a.len() == b.len() => {
111-
let a_iter = a.iter().map(|a| a.char);
112-
let b_iter = b.iter().map(|b| b.char);
113-
a_iter.eq(b_iter)
93+
fn validate(pattern: &tt::Subtree) -> Result<(), ParseError> {
94+
for op in parse_pattern(pattern) {
95+
let op = match op {
96+
Ok(it) => it,
97+
Err(e) => {
98+
let msg = match e {
99+
ExpandError::InvalidRepeat => "invalid repeat".to_string(),
100+
_ => "invalid macro definition".to_string(),
101+
};
102+
return Err(ParseError::Expected(msg));
103+
}
104+
};
105+
match op {
106+
Op::TokenTree(tt::TokenTree::Subtree(subtree)) | Op::Repeat { subtree, .. } => {
107+
validate(subtree)?
114108
}
115-
_ => false,
109+
_ => (),
116110
}
117111
}
118-
}
119-
120-
#[derive(Clone, Debug, PartialEq, Eq)]
121-
pub(crate) struct Repeat {
122-
pub(crate) subtree: Subtree,
123-
pub(crate) kind: RepeatKind,
124-
pub(crate) separator: Option<Separator>,
125-
}
126-
127-
#[derive(Clone, Debug, PartialEq, Eq)]
128-
pub(crate) enum RepeatKind {
129-
ZeroOrMore,
130-
OneOrMore,
131-
ZeroOrOne,
132-
}
133-
134-
#[derive(Clone, Debug, PartialEq, Eq)]
135-
pub(crate) struct Literal {
136-
pub(crate) text: SmolStr,
137-
}
138-
139-
#[derive(Clone, Debug, PartialEq, Eq)]
140-
pub(crate) struct Ident {
141-
pub(crate) text: SmolStr,
142-
}
143-
144-
#[derive(Clone, Debug, PartialEq, Eq)]
145-
pub(crate) struct Var {
146-
pub(crate) text: SmolStr,
147-
pub(crate) kind: Option<SmolStr>,
112+
Ok(())
148113
}
149114

150115
#[cfg(test)]

crates/ra_mbe/src/mbe_expander.rs

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ mod transcriber;
88
use ra_syntax::SmolStr;
99
use rustc_hash::FxHashMap;
1010

11-
use crate::tt_cursor::TtCursor;
1211
use crate::ExpandError;
1312

1413
pub(crate) fn expand(
@@ -19,12 +18,8 @@ pub(crate) fn expand(
1918
}
2019

2120
fn expand_rule(rule: &crate::Rule, input: &tt::Subtree) -> Result<tt::Subtree, ExpandError> {
22-
let mut input = TtCursor::new(input);
23-
let bindings = matcher::match_lhs(&rule.lhs, &mut input)?;
24-
if !input.is_eof() {
25-
return Err(ExpandError::UnexpectedToken);
26-
}
27-
let res = transcriber::transcribe(&bindings, &rule.rhs)?;
21+
let bindings = matcher::match_(&rule.lhs, input)?;
22+
let res = transcriber::transcribe(&rule.rhs, &bindings)?;
2823
Ok(res)
2924
}
3025

@@ -103,13 +98,6 @@ mod tests {
10398

10499
#[test]
105100
fn test_expand_rule() {
106-
// FIXME: The missing $var check should be in parsing phase
107-
// assert_err(
108-
// "($i:ident) => ($j)",
109-
// "foo!{a}",
110-
// ExpandError::BindingError(String::from("could not find binding `j`")),
111-
// );
112-
113101
assert_err(
114102
"($($i:ident);*) => ($i)",
115103
"foo!{a}",
@@ -118,9 +106,6 @@ mod tests {
118106
)),
119107
);
120108

121-
assert_err("($i) => ($i)", "foo!{a}", ExpandError::UnexpectedToken);
122-
assert_err("($i:) => ($i)", "foo!{a}", ExpandError::UnexpectedToken);
123-
124109
// FIXME:
125110
// Add an err test case for ($($i:ident)) => ($())
126111
}

0 commit comments

Comments
 (0)