diff options
Diffstat (limited to 'crates/ra_parser/src/grammar.rs')
-rw-r--r-- | crates/ra_parser/src/grammar.rs | 146 |
1 files changed, 72 insertions, 74 deletions
diff --git a/crates/ra_parser/src/grammar.rs b/crates/ra_parser/src/grammar.rs index dee3a229d..2bcbb4184 100644 --- a/crates/ra_parser/src/grammar.rs +++ b/crates/ra_parser/src/grammar.rs | |||
@@ -49,98 +49,96 @@ pub(crate) fn root(p: &mut Parser) { | |||
49 | m.complete(p, SOURCE_FILE); | 49 | m.complete(p, SOURCE_FILE); |
50 | } | 50 | } |
51 | 51 | ||
52 | pub(crate) fn macro_items(p: &mut Parser) { | 52 | /// Various pieces of syntax that can be parsed by macros by example |
53 | let m = p.start(); | 53 | pub(crate) mod fragments { |
54 | items::mod_contents(p, false); | 54 | use super::*; |
55 | m.complete(p, MACRO_ITEMS); | ||
56 | } | ||
57 | 55 | ||
58 | pub(crate) fn macro_stmts(p: &mut Parser) { | 56 | pub(crate) use super::{ |
59 | let m = p.start(); | 57 | expressions::block, paths::type_path as path, patterns::pattern, types::type_, |
60 | 58 | }; | |
61 | while !p.at(EOF) { | ||
62 | if p.current() == T![;] { | ||
63 | p.bump(); | ||
64 | continue; | ||
65 | } | ||
66 | 59 | ||
67 | expressions::stmt(p, expressions::StmtWithSemi::Optional); | 60 | pub(crate) fn expr(p: &mut Parser) { |
61 | let _ = expressions::expr(p); | ||
68 | } | 62 | } |
69 | 63 | ||
70 | m.complete(p, MACRO_STMTS); | 64 | pub(crate) fn stmt(p: &mut Parser, with_semi: bool) { |
71 | } | 65 | let with_semi = |
72 | 66 | if with_semi { expressions::StmtWithSemi::Yes } else { expressions::StmtWithSemi::No }; | |
73 | pub(crate) fn path(p: &mut Parser) { | ||
74 | paths::type_path(p); | ||
75 | } | ||
76 | 67 | ||
77 | pub(crate) fn expr(p: &mut Parser) { | 68 | expressions::stmt(p, with_semi) |
78 | expressions::expr(p); | 69 | } |
79 | } | ||
80 | 70 | ||
81 | pub(crate) fn type_(p: &mut Parser) { | 71 | pub(crate) fn opt_visibility(p: &mut Parser) { |
82 | types::type_(p) | 72 | let _ = super::opt_visibility(p); |
83 | } | 73 | } |
84 | 74 | ||
85 | pub(crate) fn pattern(p: &mut Parser) { | 75 | // Parse a meta item , which excluded [], e.g : #[ MetaItem ] |
86 | patterns::pattern(p) | 76 | pub(crate) fn meta_item(p: &mut Parser) { |
87 | } | 77 | fn is_delimiter(p: &mut Parser) -> bool { |
78 | match p.current() { | ||
79 | T!['{'] | T!['('] | T!['['] => true, | ||
80 | _ => false, | ||
81 | } | ||
82 | } | ||
88 | 83 | ||
89 | pub(crate) fn stmt(p: &mut Parser, with_semi: bool) { | 84 | if is_delimiter(p) { |
90 | let with_semi = | 85 | items::token_tree(p); |
91 | if with_semi { expressions::StmtWithSemi::Yes } else { expressions::StmtWithSemi::No }; | 86 | return; |
87 | } | ||
92 | 88 | ||
93 | expressions::stmt(p, with_semi) | 89 | let m = p.start(); |
94 | } | 90 | while !p.at(EOF) { |
91 | if is_delimiter(p) { | ||
92 | items::token_tree(p); | ||
93 | break; | ||
94 | } else { | ||
95 | // https://doc.rust-lang.org/reference/attributes.html | ||
96 | // https://doc.rust-lang.org/reference/paths.html#simple-paths | ||
97 | // The start of an meta must be a simple path | ||
98 | match p.current() { | ||
99 | IDENT | T![::] | T![super] | T![self] | T![crate] => p.bump(), | ||
100 | T![=] => { | ||
101 | p.bump(); | ||
102 | match p.current() { | ||
103 | c if c.is_literal() => p.bump(), | ||
104 | T![true] | T![false] => p.bump(), | ||
105 | _ => {} | ||
106 | } | ||
107 | break; | ||
108 | } | ||
109 | _ => break, | ||
110 | } | ||
111 | } | ||
112 | } | ||
95 | 113 | ||
96 | pub(crate) fn block(p: &mut Parser) { | 114 | m.complete(p, TOKEN_TREE); |
97 | expressions::block(p); | 115 | } |
98 | } | ||
99 | 116 | ||
100 | // Parse a meta item , which excluded [], e.g : #[ MetaItem ] | 117 | pub(crate) fn item(p: &mut Parser) { |
101 | pub(crate) fn meta_item(p: &mut Parser) { | 118 | items::item_or_macro(p, true, items::ItemFlavor::Mod) |
102 | fn is_delimiter(p: &mut Parser) -> bool { | ||
103 | match p.current() { | ||
104 | T!['{'] | T!['('] | T!['['] => true, | ||
105 | _ => false, | ||
106 | } | ||
107 | } | 119 | } |
108 | 120 | ||
109 | if is_delimiter(p) { | 121 | pub(crate) fn macro_items(p: &mut Parser) { |
110 | items::token_tree(p); | 122 | let m = p.start(); |
111 | return; | 123 | items::mod_contents(p, false); |
124 | m.complete(p, MACRO_ITEMS); | ||
112 | } | 125 | } |
113 | 126 | ||
114 | let m = p.start(); | 127 | pub(crate) fn macro_stmts(p: &mut Parser) { |
115 | while !p.at(EOF) { | 128 | let m = p.start(); |
116 | if is_delimiter(p) { | 129 | |
117 | items::token_tree(p); | 130 | while !p.at(EOF) { |
118 | break; | 131 | if p.current() == T![;] { |
119 | } else { | 132 | p.bump(); |
120 | // https://doc.rust-lang.org/reference/attributes.html | 133 | continue; |
121 | // https://doc.rust-lang.org/reference/paths.html#simple-paths | ||
122 | // The start of an meta must be a simple path | ||
123 | match p.current() { | ||
124 | IDENT | T![::] | T![super] | T![self] | T![crate] => p.bump(), | ||
125 | T![=] => { | ||
126 | p.bump(); | ||
127 | match p.current() { | ||
128 | c if c.is_literal() => p.bump(), | ||
129 | T![true] | T![false] => p.bump(), | ||
130 | _ => {} | ||
131 | } | ||
132 | break; | ||
133 | } | ||
134 | _ => break, | ||
135 | } | 134 | } |
135 | |||
136 | expressions::stmt(p, expressions::StmtWithSemi::Optional); | ||
136 | } | 137 | } |
137 | } | ||
138 | 138 | ||
139 | m.complete(p, TOKEN_TREE); | 139 | m.complete(p, MACRO_STMTS); |
140 | } | 140 | } |
141 | 141 | ||
142 | pub(crate) fn item(p: &mut Parser) { | ||
143 | items::item_or_macro(p, true, items::ItemFlavor::Mod) | ||
144 | } | 142 | } |
145 | 143 | ||
146 | pub(crate) fn reparser( | 144 | pub(crate) fn reparser( |
@@ -180,7 +178,7 @@ impl BlockLike { | |||
180 | } | 178 | } |
181 | } | 179 | } |
182 | 180 | ||
183 | pub(crate) fn opt_visibility(p: &mut Parser) -> bool { | 181 | fn opt_visibility(p: &mut Parser) -> bool { |
184 | match p.current() { | 182 | match p.current() { |
185 | T![pub] => { | 183 | T![pub] => { |
186 | let m = p.start(); | 184 | let m = p.start(); |