1pub mod element_type;
3
4use crate::{
5 language::MsilLanguage,
6 lexer::{MsilLexer, token_type::MsilTokenType},
7};
8use oak_core::{
9 TextEdit,
10 parser::{ParseCache, Parser, ParserState, parse_with_lexer},
11 source::Source,
12};
13
14pub(crate) type State<'a, S> = ParserState<'a, MsilLanguage, S>;
15
16pub struct MsilParser<'config> {
18 pub(crate) config: &'config MsilLanguage,
19}
20
21impl<'config> MsilParser<'config> {
22 pub fn new(config: &'config MsilLanguage) -> Self {
24 Self { config }
25 }
26
27 fn skip_trivia<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) {
28 while let Some(kind) = state.peek_kind() {
29 if kind == MsilTokenType::Whitespace || kind == MsilTokenType::CommentToken {
30 state.bump();
31 }
32 else {
33 break;
34 }
35 }
36 }
37
38 fn parse_assembly<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) {
39 let cp = state.checkpoint();
40 state.bump(); self.skip_trivia(state);
42
43 let is_extern = if state.at(MsilTokenType::ExternKeyword) {
44 state.bump(); self.skip_trivia(state);
46 true
47 }
48 else {
49 false
50 };
51
52 if state.at(MsilTokenType::IdentifierToken) {
53 let id_cp = state.checkpoint();
54 state.bump();
55 state.finish_at(id_cp, crate::parser::element_type::MsilElementType::Identifier);
56 self.skip_trivia(state);
57 }
58
59 if state.at(MsilTokenType::LeftBrace) {
60 state.bump();
61 while state.not_at_end() && !state.at(MsilTokenType::RightBrace) {
62 state.bump();
63 }
64 if state.at(MsilTokenType::RightBrace) {
65 state.bump();
66 }
67 }
68
69 if is_extern {
70 state.finish_at(cp, crate::parser::element_type::MsilElementType::AssemblyExtern);
71 }
72 else {
73 state.finish_at(cp, crate::parser::element_type::MsilElementType::Assembly);
74 }
75 }
76
77 fn parse_module<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) {
78 let cp = state.checkpoint();
79 state.bump(); self.skip_trivia(state);
81 while state.not_at_end() && !state.at(MsilTokenType::Semicolon) && !state.at(MsilTokenType::Eof) {
82 if state.at(MsilTokenType::IdentifierToken) {
83 let id_cp = state.checkpoint();
84 state.bump();
85 state.finish_at(id_cp, crate::parser::element_type::MsilElementType::Identifier);
86 self.skip_trivia(state);
87 }
88 else {
89 state.bump();
90 }
91 }
92 state.finish_at(cp, crate::parser::element_type::MsilElementType::Module);
93 }
94
95 fn parse_class<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) {
96 let cp = state.checkpoint();
97 state.bump(); self.skip_trivia(state);
99
100 while state.at(MsilTokenType::PublicKeyword) || state.at(MsilTokenType::PrivateKeyword) || state.at(MsilTokenType::StaticKeyword) || state.at(MsilTokenType::Keyword) {
102 state.bump();
103 self.skip_trivia(state);
104 }
105
106 if state.at(MsilTokenType::IdentifierToken) {
107 let id_cp = state.checkpoint();
108 state.bump();
109 state.finish_at(id_cp, crate::parser::element_type::MsilElementType::Identifier);
110 self.skip_trivia(state);
111 }
112
113 if (state.at(MsilTokenType::IdentifierToken) || state.at(MsilTokenType::Keyword)) && state.peek_text().as_deref() == Some("extends") {
115 state.bump();
116 self.skip_trivia(state);
117 while state.not_at_end() && !state.at(MsilTokenType::LeftBrace) {
118 state.bump();
119 }
120 }
121
122 if state.at(MsilTokenType::LeftBrace) {
123 state.bump();
124 while state.not_at_end() && !state.at(MsilTokenType::RightBrace) {
125 self.skip_trivia(state);
126 if !state.not_at_end() || state.at(MsilTokenType::RightBrace) {
127 break;
128 }
129
130 if state.at(MsilTokenType::MethodKeyword) {
131 self.parse_method(state);
132 }
133 else {
134 state.bump();
135 }
136 }
137 if state.at(MsilTokenType::RightBrace) {
138 state.bump();
139 }
140 }
141
142 state.finish_at(cp, crate::parser::element_type::MsilElementType::Class);
143 }
144
145 fn parse_method<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) {
146 let cp = state.checkpoint();
147 state.bump(); self.skip_trivia(state);
149
150 while state.not_at_end() && !state.at(MsilTokenType::LeftBrace) {
152 if state.at(MsilTokenType::PublicKeyword) || state.at(MsilTokenType::PrivateKeyword) || state.at(MsilTokenType::StaticKeyword) || state.at(MsilTokenType::Keyword) {
153 state.bump();
154 self.skip_trivia(state);
155 }
156 else if state.at(MsilTokenType::IdentifierToken) {
157 let id_cp = state.checkpoint();
158 state.bump();
159 state.finish_at(id_cp, crate::parser::element_type::MsilElementType::Identifier);
160 self.skip_trivia(state);
161 }
162 else if state.at(MsilTokenType::LeftParen) {
163 state.bump();
165 self.skip_trivia(state);
166 while state.not_at_end() && !state.at(MsilTokenType::RightParen) {
167 if state.at(MsilTokenType::IdentifierToken) {
168 let id_cp = state.checkpoint();
169 state.bump();
170 state.finish_at(id_cp, crate::parser::element_type::MsilElementType::Identifier);
171 self.skip_trivia(state);
172 }
173 else if state.at(MsilTokenType::Comma) {
174 state.bump();
175 self.skip_trivia(state);
176 }
177 else {
178 state.bump();
179 }
180 }
181 if state.at(MsilTokenType::RightParen) {
182 state.bump();
183 self.skip_trivia(state);
184 }
185 }
186 else {
187 state.bump();
188 }
189 }
190
191 if state.at(MsilTokenType::LeftBrace) {
192 state.bump();
193 while state.not_at_end() && !state.at(MsilTokenType::RightBrace) {
194 self.skip_trivia(state);
195 if !state.not_at_end() || state.at(MsilTokenType::RightBrace) {
196 break;
197 }
198
199 if state.at(MsilTokenType::IdentifierToken) {
201 let peeked = state.peek_text();
202 let text = peeked.as_deref().unwrap_or("");
203 if text.starts_with(".") {
204 let dir_cp = state.checkpoint();
206 state.bump();
207 self.skip_trivia(state);
208 while state.not_at_end() && !state.at(MsilTokenType::Semicolon) && !state.at(MsilTokenType::LeftBrace) && !state.at(MsilTokenType::RightBrace) {
209 state.bump();
210 }
211 if state.at(MsilTokenType::Semicolon) {
212 state.bump();
213 }
214 state.finish_at(dir_cp, crate::parser::element_type::MsilElementType::Directive);
215 }
216 else if text.starts_with("IL_") {
217 let label_cp = state.checkpoint();
219 state.bump();
220 if state.at(MsilTokenType::Colon) {
221 state.bump();
222 }
223 state.finish_at(label_cp, crate::parser::element_type::MsilElementType::Label);
224 }
225 else {
226 let inst_cp = state.checkpoint();
228 state.bump();
229 self.skip_trivia(state);
230 while state.not_at_end() && !state.at(MsilTokenType::Semicolon) && !state.at(MsilTokenType::RightBrace) {
232 if state.at(MsilTokenType::IdentifierToken) || state.at(MsilTokenType::NumberToken) || state.at(MsilTokenType::StringToken) || state.at(MsilTokenType::LeftBracket) {
233 state.bump();
234 }
235 else {
236 break;
237 }
238 self.skip_trivia(state);
239 }
240 state.finish_at(inst_cp, crate::parser::element_type::MsilElementType::Instruction);
241 }
242 }
243 else {
244 state.bump();
245 }
246 }
247 if state.at(MsilTokenType::RightBrace) {
248 state.bump();
249 }
250 }
251
252 state.finish_at(cp, crate::parser::element_type::MsilElementType::Method);
253 }
254}
255
256impl<'config> Parser<MsilLanguage> for MsilParser<'config> {
257 fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<MsilLanguage>) -> oak_core::ParseOutput<'a, MsilLanguage> {
258 let lexer = MsilLexer::new(self.config);
259 parse_with_lexer(&lexer, text, edits, cache, |state| {
260 let cp = state.checkpoint();
261 while state.not_at_end() {
262 self.skip_trivia(state);
263 if !state.not_at_end() {
264 break;
265 }
266
267 if state.at(MsilTokenType::AssemblyKeyword) {
268 self.parse_assembly(state);
269 }
270 else if state.at(MsilTokenType::ModuleKeyword) {
271 self.parse_module(state);
272 }
273 else if state.at(MsilTokenType::ClassKeyword) {
274 self.parse_class(state);
275 }
276 else {
277 state.bump();
278 }
279 }
280 Ok(state.finish_at(cp, crate::parser::element_type::MsilElementType::Root))
281 })
282 }
283}