1pub mod element_type;
2
3use crate::{
4 language::OCamlLanguage,
5 lexer::{OCamlLexer, token_type::OCamlTokenType},
6 parser::element_type::OCamlElementType,
7};
8use oak_core::{
9 GreenNode, OakError,
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, OCamlLanguage, S>;
16
17pub struct OCamlParser<'config> {
19 pub language: &'config OCamlLanguage,
21}
22
23impl<'config> OCamlParser<'config> {
24 pub fn new(language: &'config OCamlLanguage) -> Self {
26 Self { language }
27 }
28
29 fn parse_item<'s, S: Source + ?Sized>(&self, state: &mut State<'s, S>) -> Result<(), OakError> {
31 let kind = state.peek_kind();
32 match kind {
33 Some(OCamlTokenType::Let) => self.parse_let_binding(state),
34 Some(OCamlTokenType::Module) => self.parse_module_def(state),
35 Some(OCamlTokenType::Type) => self.parse_type_definition(state),
36 Some(OCamlTokenType::Open) => {
37 let cp = state.checkpoint();
38 state.bump();
39 while state.not_at_end() && !state.at(OCamlTokenType::Semicolon) {
40 state.bump();
41 }
42 state.finish_at(cp, OCamlElementType::Expression);
43 Ok(())
44 }
45 _ => self.parse_expression_item(state),
46 }
47 }
48
49 fn parse_expression_item<'s, S: Source + ?Sized>(&self, state: &mut State<'s, S>) -> Result<(), OakError> {
50 let cp = state.checkpoint();
51 PrattParser::parse(state, 0, self);
52 if state.at(OCamlTokenType::Semicolon) {
53 state.bump();
54 if state.at(OCamlTokenType::Semicolon) {
55 state.bump();
56 }
57 }
58 state.finish_at(cp, OCamlElementType::Expression);
59 Ok(())
60 }
61
62 fn parse_let_binding<'s, S: Source + ?Sized>(&self, state: &mut State<'s, S>) -> Result<(), OakError> {
64 let checkpoint = state.checkpoint();
65 state.bump(); if state.at(OCamlTokenType::Rec) {
67 state.bump(); }
69 while state.not_at_end() && !state.at(OCamlTokenType::Equal) && !state.at(OCamlTokenType::Semicolon) {
71 state.bump();
72 }
73 if state.at(OCamlTokenType::Equal) {
74 state.bump(); PrattParser::parse(state, 0, self);
76 }
77 state.finish_at(checkpoint, OCamlElementType::LetBinding);
78 Ok(())
79 }
80
81 fn parse_module_def<'s, S: Source + ?Sized>(&self, state: &mut State<'s, S>) -> Result<(), OakError> {
83 let checkpoint = state.checkpoint();
84 state.bump(); while state.not_at_end() && !state.at(OCamlTokenType::Equal) && !state.at(OCamlTokenType::Semicolon) {
86 state.bump();
87 }
88 if state.at(OCamlTokenType::Equal) {
89 state.bump(); while state.not_at_end() && !state.at(OCamlTokenType::Semicolon) {
91 state.bump();
92 }
93 }
94 state.finish_at(checkpoint, OCamlElementType::ModuleDef);
95 Ok(())
96 }
97
98 fn parse_type_definition<'s, S: Source + ?Sized>(&self, state: &mut State<'s, S>) -> Result<(), OakError> {
100 let checkpoint = state.checkpoint();
101 state.bump(); while state.not_at_end() && !state.at(OCamlTokenType::Semicolon) {
103 state.bump();
104 }
105 state.finish_at(checkpoint, OCamlElementType::TypeDefinition);
106 Ok(())
107 }
108}
109
110impl<'config> Parser<OCamlLanguage> for OCamlParser<'config> {
111 fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<OCamlLanguage>) -> ParseOutput<'a, OCamlLanguage> {
112 let lexer = OCamlLexer::new(self.language);
113 parse_with_lexer(&lexer, text, edits, cache, |state| {
114 let checkpoint = state.checkpoint();
115
116 while state.not_at_end() {
117 self.parse_item(state)?;
118 }
119
120 Ok(state.finish_at(checkpoint, OCamlElementType::Root))
121 })
122 }
123}
124
125impl<'config> Pratt<OCamlLanguage> for OCamlParser<'config> {
126 fn primary<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, OCamlLanguage> {
127 let cp = state.checkpoint();
128 match state.peek_kind() {
129 Some(OCamlTokenType::Identifier) => {
130 state.bump();
131 state.finish_at(cp, OCamlElementType::IdentifierExpr)
132 }
133 Some(OCamlTokenType::IntegerLiteral) | Some(OCamlTokenType::FloatLiteral) | Some(OCamlTokenType::StringLiteral) | Some(OCamlTokenType::CharLiteral) | Some(OCamlTokenType::True) | Some(OCamlTokenType::False) => {
134 state.bump();
135 state.finish_at(cp, OCamlElementType::LiteralExpr)
136 }
137 Some(OCamlTokenType::LeftParen) => {
138 state.bump();
139 PrattParser::parse(state, 0, self);
140 state.expect(OCamlTokenType::RightParen).ok();
141 state.finish_at(cp, OCamlElementType::Expression)
142 }
143 _ => {
144 state.bump();
145 state.finish_at(cp, OCamlElementType::Error)
146 }
147 }
148 }
149
150 fn prefix<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, OCamlLanguage> {
151 let kind = match state.peek_kind() {
152 Some(k) => k,
153 None => return self.primary(state),
154 };
155
156 match kind {
157 OCamlTokenType::Minus | OCamlTokenType::MinusDot | OCamlTokenType::Tilde => unary(state, kind, 12, OCamlElementType::UnaryExpr.into(), |s, p| PrattParser::parse(s, p, self)),
158 _ => self.primary(state),
159 }
160 }
161
162 fn infix<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>, left: &'a GreenNode<'a, OCamlLanguage>, min_precedence: u8) -> Option<&'a GreenNode<'a, OCamlLanguage>> {
163 let kind = state.peek_kind()?;
164
165 let (prec, assoc) = match kind {
166 OCamlTokenType::Dot => (13, Associativity::Left),
167 OCamlTokenType::Star | OCamlTokenType::Slash | OCamlTokenType::Percent => (11, Associativity::Left),
168 OCamlTokenType::Plus | OCamlTokenType::Minus => (10, Associativity::Left),
169 OCamlTokenType::At => (9, Associativity::Right),
170 OCamlTokenType::Equal | OCamlTokenType::NotEqual | OCamlTokenType::Less | OCamlTokenType::Greater | OCamlTokenType::LessEqual | OCamlTokenType::GreaterEqual => (8, Associativity::Left),
171 OCamlTokenType::And => (7, Associativity::Right),
172 OCamlTokenType::Or => (6, Associativity::Right),
173 OCamlTokenType::Semicolon => (5, Associativity::Right),
174 _ => return None,
175 };
176
177 if prec < min_precedence {
178 return None;
179 }
180
181 Some(binary(state, left, kind, prec, assoc, OCamlElementType::BinaryExpr.into(), |s, p| PrattParser::parse(s, p, self)))
182 }
183}