aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_mbe/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_mbe/src/lib.rs')
-rw-r--r--crates/ra_mbe/src/lib.rs157
1 files changed, 61 insertions, 96 deletions
diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs
index f07f000ff..41720df79 100644
--- a/crates/ra_mbe/src/lib.rs
+++ b/crates/ra_mbe/src/lib.rs
@@ -3,30 +3,19 @@
3/// interface, although it contains some code to bridge `SyntaxNode`s and 3/// interface, although it contains some code to bridge `SyntaxNode`s and
4/// `TokenTree`s as well! 4/// `TokenTree`s as well!
5 5
6macro_rules! impl_froms { 6mod parser;
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
18mod mbe_parser;
19mod mbe_expander; 7mod mbe_expander;
20mod syntax_bridge; 8mod syntax_bridge;
21mod tt_cursor; 9mod tt_iter;
22mod subtree_source; 10mod subtree_source;
23mod subtree_parser;
24
25use ra_syntax::SmolStr;
26use smallvec::SmallVec;
27 11
28pub use tt::{Delimiter, Punct}; 12pub use tt::{Delimiter, Punct};
29 13
14use crate::{
15 parser::{parse_pattern, Op},
16 tt_iter::TtIter,
17};
18
30#[derive(Debug, PartialEq, Eq)] 19#[derive(Debug, PartialEq, Eq)]
31pub enum ParseError { 20pub enum ParseError {
32 Expected(String), 21 Expected(String),
@@ -38,6 +27,7 @@ pub enum ExpandError {
38 UnexpectedToken, 27 UnexpectedToken,
39 BindingError(String), 28 BindingError(String),
40 ConversionError, 29 ConversionError,
30 InvalidRepeat,
41} 31}
42 32
43pub use crate::syntax_bridge::{ 33pub use crate::syntax_bridge::{
@@ -54,97 +44,72 @@ pub struct MacroRules {
54 pub(crate) rules: Vec<Rule>, 44 pub(crate) rules: Vec<Rule>,
55} 45}
56 46
47#[derive(Clone, Debug, PartialEq, Eq)]
48pub(crate) struct Rule {
49 pub(crate) lhs: tt::Subtree,
50 pub(crate) rhs: tt::Subtree,
51}
52
57impl MacroRules { 53impl MacroRules {
58 pub fn parse(tt: &tt::Subtree) -> Result<MacroRules, ParseError> { 54 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 })
60 } 68 }
61 pub fn expand(&self, tt: &tt::Subtree) -> Result<tt::Subtree, ExpandError> { 69 pub fn expand(&self, tt: &tt::Subtree) -> Result<tt::Subtree, ExpandError> {
62 mbe_expander::expand(self, tt) 70 mbe_expander::expand(self, tt)
63 } 71 }
64} 72}
65 73
66#[derive(Clone, Debug, PartialEq, Eq)] 74impl Rule {
67pub(crate) struct Rule { 75 fn parse(src: &mut TtIter) -> Result<Rule, ParseError> {
68 pub(crate) lhs: Subtree, 76 let mut lhs = src
69 pub(crate) rhs: Subtree, 77 .expect_subtree()
70} 78 .map_err(|()| ParseError::Expected("expected subtree".to_string()))?
71 79 .clone();
72#[derive(Clone, Debug, PartialEq, Eq)] 80 validate(&lhs)?;
73pub(crate) enum TokenTree { 81 lhs.delimiter = tt::Delimiter::None;
74 Leaf(Leaf), 82 src.expect_char('=').map_err(|()| ParseError::Expected("expected `=`".to_string()))?;
75 Subtree(Subtree), 83 src.expect_char('>').map_err(|()| ParseError::Expected("expected `>`".to_string()))?;
76 Repeat(Repeat), 84 let mut rhs = src
77} 85 .expect_subtree()
78impl_froms!(TokenTree: Leaf, Subtree, Repeat); 86 .map_err(|()| ParseError::Expected("expected subtree".to_string()))?
79 87 .clone();
80#[derive(Clone, Debug, PartialEq, Eq)] 88 rhs.delimiter = tt::Delimiter::None;
81pub(crate) enum Leaf { 89 Ok(crate::Rule { lhs, rhs })
82 Literal(Literal), 90 }
83 Punct(Punct),
84 Ident(Ident),
85 Var(Var),
86}
87impl_froms!(Leaf: Literal, Punct, Ident, Var);
88
89#[derive(Clone, Debug, PartialEq, Eq)]
90pub(crate) struct Subtree {
91 pub(crate) delimiter: Delimiter,
92 pub(crate) token_trees: Vec<TokenTree>,
93}
94
95#[derive(Clone, Debug, Eq)]
96pub(crate) enum Separator {
97 Literal(tt::Literal),
98 Ident(tt::Ident),
99 Puncts(SmallVec<[tt::Punct; 3]>),
100} 91}
101 92
102// Note that when we compare a Separator, we just care about its textual value. 93fn validate(pattern: &tt::Subtree) -> Result<(), ParseError> {
103impl PartialEq for crate::Separator { 94 for op in parse_pattern(pattern) {
104 fn eq(&self, other: &crate::Separator) -> bool { 95 let op = match op {
105 use crate::Separator::*; 96 Ok(it) => it,
106 97 Err(e) => {
107 match (self, other) { 98 let msg = match e {
108 (Ident(ref a), Ident(ref b)) => a.text == b.text, 99 ExpandError::InvalidRepeat => "invalid repeat".to_string(),
109 (Literal(ref a), Literal(ref b)) => a.text == b.text, 100 _ => "invalid macro definition".to_string(),
110 (Puncts(ref a), Puncts(ref b)) if a.len() == b.len() => { 101 };
111 let a_iter = a.iter().map(|a| a.char); 102 return Err(ParseError::Expected(msg));
112 let b_iter = b.iter().map(|b| b.char); 103 }
113 a_iter.eq(b_iter) 104 };
105 match op {
106 Op::TokenTree(tt::TokenTree::Subtree(subtree)) | Op::Repeat { subtree, .. } => {
107 validate(subtree)?
114 } 108 }
115 _ => false, 109 _ => (),
116 } 110 }
117 } 111 }
118} 112 Ok(())
119
120#[derive(Clone, Debug, PartialEq, Eq)]
121pub(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)]
128pub(crate) enum RepeatKind {
129 ZeroOrMore,
130 OneOrMore,
131 ZeroOrOne,
132}
133
134#[derive(Clone, Debug, PartialEq, Eq)]
135pub(crate) struct Literal {
136 pub(crate) text: SmolStr,
137}
138
139#[derive(Clone, Debug, PartialEq, Eq)]
140pub(crate) struct Ident {
141 pub(crate) text: SmolStr,
142}
143
144#[derive(Clone, Debug, PartialEq, Eq)]
145pub(crate) struct Var {
146 pub(crate) text: SmolStr,
147 pub(crate) kind: Option<SmolStr>,
148} 113}
149 114
150#[cfg(test)] 115#[cfg(test)]