1pub mod element_type;
3
4use crate::{
5 language::WatLanguage,
6 lexer::{WatLexer, token_type::WatTokenType},
7 parser::element_type::WatElementType,
8};
9use oak_core::{
10 TextEdit,
11 parser::{ParseCache, ParseOutput, Parser, ParserState, parse_with_lexer},
12 source::Source,
13};
14
15pub(crate) type State<'a, S> = ParserState<'a, WatLanguage, S>;
16
17pub struct WatParser<'config> {
19 pub(crate) config: &'config WatLanguage,
20}
21
22impl<'config> WatParser<'config> {
23 pub fn new(config: &'config WatLanguage) -> Self {
25 Self { config }
26 }
27
28 fn parse_item<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) {
30 let cp = state.checkpoint();
31 state.expect(WatTokenType::LeftParen).ok();
32
33 if state.at(WatTokenType::ModuleKw) {
34 state.bump();
35 while state.not_at_end() && !state.at(WatTokenType::RightParen) {
36 if state.at(WatTokenType::LeftParen) {
37 self.parse_item(state);
38 }
39 else {
40 state.bump();
41 }
42 }
43 state.expect(WatTokenType::RightParen).ok();
44 state.finish_at(cp, WatElementType::Module);
45 }
46 else if state.at(WatTokenType::FuncKw) {
47 state.bump();
48 while state.not_at_end() && !state.at(WatTokenType::RightParen) {
49 if state.at(WatTokenType::LeftParen) {
50 self.parse_item(state);
51 }
52 else {
53 state.bump();
54 }
55 }
56 state.expect(WatTokenType::RightParen).ok();
57 state.finish_at(cp, WatElementType::Func);
58 }
59 else if state.at(WatTokenType::ParamKw) {
60 state.bump();
61 while state.not_at_end() && !state.at(WatTokenType::RightParen) {
62 state.bump();
63 }
64 state.expect(WatTokenType::RightParen).ok();
65 state.finish_at(cp, WatElementType::Param);
66 }
67 else if state.at(WatTokenType::ResultKw) {
68 state.bump();
69 while state.not_at_end() && !state.at(WatTokenType::RightParen) {
70 state.bump();
71 }
72 state.expect(WatTokenType::RightParen).ok();
73 state.finish_at(cp, WatElementType::Result);
74 }
75 else if state.at(WatTokenType::LocalKw) {
76 state.bump();
77 while state.not_at_end() && !state.at(WatTokenType::RightParen) {
78 state.bump();
79 }
80 state.expect(WatTokenType::RightParen).ok();
81 state.finish_at(cp, WatElementType::Local);
82 }
83 else if state.at(WatTokenType::ExportKw) {
84 state.bump();
85 while state.not_at_end() && !state.at(WatTokenType::RightParen) {
86 state.bump();
87 }
88 state.expect(WatTokenType::RightParen).ok();
89 state.finish_at(cp, WatElementType::Export);
90 }
91 else if state.at(WatTokenType::ImportKw) {
92 state.bump();
93 while state.not_at_end() && !state.at(WatTokenType::RightParen) {
94 state.bump();
95 }
96 state.expect(WatTokenType::RightParen).ok();
97 state.finish_at(cp, WatElementType::Import);
98 }
99 else if state.at(WatTokenType::TypeKw) {
100 state.bump();
101 while state.not_at_end() && !state.at(WatTokenType::RightParen) {
102 state.bump();
103 }
104 state.expect(WatTokenType::RightParen).ok();
105 state.finish_at(cp, WatElementType::Type);
106 }
107 else if state.at(WatTokenType::TableKw) {
108 state.bump();
109 while state.not_at_end() && !state.at(WatTokenType::RightParen) {
110 if state.at(WatTokenType::LeftParen) {
111 self.parse_item(state);
112 }
113 else {
114 state.bump();
115 }
116 }
117 state.expect(WatTokenType::RightParen).ok();
118 state.finish_at(cp, WatElementType::Table);
119 }
120 else if state.at(WatTokenType::MemoryKw) {
121 state.bump();
122 while state.not_at_end() && !state.at(WatTokenType::RightParen) {
123 if state.at(WatTokenType::LeftParen) {
124 self.parse_item(state);
125 }
126 else {
127 state.bump();
128 }
129 }
130 state.expect(WatTokenType::RightParen).ok();
131 state.finish_at(cp, WatElementType::Memory);
132 }
133 else if state.at(WatTokenType::GlobalKw) {
134 state.bump();
135 while state.not_at_end() && !state.at(WatTokenType::RightParen) {
136 state.bump();
137 }
138 state.expect(WatTokenType::RightParen).ok();
139 state.finish_at(cp, WatElementType::Global);
140 }
141 else {
142 let is_instr = state.peek_kind().map_or(false, |k| {
144 let kind_val = k as u8;
145 kind_val >= WatTokenType::LocalGetKw as u8 && kind_val <= WatTokenType::I64RemUKw as u8
146 });
147
148 state.bump();
149 while state.not_at_end() && !state.at(WatTokenType::RightParen) {
150 if state.at(WatTokenType::LeftParen) {
151 self.parse_item(state);
152 }
153 else {
154 state.bump();
155 }
156 }
157 state.expect(WatTokenType::RightParen).ok();
158
159 if is_instr {
160 state.finish_at(cp, WatElementType::Instruction);
161 }
162 else {
163 state.finish_at(cp, WatElementType::Item);
164 }
165 }
166 }
167}
168
169impl<'config> Parser<WatLanguage> for WatParser<'config> {
170 fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<WatLanguage>) -> ParseOutput<'a, WatLanguage> {
171 let lexer = WatLexer::new(&self.config);
172 parse_with_lexer(&lexer, text, edits, cache, |state| {
173 let cp = state.checkpoint();
174
175 while state.not_at_end() {
176 if state.at(WatTokenType::LeftParen) {
177 self.parse_item(state);
178 }
179 else {
180 state.bump();
181 }
182 }
183 Ok(state.finish_at(cp, WatElementType::Root))
184 })
185 }
186}