diff options
Diffstat (limited to 'src/grammar/mod.rs')
-rw-r--r-- | src/grammar/mod.rs | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/src/grammar/mod.rs b/src/grammar/mod.rs new file mode 100644 index 000000000..b558da477 --- /dev/null +++ b/src/grammar/mod.rs | |||
@@ -0,0 +1,141 @@ | |||
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 fn_item_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. | ||
24 | mod attributes; | ||
25 | mod expressions; | ||
26 | mod items; | ||
27 | mod params; | ||
28 | mod paths; | ||
29 | mod patterns; | ||
30 | mod type_args; | ||
31 | mod type_params; | ||
32 | mod types; | ||
33 | |||
34 | use { | ||
35 | parser_api::{CompletedMarker, Parser, TokenSet}, | ||
36 | SyntaxKind::{self, *}, | ||
37 | }; | ||
38 | |||
39 | pub(crate) fn file(p: &mut Parser) { | ||
40 | let file = p.start(); | ||
41 | p.eat(SHEBANG); | ||
42 | items::mod_contents(p, false); | ||
43 | file.complete(p, FILE); | ||
44 | } | ||
45 | |||
46 | fn visibility(p: &mut Parser) { | ||
47 | if p.at(PUB_KW) { | ||
48 | let vis = p.start(); | ||
49 | p.bump(); | ||
50 | if p.at(L_PAREN) { | ||
51 | match p.nth(1) { | ||
52 | // test crate_visibility | ||
53 | // pub(crate) struct S; | ||
54 | // pub(self) struct S; | ||
55 | // pub(self) struct S; | ||
56 | // pub(self) struct S; | ||
57 | CRATE_KW | SELF_KW | SUPER_KW => { | ||
58 | p.bump(); | ||
59 | p.bump(); | ||
60 | p.expect(R_PAREN); | ||
61 | } | ||
62 | IN_KW => { | ||
63 | p.bump(); | ||
64 | p.bump(); | ||
65 | paths::use_path(p); | ||
66 | p.expect(R_PAREN); | ||
67 | } | ||
68 | _ => (), | ||
69 | } | ||
70 | } | ||
71 | vis.complete(p, VISIBILITY); | ||
72 | } | ||
73 | } | ||
74 | |||
75 | fn alias(p: &mut Parser) -> bool { | ||
76 | if p.at(AS_KW) { | ||
77 | let alias = p.start(); | ||
78 | p.bump(); | ||
79 | name(p); | ||
80 | alias.complete(p, ALIAS); | ||
81 | } | ||
82 | true //FIXME: return false if three are errors | ||
83 | } | ||
84 | |||
85 | fn abi(p: &mut Parser) { | ||
86 | assert!(p.at(EXTERN_KW)); | ||
87 | let abi = p.start(); | ||
88 | p.bump(); | ||
89 | match p.current() { | ||
90 | STRING | RAW_STRING => p.bump(), | ||
91 | _ => (), | ||
92 | } | ||
93 | abi.complete(p, ABI); | ||
94 | } | ||
95 | |||
96 | fn fn_ret_type(p: &mut Parser) -> bool { | ||
97 | if p.at(THIN_ARROW) { | ||
98 | p.bump(); | ||
99 | types::type_(p); | ||
100 | true | ||
101 | } else { | ||
102 | false | ||
103 | } | ||
104 | } | ||
105 | |||
106 | fn name(p: &mut Parser) { | ||
107 | if p.at(IDENT) { | ||
108 | let m = p.start(); | ||
109 | p.bump(); | ||
110 | m.complete(p, NAME); | ||
111 | } else { | ||
112 | p.error("expected a name"); | ||
113 | } | ||
114 | } | ||
115 | |||
116 | fn name_ref(p: &mut Parser) { | ||
117 | if p.at(IDENT) { | ||
118 | let m = p.start(); | ||
119 | p.bump(); | ||
120 | m.complete(p, NAME_REF); | ||
121 | } else { | ||
122 | p.error("expected identifier"); | ||
123 | } | ||
124 | } | ||
125 | |||
126 | fn error_block(p: &mut Parser, message: &str) { | ||
127 | assert!(p.at(L_CURLY)); | ||
128 | let err = p.start(); | ||
129 | p.error(message); | ||
130 | p.bump(); | ||
131 | let mut level: u32 = 1; | ||
132 | while level > 0 && !p.at(EOF) { | ||
133 | match p.current() { | ||
134 | L_CURLY => level += 1, | ||
135 | R_CURLY => level -= 1, | ||
136 | _ => (), | ||
137 | } | ||
138 | p.bump(); | ||
139 | } | ||
140 | err.complete(p, ERROR); | ||
141 | } | ||