aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src/grammar/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_syntax/src/grammar/mod.rs')
-rw-r--r--crates/ra_syntax/src/grammar/mod.rs188
1 files changed, 188 insertions, 0 deletions
diff --git a/crates/ra_syntax/src/grammar/mod.rs b/crates/ra_syntax/src/grammar/mod.rs
new file mode 100644
index 000000000..2cb11dc1e
--- /dev/null
+++ b/crates/ra_syntax/src/grammar/mod.rs
@@ -0,0 +1,188 @@
1//! This is the actual "grammar" of the Rust language.
2//!
3//! Each function in this module and its children corresponds
4//! to a production of the format grammar. Submodules roughly
5//! correspond to different *areas* of the grammar. By convention,
6//! each submodule starts with `use super::*` import and exports
7//! "public" productions via `pub(super)`.
8//!
9//! See docs for `Parser` to learn about API, available to the grammar,
10//! and see docs for `Event` to learn how this actually manages to
11//! produce parse trees.
12//!
13//! Code in this module also contains inline tests, which start with
14//! `// test name-of-the-test` comment and look like this:
15//!
16//! ```
17//! // test function_with_zero_parameters
18//! // fn foo() {}
19//! ```
20//!
21//! After adding a new inline-test, run `cargo collect-tests` to extract
22//! it as a standalone text-fixture into `tests/data/parser/inline`, and
23//! run `cargo test` once to create the "gold" value.
24mod attributes;
25mod expressions;
26mod items;
27mod params;
28mod paths;
29mod patterns;
30mod type_args;
31mod type_params;
32mod types;
33
34use {
35 token_set::TokenSet,
36 parser_api::{Marker, CompletedMarker, Parser},
37 SyntaxKind::{self, *},
38};
39pub(crate) use self::{
40 expressions::{
41 block,
42 },
43 items::{
44 enum_variant_list,
45 extern_item_list,
46 impl_item_list,
47 match_arm_list,
48 mod_item_list,
49 named_field_def_list,
50 named_field_list,
51 token_tree,
52 trait_item_list,
53 use_tree_list,
54 },
55};
56
57pub(crate) fn root(p: &mut Parser) {
58 let m = p.start();
59 p.eat(SHEBANG);
60 items::mod_contents(p, false);
61 m.complete(p, ROOT);
62}
63
64
65#[derive(Clone, Copy, PartialEq, Eq)]
66enum BlockLike {
67 Block,
68 NotBlock,
69}
70
71impl BlockLike {
72 fn is_block(self) -> bool { self == BlockLike::Block }
73}
74
75fn opt_visibility(p: &mut Parser) {
76 match p.current() {
77 PUB_KW => {
78 let m = p.start();
79 p.bump();
80 if p.at(L_PAREN) {
81 match p.nth(1) {
82 // test crate_visibility
83 // pub(crate) struct S;
84 // pub(self) struct S;
85 // pub(self) struct S;
86 // pub(self) struct S;
87 CRATE_KW | SELF_KW | SUPER_KW => {
88 p.bump();
89 p.bump();
90 p.expect(R_PAREN);
91 }
92 IN_KW => {
93 p.bump();
94 p.bump();
95 paths::use_path(p);
96 p.expect(R_PAREN);
97 }
98 _ => (),
99 }
100 }
101 m.complete(p, VISIBILITY);
102 }
103 // test crate_keyword_vis
104 // crate fn main() { }
105 CRATE_KW => {
106 let m = p.start();
107 p.bump();
108 m.complete(p, VISIBILITY);
109 }
110 _ => (),
111 }
112}
113
114fn opt_alias(p: &mut Parser) {
115 if p.at(AS_KW) {
116 let m = p.start();
117 p.bump();
118 name(p);
119 m.complete(p, ALIAS);
120 }
121}
122
123fn abi(p: &mut Parser) {
124 assert!(p.at(EXTERN_KW));
125 let abi = p.start();
126 p.bump();
127 match p.current() {
128 STRING | RAW_STRING => p.bump(),
129 _ => (),
130 }
131 abi.complete(p, ABI);
132}
133
134fn opt_fn_ret_type(p: &mut Parser) -> bool {
135 if p.at(THIN_ARROW) {
136 let m = p.start();
137 p.bump();
138 types::type_(p);
139 m.complete(p, RET_TYPE);
140 true
141 } else {
142 false
143 }
144}
145
146fn name_r(p: &mut Parser, recovery: TokenSet) {
147 if p.at(IDENT) {
148 let m = p.start();
149 p.bump();
150 m.complete(p, NAME);
151 } else {
152 p.err_recover("expected a name", recovery);
153 }
154}
155
156fn name(p: &mut Parser) {
157 name_r(p, TokenSet::EMPTY)
158}
159
160fn name_ref(p: &mut Parser) {
161 if p.at(IDENT) {
162 let m = p.start();
163 p.bump();
164 m.complete(p, NAME_REF);
165 } else {
166 p.err_and_bump("expected identifier");
167 }
168}
169
170fn error_block(p: &mut Parser, message: &str) {
171 go(p, Some(message));
172 fn go(p: &mut Parser, message: Option<&str>) {
173 assert!(p.at(L_CURLY));
174 let m = p.start();
175 if let Some(message) = message {
176 p.error(message);
177 }
178 p.bump();
179 while !p.at(EOF) && !p.at(R_CURLY) {
180 match p.current() {
181 L_CURLY => go(p, None),
182 _ => p.bump(),
183 }
184 }
185 p.eat(R_CURLY);
186 m.complete(p, ERROR);
187 }
188}