1pub mod element_type;
3
4use crate::{
5 language::FSharpLanguage,
6 lexer::{FSharpLexer, token_type::FSharpTokenType},
7 parser::element_type::FSharpElementType,
8};
9use oak_core::{
10 GreenNode, OakError,
11 parser::{ParseCache, ParseOutput, Parser, ParserState, parse_with_lexer},
12 source::{Source, TextEdit},
13};
14
15pub(crate) type State<'a, S> = ParserState<'a, FSharpLanguage, S>;
16
17pub struct FSharpParser<'config> {
19 pub(crate) config: &'config FSharpLanguage,
20}
21
22impl<'config> FSharpParser<'config> {
23 pub fn new(config: &'config FSharpLanguage) -> Self {
25 Self { config }
26 }
27
28 fn parse_namespace<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
29 let checkpoint = state.checkpoint();
30 state.expect(FSharpTokenType::Namespace)?;
31
32 while state.not_at_end() && state.at(FSharpTokenType::Identifier) {
34 state.bump();
35 if state.at(FSharpTokenType::Dot) { state.bump() } else { break }
36 }
37
38 state.finish_at(checkpoint, FSharpElementType::Namespace);
39 Ok(())
40 }
41
42 fn parse_module<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
43 let checkpoint = state.checkpoint();
44 state.expect(FSharpTokenType::Module)?;
45
46 if state.at(FSharpTokenType::Identifier) {
47 state.bump()
48 }
49
50 state.finish_at(checkpoint, FSharpElementType::Module);
51 Ok(())
52 }
53
54 fn parse_open<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
55 let checkpoint = state.checkpoint();
56 state.expect(FSharpTokenType::Open)?;
57
58 while state.not_at_end() && state.at(FSharpTokenType::Identifier) {
60 state.bump();
61 if state.at(FSharpTokenType::Dot) { state.bump() } else { break }
62 }
63
64 state.finish_at(checkpoint, FSharpElementType::Open);
65 Ok(())
66 }
67
68 fn parse_binding<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
69 let checkpoint = state.checkpoint();
70 state.expect(FSharpTokenType::Let)?;
71
72 if state.eat(FSharpTokenType::Rec) {
73 }
75
76 state.expect(FSharpTokenType::Identifier)?;
78
79 while state.not_at_end() && state.at(FSharpTokenType::Identifier) {
81 state.bump()
82 }
83
84 state.expect(FSharpTokenType::Equal)?;
86
87 self.parse_expression(state)?;
89
90 state.finish_at(checkpoint, FSharpElementType::Let);
91 Ok(())
92 }
93
94 fn parse_expression<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
95 let checkpoint = state.checkpoint();
96 let kind = state.peek_kind();
97 match kind {
98 Some(FSharpTokenType::If) => {
99 state.expect(FSharpTokenType::If)?;
100 self.parse_expression(state)?;
101 state.expect(FSharpTokenType::Then)?;
102 self.parse_expression(state)?;
103 if state.eat(FSharpTokenType::Else) {
104 self.parse_expression(state)?
105 }
106 state.finish_at(checkpoint, FSharpElementType::If);
107 }
108 _ => {
109 while state.not_at_end() {
111 let kind = state.peek_kind();
112 if matches!(kind, Some(FSharpTokenType::Newline | FSharpTokenType::Then | FSharpTokenType::Else)) {
113 break;
114 }
115 state.bump()
116 }
117 if state.checkpoint().0 == checkpoint.0 {
119 state.bump()
120 }
121 state.finish_at(checkpoint, FSharpElementType::Expression);
122 }
123 }
124 Ok(())
125 }
126}
127
128impl<'config> Parser<FSharpLanguage> for FSharpParser<'config> {
129 fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<FSharpLanguage>) -> ParseOutput<'a, FSharpLanguage> {
130 let lexer = FSharpLexer::new(self.config);
131 parse_with_lexer(&lexer, text, edits, cache, |state| {
132 let cp = (0, 0); while state.not_at_end() {
134 let kind = state.peek_kind();
135 match kind {
136 Some(FSharpTokenType::Namespace) => self.parse_namespace(state)?,
137 Some(FSharpTokenType::Module) => self.parse_module(state)?,
138 Some(FSharpTokenType::Open) => self.parse_open(state)?,
139 Some(FSharpTokenType::Let) => self.parse_binding(state)?,
140 _ => state.bump(),
141 }
142 }
143
144 Ok(state.finish_at(cp, FSharpElementType::Root))
145 })
146 }
147}