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