aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_macros
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-01-31 18:09:43 +0000
committerAleksey Kladov <[email protected]>2019-01-31 20:23:30 +0000
commit40feacdeb90786b49ea9e0510ba22ff7af79e020 (patch)
tree294162ffb99480a5f150b9718675a954a4ac0f0a /crates/ra_macros
parentad80a0c551458de7d27a98d182d7f559de04f291 (diff)
split macros across crates
Diffstat (limited to 'crates/ra_macros')
-rw-r--r--crates/ra_macros/Cargo.toml9
-rw-r--r--crates/ra_macros/src/lib.rs17
-rw-r--r--crates/ra_macros/src/mbe.rs72
-rw-r--r--crates/ra_macros/src/mbe_expander.rs169
-rw-r--r--crates/ra_macros/src/mbe_parser.rs94
-rw-r--r--crates/ra_macros/src/tt.rs119
-rw-r--r--crates/ra_macros/src/tt_cursor.rs93
7 files changed, 0 insertions, 573 deletions
diff --git a/crates/ra_macros/Cargo.toml b/crates/ra_macros/Cargo.toml
deleted file mode 100644
index 7d3cb055c..000000000
--- a/crates/ra_macros/Cargo.toml
+++ /dev/null
@@ -1,9 +0,0 @@
1[package]
2edition = "2018"
3name = "ra_macros"
4version = "0.1.0"
5authors = ["Aleksey Kladov <[email protected]>"]
6
7[dependencies]
8rustc-hash = "1.0.0"
9smol_str = "0.1.9"
diff --git a/crates/ra_macros/src/lib.rs b/crates/ra_macros/src/lib.rs
deleted file mode 100644
index e35a056cc..000000000
--- a/crates/ra_macros/src/lib.rs
+++ /dev/null
@@ -1,17 +0,0 @@
1macro_rules! impl_froms {
2 ($e:ident: $($v:ident), *) => {
3 $(
4 impl From<$v> for $e {
5 fn from(it: $v) -> $e {
6 $e::$v(it)
7 }
8 }
9 )*
10 }
11}
12
13pub mod tt;
14pub mod mbe;
15mod tt_cursor;
16mod mbe_parser;
17mod mbe_expander;
diff --git a/crates/ra_macros/src/mbe.rs b/crates/ra_macros/src/mbe.rs
deleted file mode 100644
index d4106a41c..000000000
--- a/crates/ra_macros/src/mbe.rs
+++ /dev/null
@@ -1,72 +0,0 @@
1use smol_str::SmolStr;
2
3pub(crate) use crate::tt::{Delimiter, Punct};
4
5pub use crate::{
6 mbe_parser::parse,
7 mbe_expander::exapnd,
8};
9
10#[derive(Debug)]
11pub struct MacroRules {
12 pub(crate) rules: Vec<Rule>,
13}
14
15#[derive(Debug)]
16pub(crate) struct Rule {
17 pub(crate) lhs: Subtree,
18 pub(crate) rhs: Subtree,
19}
20
21#[derive(Debug)]
22pub(crate) enum TokenTree {
23 Leaf(Leaf),
24 Subtree(Subtree),
25 Repeat(Repeat),
26}
27impl_froms!(TokenTree: Leaf, Subtree, Repeat);
28
29#[derive(Debug)]
30pub(crate) enum Leaf {
31 Literal(Literal),
32 Punct(Punct),
33 Ident(Ident),
34 Var(Var),
35}
36impl_froms!(Leaf: Literal, Punct, Ident, Var);
37
38#[derive(Debug)]
39pub(crate) struct Subtree {
40 pub(crate) delimiter: Delimiter,
41 pub(crate) token_trees: Vec<TokenTree>,
42}
43
44#[derive(Debug)]
45pub(crate) struct Repeat {
46 pub(crate) subtree: Subtree,
47 pub(crate) kind: RepeatKind,
48 pub(crate) separator: Option<char>,
49}
50
51#[derive(Debug)]
52pub(crate) enum RepeatKind {
53 ZeroOrMore,
54 OneOrMore,
55 ZeroOrOne,
56}
57
58#[derive(Debug)]
59pub(crate) struct Literal {
60 pub(crate) text: SmolStr,
61}
62
63#[derive(Debug)]
64pub(crate) struct Ident {
65 pub(crate) text: SmolStr,
66}
67
68#[derive(Debug)]
69pub(crate) struct Var {
70 pub(crate) text: SmolStr,
71 pub(crate) kind: Option<SmolStr>,
72}
diff --git a/crates/ra_macros/src/mbe_expander.rs b/crates/ra_macros/src/mbe_expander.rs
deleted file mode 100644
index 5d5363261..000000000
--- a/crates/ra_macros/src/mbe_expander.rs
+++ /dev/null
@@ -1,169 +0,0 @@
1use rustc_hash::FxHashMap;
2use smol_str::SmolStr;
3
4use crate::{mbe, tt, tt_cursor::TtCursor};
5
6pub fn exapnd(rules: &mbe::MacroRules, input: &tt::Subtree) -> Option<tt::Subtree> {
7 rules.rules.iter().find_map(|it| expand_rule(it, input))
8}
9
10fn expand_rule(rule: &mbe::Rule, input: &tt::Subtree) -> Option<tt::Subtree> {
11 let mut input = TtCursor::new(input);
12 let bindings = match_lhs(&rule.lhs, &mut input)?;
13 expand_subtree(&rule.rhs, &bindings, &mut Vec::new())
14}
15
16#[derive(Debug, Default)]
17struct Bindings {
18 inner: FxHashMap<SmolStr, Binding>,
19}
20
21#[derive(Debug)]
22enum Binding {
23 Simple(tt::TokenTree),
24 Nested(Vec<Binding>),
25}
26
27impl Bindings {
28 fn get(&self, name: &SmolStr, nesting: &[usize]) -> Option<&tt::TokenTree> {
29 let mut b = self.inner.get(name)?;
30 for &idx in nesting.iter() {
31 b = match b {
32 Binding::Simple(_) => break,
33 Binding::Nested(bs) => bs.get(idx)?,
34 };
35 }
36 match b {
37 Binding::Simple(it) => Some(it),
38 Binding::Nested(_) => None,
39 }
40 }
41 fn push_nested(&mut self, nested: Bindings) -> Option<()> {
42 for (key, value) in nested.inner {
43 if !self.inner.contains_key(&key) {
44 self.inner.insert(key.clone(), Binding::Nested(Vec::new()));
45 }
46 match self.inner.get_mut(&key) {
47 Some(Binding::Nested(it)) => it.push(value),
48 _ => return None,
49 }
50 }
51 Some(())
52 }
53}
54
55fn match_lhs(pattern: &mbe::Subtree, input: &mut TtCursor) -> Option<Bindings> {
56 let mut res = Bindings::default();
57 for pat in pattern.token_trees.iter() {
58 match pat {
59 mbe::TokenTree::Leaf(leaf) => match leaf {
60 mbe::Leaf::Var(mbe::Var { text, kind }) => {
61 let kind = kind.clone()?;
62 match kind.as_str() {
63 "ident" => {
64 let ident = input.eat_ident()?.clone();
65 res.inner.insert(
66 text.clone(),
67 Binding::Simple(tt::Leaf::from(ident).into()),
68 );
69 }
70 _ => return None,
71 }
72 }
73 mbe::Leaf::Punct(punct) => {
74 if input.eat_punct()? != punct {
75 return None;
76 }
77 }
78 _ => return None,
79 },
80 mbe::TokenTree::Repeat(mbe::Repeat {
81 subtree,
82 kind: _,
83 separator,
84 }) => {
85 while let Some(nested) = match_lhs(subtree, input) {
86 res.push_nested(nested)?;
87 if separator.is_some() && !input.is_eof() {
88 input.eat_punct()?;
89 }
90 }
91 }
92 _ => {}
93 }
94 }
95 Some(res)
96}
97
98/*
99
100macro_rules! impl_froms {
101 ($e:ident: $($v:ident),*) => {
102 $(
103 impl From<$v> for $e {
104 fn from(it: $v) -> $e {
105 $e::$v(it)
106 }
107 }
108 )*
109 }
110}
111
112impl_froms! (Foo: Bar, Baz)
113
114*/
115
116fn expand_subtree(
117 template: &mbe::Subtree,
118 bindings: &Bindings,
119 nesting: &mut Vec<usize>,
120) -> Option<tt::Subtree> {
121 let token_trees = template
122 .token_trees
123 .iter()
124 .map(|it| expand_tt(it, bindings, nesting))
125 .collect::<Option<Vec<_>>>()?;
126
127 Some(tt::Subtree {
128 token_trees,
129 delimiter: template.delimiter,
130 })
131}
132
133fn expand_tt(
134 template: &mbe::TokenTree,
135 bindings: &Bindings,
136 nesting: &mut Vec<usize>,
137) -> Option<tt::TokenTree> {
138 let res: tt::TokenTree = match template {
139 mbe::TokenTree::Subtree(subtree) => expand_subtree(subtree, bindings, nesting)?.into(),
140 mbe::TokenTree::Repeat(repeat) => {
141 let mut token_trees = Vec::new();
142 nesting.push(0);
143 while let Some(t) = expand_subtree(&repeat.subtree, bindings, nesting) {
144 let idx = nesting.pop().unwrap();
145 nesting.push(idx + 1);
146 token_trees.push(t.into())
147 }
148 nesting.pop().unwrap();
149 tt::Subtree {
150 token_trees,
151 delimiter: tt::Delimiter::None,
152 }
153 .into()
154 }
155 mbe::TokenTree::Leaf(leaf) => match leaf {
156 mbe::Leaf::Ident(ident) => tt::Leaf::from(tt::Ident {
157 text: ident.text.clone(),
158 })
159 .into(),
160 mbe::Leaf::Punct(punct) => tt::Leaf::from(punct.clone()).into(),
161 mbe::Leaf::Var(v) => bindings.get(&v.text, nesting)?.clone(),
162 mbe::Leaf::Literal(l) => tt::Leaf::from(tt::Literal {
163 text: l.text.clone(),
164 })
165 .into(),
166 },
167 };
168 Some(res)
169}
diff --git a/crates/ra_macros/src/mbe_parser.rs b/crates/ra_macros/src/mbe_parser.rs
deleted file mode 100644
index 483594590..000000000
--- a/crates/ra_macros/src/mbe_parser.rs
+++ /dev/null
@@ -1,94 +0,0 @@
1use crate::{tt, mbe};
2use crate::tt_cursor::TtCursor;
3
4/// This module parses a raw `tt::TokenStream` into macro-by-example token
5/// stream. This is a *mostly* identify function, expect for handling of
6/// `$var:tt_kind` and `$(repeat),*` constructs.
7
8pub fn parse(tt: &tt::Subtree) -> Option<mbe::MacroRules> {
9 let mut parser = TtCursor::new(tt);
10 let mut rules = Vec::new();
11 while !parser.is_eof() {
12 rules.push(parse_rule(&mut parser)?)
13 }
14 Some(mbe::MacroRules { rules })
15}
16
17fn parse_rule(p: &mut TtCursor) -> Option<mbe::Rule> {
18 let lhs = parse_subtree(p.eat_subtree()?)?;
19 p.expect_char('=')?;
20 p.expect_char('>')?;
21 let rhs = parse_subtree(p.eat_subtree()?)?;
22 Some(mbe::Rule { lhs, rhs })
23}
24
25fn parse_subtree(tt: &tt::Subtree) -> Option<mbe::Subtree> {
26 let mut token_trees = Vec::new();
27 let mut p = TtCursor::new(tt);
28 while let Some(tt) = p.eat() {
29 let child: mbe::TokenTree = match tt {
30 tt::TokenTree::Leaf(leaf) => match leaf {
31 tt::Leaf::Punct(tt::Punct { char: '$', .. }) => {
32 if p.at_ident().is_some() {
33 mbe::Leaf::from(parse_var(&mut p)?).into()
34 } else {
35 parse_repeat(&mut p)?.into()
36 }
37 }
38 tt::Leaf::Punct(punct) => mbe::Leaf::from(*punct).into(),
39 tt::Leaf::Ident(tt::Ident { text }) => {
40 mbe::Leaf::from(mbe::Ident { text: text.clone() }).into()
41 }
42 tt::Leaf::Literal(tt::Literal { text }) => {
43 mbe::Leaf::from(mbe::Literal { text: text.clone() }).into()
44 }
45 },
46 tt::TokenTree::Subtree(subtree) => parse_subtree(subtree)?.into(),
47 };
48 token_trees.push(child);
49 }
50 Some(mbe::Subtree {
51 token_trees,
52 delimiter: tt.delimiter,
53 })
54}
55
56fn parse_var(p: &mut TtCursor) -> Option<mbe::Var> {
57 let ident = p.eat_ident().unwrap();
58 let text = ident.text.clone();
59 let kind = if p.at_char(':') {
60 p.bump();
61 if let Some(ident) = p.eat_ident() {
62 Some(ident.text.clone())
63 } else {
64 p.rev_bump();
65 None
66 }
67 } else {
68 None
69 };
70 Some(mbe::Var { text, kind })
71}
72
73fn parse_repeat(p: &mut TtCursor) -> Option<mbe::Repeat> {
74 let subtree = p.eat_subtree().unwrap();
75 let subtree = parse_subtree(subtree)?;
76 let sep = p.eat_punct()?;
77 let (separator, rep) = match sep.char {
78 '*' | '+' | '?' => (None, sep.char),
79 char => (Some(char), p.eat_punct()?.char),
80 };
81
82 let kind = match rep {
83 '*' => mbe::RepeatKind::ZeroOrMore,
84 '+' => mbe::RepeatKind::OneOrMore,
85 '?' => mbe::RepeatKind::ZeroOrOne,
86 _ => return None,
87 };
88 p.bump();
89 Some(mbe::Repeat {
90 subtree,
91 kind,
92 separator,
93 })
94}
diff --git a/crates/ra_macros/src/tt.rs b/crates/ra_macros/src/tt.rs
deleted file mode 100644
index 2855bae51..000000000
--- a/crates/ra_macros/src/tt.rs
+++ /dev/null
@@ -1,119 +0,0 @@
1use std::fmt;
2
3use smol_str::SmolStr;
4
5#[derive(Debug, Clone)]
6pub enum TokenTree {
7 Leaf(Leaf),
8 Subtree(Subtree),
9}
10impl_froms!(TokenTree: Leaf, Subtree);
11
12#[derive(Debug, Clone)]
13pub enum Leaf {
14 Literal(Literal),
15 Punct(Punct),
16 Ident(Ident),
17}
18impl_froms!(Leaf: Literal, Punct, Ident);
19
20#[derive(Debug, Clone)]
21pub struct Subtree {
22 pub delimiter: Delimiter,
23 pub token_trees: Vec<TokenTree>,
24}
25
26#[derive(Clone, Copy, Debug)]
27pub enum Delimiter {
28 Parenthesis,
29 Brace,
30 Bracket,
31 None,
32}
33
34#[derive(Debug, Clone)]
35pub struct Literal {
36 pub text: SmolStr,
37}
38
39#[derive(Debug, Clone, Copy, PartialEq, Eq)]
40pub struct Punct {
41 pub char: char,
42 pub spacing: Spacing,
43}
44
45#[derive(Debug, Clone, Copy, PartialEq, Eq)]
46pub enum Spacing {
47 Alone,
48 Joint,
49}
50
51#[derive(Debug, Clone)]
52pub struct Ident {
53 pub text: SmolStr,
54}
55
56impl fmt::Display for TokenTree {
57 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
58 match self {
59 TokenTree::Leaf(it) => fmt::Display::fmt(it, f),
60 TokenTree::Subtree(it) => fmt::Display::fmt(it, f),
61 }
62 }
63}
64
65impl fmt::Display for Subtree {
66 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
67 let (l, r) = match self.delimiter {
68 Delimiter::Parenthesis => ("(", ")"),
69 Delimiter::Brace => ("{", "}"),
70 Delimiter::Bracket => ("[", "]"),
71 Delimiter::None => ("", ""),
72 };
73 f.write_str(l)?;
74 let mut needs_space = false;
75 for tt in self.token_trees.iter() {
76 if needs_space {
77 f.write_str(" ")?;
78 }
79 needs_space = true;
80 match tt {
81 TokenTree::Leaf(Leaf::Punct(p)) => {
82 needs_space = p.spacing == Spacing::Alone;
83 fmt::Display::fmt(p, f)?
84 }
85 tt => fmt::Display::fmt(tt, f)?,
86 }
87 }
88 f.write_str(r)?;
89 Ok(())
90 }
91}
92
93impl fmt::Display for Leaf {
94 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
95 match self {
96 Leaf::Ident(it) => fmt::Display::fmt(it, f),
97 Leaf::Literal(it) => fmt::Display::fmt(it, f),
98 Leaf::Punct(it) => fmt::Display::fmt(it, f),
99 }
100 }
101}
102
103impl fmt::Display for Ident {
104 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
105 fmt::Display::fmt(&self.text, f)
106 }
107}
108
109impl fmt::Display for Literal {
110 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
111 fmt::Display::fmt(&self.text, f)
112 }
113}
114
115impl fmt::Display for Punct {
116 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
117 fmt::Display::fmt(&self.char, f)
118 }
119}
diff --git a/crates/ra_macros/src/tt_cursor.rs b/crates/ra_macros/src/tt_cursor.rs
deleted file mode 100644
index 046770a0f..000000000
--- a/crates/ra_macros/src/tt_cursor.rs
+++ /dev/null
@@ -1,93 +0,0 @@
1use crate::tt;
2
3#[derive(Clone)]
4pub(crate) struct TtCursor<'a> {
5 subtree: &'a tt::Subtree,
6 pos: usize,
7}
8
9impl<'a> TtCursor<'a> {
10 pub(crate) fn new(subtree: &'a tt::Subtree) -> TtCursor<'a> {
11 TtCursor { subtree, pos: 0 }
12 }
13
14 pub(crate) fn is_eof(&self) -> bool {
15 self.pos == self.subtree.token_trees.len()
16 }
17
18 pub(crate) fn current(&self) -> Option<&'a tt::TokenTree> {
19 self.subtree.token_trees.get(self.pos)
20 }
21
22 pub(crate) fn at_punct(&self) -> Option<&'a tt::Punct> {
23 match self.current() {
24 Some(tt::TokenTree::Leaf(tt::Leaf::Punct(it))) => Some(it),
25 _ => None,
26 }
27 }
28
29 pub(crate) fn at_char(&self, char: char) -> bool {
30 match self.at_punct() {
31 Some(tt::Punct { char: c, .. }) if *c == char => true,
32 _ => false,
33 }
34 }
35
36 pub(crate) fn at_ident(&mut self) -> Option<&'a tt::Ident> {
37 match self.current() {
38 Some(tt::TokenTree::Leaf(tt::Leaf::Ident(i))) => Some(i),
39 _ => None,
40 }
41 }
42
43 pub(crate) fn bump(&mut self) {
44 self.pos += 1;
45 }
46 pub(crate) fn rev_bump(&mut self) {
47 self.pos -= 1;
48 }
49
50 pub(crate) fn eat(&mut self) -> Option<&'a tt::TokenTree> {
51 match self.current() {
52 Some(it) => {
53 self.bump();
54 Some(it)
55 }
56 None => None,
57 }
58 }
59
60 pub(crate) fn eat_subtree(&mut self) -> Option<&'a tt::Subtree> {
61 match self.current()? {
62 tt::TokenTree::Subtree(sub) => {
63 self.bump();
64 Some(sub)
65 }
66 _ => return None,
67 }
68 }
69
70 pub(crate) fn eat_punct(&mut self) -> Option<&'a tt::Punct> {
71 if let Some(it) = self.at_punct() {
72 self.bump();
73 return Some(it);
74 }
75 None
76 }
77
78 pub(crate) fn eat_ident(&mut self) -> Option<&'a tt::Ident> {
79 if let Some(i) = self.at_ident() {
80 self.bump();
81 return Some(i);
82 }
83 None
84 }
85
86 pub(crate) fn expect_char(&mut self, char: char) -> Option<()> {
87 if self.at_char(char) {
88 self.bump();
89 return Some(());
90 }
91 None
92 }
93}