aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_parser/src/grammar
diff options
context:
space:
mode:
authorEdwin Cheng <[email protected]>2019-04-17 05:34:43 +0100
committerEdwin Cheng <[email protected]>2019-04-17 05:34:43 +0100
commit57e4122b890d56c11f9d74c1bdfed40f186331a4 (patch)
tree5ce7ba4ec6fbf9ce8a25bfe2877abc78dd4e9f45 /crates/ra_parser/src/grammar
parent546d9be2a7bf7b3942c125f922a01321aea6ad26 (diff)
Add mbe stmt matcher
Diffstat (limited to 'crates/ra_parser/src/grammar')
-rw-r--r--crates/ra_parser/src/grammar/expressions.rs154
1 files changed, 82 insertions, 72 deletions
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs
index 295577325..06f2b45b1 100644
--- a/crates/ra_parser/src/grammar/expressions.rs
+++ b/crates/ra_parser/src/grammar/expressions.rs
@@ -48,88 +48,77 @@ fn is_expr_stmt_attr_allowed(kind: SyntaxKind) -> bool {
48 } 48 }
49} 49}
50 50
51pub(crate) fn expr_block_contents(p: &mut Parser) { 51pub(super) fn stmt(p: &mut Parser, with_semi: bool) {
52 // This is checked by a validator 52 // test block_items
53 attributes::inner_attributes(p); 53 // fn a() { fn b() {} }
54 54 let m = p.start();
55 while !p.at(EOF) && !p.at(R_CURLY) { 55 // test attr_on_expr_stmt
56 // test nocontentexpr 56 // fn foo() {
57 // fn foo(){ 57 // #[A] foo();
58 // ;;;some_expr();;;;{;;;};;;;Ok(()) 58 // #[B] bar!{}
59 // } 59 // #[C] #[D] {}
60 if p.current() == SEMI { 60 // #[D] return ();
61 p.bump(); 61 // }
62 continue; 62 let has_attrs = p.at(POUND);
63 } 63 attributes::outer_attributes(p);
64 64
65 // test block_items 65 if p.at(LET_KW) {
66 // fn a() { fn b() {} } 66 let_stmt(p, m, with_semi);
67 let m = p.start(); 67 return;
68 // test attr_on_expr_stmt 68 }
69 // fn foo() {
70 // #[A] foo();
71 // #[B] bar!{}
72 // #[C] #[D] {}
73 // #[D] return ();
74 // }
75 let has_attrs = p.at(POUND);
76 attributes::outer_attributes(p);
77 if p.at(LET_KW) {
78 let_stmt(p, m);
79 continue;
80 }
81 69
82 let m = match items::maybe_item(p, m, items::ItemFlavor::Mod) { 70 let m = match items::maybe_item(p, m, items::ItemFlavor::Mod) {
83 Ok(()) => continue, 71 Ok(()) => return,
84 Err(m) => m, 72 Err(m) => m,
85 }; 73 };
86 74
87 let (cm, blocklike) = expr_stmt(p); 75 let (cm, blocklike) = expr_stmt(p);
88 let kind = cm.as_ref().map(|cm| cm.kind()).unwrap_or(ERROR); 76 let kind = cm.as_ref().map(|cm| cm.kind()).unwrap_or(ERROR);
89 77
90 if has_attrs && !is_expr_stmt_attr_allowed(kind) { 78 if has_attrs && !is_expr_stmt_attr_allowed(kind) {
91 // test_err attr_on_expr_not_allowed 79 // test_err attr_on_expr_not_allowed
92 // fn foo() { 80 // fn foo() {
93 // #[A] 1 + 2; 81 // #[A] 1 + 2;
94 // #[B] if true {}; 82 // #[B] if true {};
95 // } 83 // }
96 p.error(format!("attributes are not allowed on {:?}", kind)); 84 p.error(format!("attributes are not allowed on {:?}", kind));
97 } 85 }
98 86
99 if p.at(R_CURLY) { 87 if p.at(R_CURLY) {
100 // test attr_on_last_expr_in_block 88 // test attr_on_last_expr_in_block
101 // fn foo() { 89 // fn foo() {
102 // { #[A] bar!()? } 90 // { #[A] bar!()? }
103 // #[B] &() 91 // #[B] &()
104 // } 92 // }
105 if let Some(cm) = cm { 93 if let Some(cm) = cm {
106 cm.undo_completion(p).abandon(p); 94 cm.undo_completion(p).abandon(p);
107 m.complete(p, kind); 95 m.complete(p, kind);
108 } else {
109 m.abandon(p);
110 }
111 } else { 96 } else {
112 // test no_semi_after_block 97 m.abandon(p);
113 // fn foo() { 98 }
114 // if true {} 99 } else {
115 // loop {} 100 // test no_semi_after_block
116 // match () {} 101 // fn foo() {
117 // while true {} 102 // if true {}
118 // for _ in () {} 103 // loop {}
119 // {} 104 // match () {}
120 // {} 105 // while true {}
121 // macro_rules! test { 106 // for _ in () {}
122 // () => {} 107 // {}
123 // } 108 // {}
124 // test!{} 109 // macro_rules! test {
125 // } 110 // () => {}
111 // }
112 // test!{}
113 // }
114 if with_semi {
126 if blocklike.is_block() { 115 if blocklike.is_block() {
127 p.eat(SEMI); 116 p.eat(SEMI);
128 } else { 117 } else {
129 p.expect(SEMI); 118 p.expect(SEMI);
130 } 119 }
131 m.complete(p, EXPR_STMT);
132 } 120 }
121 m.complete(p, EXPR_STMT);
133 } 122 }
134 123
135 // test let_stmt; 124 // test let_stmt;
@@ -139,7 +128,7 @@ pub(crate) fn expr_block_contents(p: &mut Parser) {
139 // let c = 92; 128 // let c = 92;
140 // let d: i32 = 92; 129 // let d: i32 = 92;
141 // } 130 // }
142 fn let_stmt(p: &mut Parser, m: Marker) { 131 fn let_stmt(p: &mut Parser, m: Marker, with_semi: bool) {
143 assert!(p.at(LET_KW)); 132 assert!(p.at(LET_KW));
144 p.bump(); 133 p.bump();
145 patterns::pattern(p); 134 patterns::pattern(p);
@@ -149,11 +138,32 @@ pub(crate) fn expr_block_contents(p: &mut Parser) {
149 if p.eat(EQ) { 138 if p.eat(EQ) {
150 expressions::expr(p); 139 expressions::expr(p);
151 } 140 }
152 p.expect(SEMI); 141
142 if with_semi {
143 p.expect(SEMI);
144 }
153 m.complete(p, LET_STMT); 145 m.complete(p, LET_STMT);
154 } 146 }
155} 147}
156 148
149pub(crate) fn expr_block_contents(p: &mut Parser) {
150 // This is checked by a validator
151 attributes::inner_attributes(p);
152
153 while !p.at(EOF) && !p.at(R_CURLY) {
154 // test nocontentexpr
155 // fn foo(){
156 // ;;;some_expr();;;;{;;;};;;;Ok(())
157 // }
158 if p.current() == SEMI {
159 p.bump();
160 continue;
161 }
162
163 stmt(p, true)
164 }
165}
166
157#[derive(Clone, Copy)] 167#[derive(Clone, Copy)]
158struct Restrictions { 168struct Restrictions {
159 forbid_structs: bool, 169 forbid_structs: bool,