1pub mod element_type;
3
4use crate::{
5 language::MsilLanguage,
6 lexer::{MsilLexer, token_type::MsilTokenType},
7};
8use oak_core::{
9 GreenNode, OakError, 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) {
151 if state.at(MsilTokenType::IdentifierToken) {
152 let id_cp = state.checkpoint();
153 state.bump();
154 state.finish_at(id_cp, crate::parser::element_type::MsilElementType::Identifier);
155 self.skip_trivia(state);
156 }
157 else {
158 state.bump();
159 }
160 }
161
162 if state.at(MsilTokenType::LeftBrace) {
163 state.bump();
164 while state.not_at_end() && !state.at(MsilTokenType::RightBrace) {
165 state.bump();
166 }
167 if state.at(MsilTokenType::RightBrace) {
168 state.bump();
169 }
170 }
171
172 state.finish_at(cp, crate::parser::element_type::MsilElementType::Method);
173 }
174}
175
176impl<'config> Parser<MsilLanguage> for MsilParser<'config> {
177 fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<MsilLanguage>) -> oak_core::ParseOutput<'a, MsilLanguage> {
178 let lexer = MsilLexer::new(self.config);
179 parse_with_lexer(&lexer, text, edits, cache, |state| {
180 let cp = state.checkpoint();
181 while state.not_at_end() {
182 self.skip_trivia(state);
183 if !state.not_at_end() {
184 break;
185 }
186
187 if state.at(MsilTokenType::AssemblyKeyword) {
188 self.parse_assembly(state);
189 }
190 else if state.at(MsilTokenType::ModuleKeyword) {
191 self.parse_module(state);
192 }
193 else if state.at(MsilTokenType::ClassKeyword) {
194 self.parse_class(state);
195 }
196 else {
197 state.bump();
198 }
199 }
200 Ok(state.finish_at(cp, crate::parser::element_type::MsilElementType::Root))
201 })
202 }
203}