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