1pub mod element_type;
2
3use crate::{
4 language::HaskellLanguage,
5 lexer::{HaskellLexer, token_type::HaskellTokenType},
6 parser::element_type::HaskellElementType,
7};
8use oak_core::{
9 GreenNode, OakError, TokenType,
10 parser::{Associativity, ParseCache, ParseOutput, Parser, ParserState, Pratt, PrattParser, binary, parse_with_lexer, unary},
11 source::{Source, TextEdit},
12};
13
14pub(crate) type State<'a, S> = ParserState<'a, HaskellLanguage, S>;
15
16pub struct HaskellParser<'config> {
18 pub(crate) config: &'config HaskellLanguage,
20}
21
22impl<'config> HaskellParser<'config> {
23 pub fn new(config: &'config HaskellLanguage) -> Self {
25 Self { config }
26 }
27
28 fn parse_item<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
30 match state.peek_kind() {
31 Some(HaskellTokenType::Module) => {
32 self.parse_module(state);
33 }
34 Some(HaskellTokenType::Import) => {
35 self.parse_import(state);
36 }
37 Some(HaskellTokenType::Data) => {
38 self.parse_data(state);
39 }
40 Some(HaskellTokenType::Type) => {
41 self.parse_type_alias(state);
42 }
43 Some(HaskellTokenType::Identifier) => {
44 self.parse_function(state);
45 }
46 _ => {
47 state.bump();
48 }
49 }
50 Ok(())
51 }
52
53 fn parse_module<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, HaskellLanguage> {
54 let cp = state.checkpoint();
55 state.expect(HaskellTokenType::Module).ok();
56 state.expect(HaskellTokenType::Constructor).ok(); if state.eat(HaskellTokenType::Where) {
58 }
60 state.finish_at(cp, HaskellElementType::ModuleDeclaration)
61 }
62
63 fn parse_import<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, HaskellLanguage> {
64 let cp = state.checkpoint();
65 state.expect(HaskellTokenType::Import).ok();
66 state.eat(HaskellTokenType::Qualified);
67 state.expect(HaskellTokenType::Constructor).ok(); if state.eat(HaskellTokenType::As) {
69 state.expect(HaskellTokenType::Constructor).ok();
70 }
71 state.finish_at(cp, HaskellElementType::ImportDeclaration)
72 }
73
74 fn parse_data<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, HaskellLanguage> {
75 let cp = state.checkpoint();
76 state.expect(HaskellTokenType::Data).ok();
77 state.expect(HaskellTokenType::Constructor).ok(); while state.at(HaskellTokenType::Identifier) {
79 state.bump(); }
81 if state.eat(HaskellTokenType::Assign) {
82 loop {
83 state.expect(HaskellTokenType::Constructor).ok();
84 while state.at(HaskellTokenType::Constructor) || state.at(HaskellTokenType::Identifier) || state.at(HaskellTokenType::LeftParen) {
85 if state.at(HaskellTokenType::LeftParen) {
86 state.bump();
87 while !state.at(HaskellTokenType::RightParen) && state.not_at_end() {
88 state.bump();
89 }
90 state.eat(HaskellTokenType::RightParen);
91 }
92 else {
93 state.bump();
94 }
95 }
96 if !state.eat(HaskellTokenType::Pipe) {
97 break;
98 }
99 }
100 }
101 state.finish_at(cp, HaskellElementType::DataDeclaration)
102 }
103
104 fn parse_type_alias<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, HaskellLanguage> {
105 let cp = state.checkpoint();
106 state.expect(HaskellTokenType::Type).ok();
107 state.expect(HaskellTokenType::Constructor).ok();
108 while state.at(HaskellTokenType::Identifier) {
109 state.bump();
110 }
111 state.expect(HaskellTokenType::Assign).ok();
112 while !state.at(HaskellTokenType::Newline) && state.not_at_end() {
114 state.bump();
115 }
116 state.finish_at(cp, HaskellElementType::TypeAliasDeclaration)
117 }
118
119 fn parse_function<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, HaskellLanguage> {
120 let cp = state.checkpoint();
121 state.expect(HaskellTokenType::Identifier).ok();
122 if state.eat(HaskellTokenType::DoubleColon) {
123 while !state.at(HaskellTokenType::Newline) && state.not_at_end() {
125 state.bump();
126 }
127 state.finish_at(cp, HaskellElementType::TypeSignature)
128 }
129 else {
130 while !state.at(HaskellTokenType::Assign) && state.not_at_end() {
132 state.bump(); }
134 state.expect(HaskellTokenType::Assign).ok();
135 PrattParser::parse(state, 0, self); state.finish_at(cp, HaskellElementType::Function)
137 }
138 }
139}
140
141impl<'config> Parser<HaskellLanguage> for HaskellParser<'config> {
142 fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<HaskellLanguage>) -> ParseOutput<'a, HaskellLanguage> {
143 let lexer = HaskellLexer::new(&self.config);
144 parse_with_lexer(&lexer, text, edits, cache, |state| {
145 let checkpoint = state.checkpoint();
146
147 while state.not_at_end() {
148 self.parse_item(state)?
149 }
150
151 Ok(state.finish_at(checkpoint, HaskellElementType::Root))
152 })
153 }
154}
155
156impl<'config> Pratt<HaskellLanguage> for HaskellParser<'config> {
157 fn primary<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, HaskellLanguage> {
158 let cp = state.checkpoint();
159 match state.peek_kind() {
160 Some(HaskellTokenType::Identifier) => {
161 state.bump();
162 state.finish_at(cp, HaskellElementType::IdentifierExpression)
163 }
164 Some(HaskellTokenType::Constructor) => {
165 state.bump();
166 state.finish_at(cp, HaskellElementType::IdentifierExpression)
167 }
168 Some(HaskellTokenType::Integer) | Some(HaskellTokenType::Float) => {
169 state.bump();
170 state.finish_at(cp, HaskellElementType::LiteralExpression)
171 }
172 Some(HaskellTokenType::StringLiteral) | Some(HaskellTokenType::CharLiteral) => {
173 state.bump();
174 state.finish_at(cp, HaskellElementType::LiteralExpression)
175 }
176 Some(HaskellTokenType::LeftParen) => {
177 state.bump();
178 PrattParser::parse(state, 0, self);
179 state.expect(HaskellTokenType::RightParen).ok();
180 state.finish_at(cp, HaskellElementType::InfixExpression) }
182 _ => {
183 state.bump();
184 state.finish_at(cp, HaskellElementType::Error)
185 }
186 }
187 }
188
189 fn prefix<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, HaskellLanguage> {
190 let kind = match state.peek_kind() {
191 Some(k) => k,
192 None => return self.primary(state),
193 };
194
195 match kind {
196 HaskellTokenType::Minus => unary(state, kind, 9, HaskellElementType::PrefixExpression.into(), |s, p| PrattParser::parse(s, p, self)),
197 _ => self.primary(state),
198 }
199 }
200
201 fn infix<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>, left: &'a GreenNode<'a, HaskellLanguage>, min_precedence: u8) -> Option<&'a GreenNode<'a, HaskellLanguage>> {
202 let kind = state.peek_kind()?;
203
204 let (prec, assoc) = match kind {
205 HaskellTokenType::Dot => (9, Associativity::Right),
206 HaskellTokenType::Star | HaskellTokenType::Slash | HaskellTokenType::Percent => (7, Associativity::Left),
207 HaskellTokenType::Plus | HaskellTokenType::Minus => (6, Associativity::Left),
208 HaskellTokenType::Append => (5, Associativity::Right),
209 HaskellTokenType::Equal | HaskellTokenType::NotEqual | HaskellTokenType::Less | HaskellTokenType::LessEqual | HaskellTokenType::Greater | HaskellTokenType::GreaterEqual => (4, Associativity::None),
210 HaskellTokenType::And => (3, Associativity::Right),
211 HaskellTokenType::Or => (2, Associativity::Right),
212 HaskellTokenType::Dollar => (0, Associativity::Right),
213 _ => return None,
214 };
215
216 if prec < min_precedence {
217 return None;
218 }
219
220 Some(binary(state, left, kind, prec, assoc, HaskellElementType::InfixExpression.into(), |s, p| PrattParser::parse(s, p, self)))
221 }
222}