1#![doc = include_str!("readme.md")]
2pub mod element_type;
4
5pub use element_type::AplElementType;
6
7use crate::{language::AplLanguage, lexer::token_type::AplTokenType};
8use oak_core::{
9 OakError, TextEdit,
10 parser::{Parser, ParserState},
11 source::Source,
12};
13
14pub(crate) type State<'a, S> = ParserState<'a, AplLanguage, S>;
15
16pub struct AplParser<'config> {
18 pub(crate) config: &'config AplLanguage,
20}
21
22impl<'config> AplParser<'config> {
23 pub fn new(config: &'config AplLanguage) -> Self {
25 Self { config }
26 }
27
28 pub(crate) fn parse_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
30 let cp = state.checkpoint();
31
32 if state.at(AplTokenType::Identifier) && state.peek_kind_at(1) == Some(AplTokenType::LeftArrow) {
34 state.advance(); state.advance(); self.parse_expression(state)?;
37 state.finish_at(cp, AplElementType::Assignment);
38 }
39 else {
40 self.parse_expression(state)?;
41 state.finish_at(cp, AplElementType::Statement);
42 }
43
44 Ok(())
45 }
46
47 pub(crate) fn parse_expression<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
49 let cp = state.checkpoint();
50
51 while state.not_at_end() && !state.at(AplTokenType::Newline) && !state.at(AplTokenType::Diamond) {
52 if state.at(AplTokenType::Identifier) {
53 state.advance();
54 }
55 else if state.at(AplTokenType::NumberLiteral) {
56 state.advance();
57 }
58 else if state.at(AplTokenType::StringLiteral) {
59 state.advance();
60 }
61 else if state.at(AplTokenType::LeftParen) {
62 state.advance();
63 self.parse_expression(state)?;
64 state.expect(AplTokenType::RightParen).ok();
65 }
66 else if state.at(AplTokenType::LeftBrace) {
67 state.advance();
69 while state.not_at_end() && !state.at(AplTokenType::RightBrace) {
70 state.advance();
71 }
72 state.expect(AplTokenType::RightBrace).ok();
73 }
74 else {
75 state.advance();
77 }
78 }
79
80 state.finish_at(cp, AplElementType::Expression);
81 Ok(())
82 }
83}
84
85impl<'config> Parser<AplLanguage> for AplParser<'config> {
86 fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl oak_core::ParseCache<AplLanguage>) -> oak_core::ParseOutput<'a, AplLanguage> {
87 let lexer = crate::lexer::AplLexer::new(self.config);
88 oak_core::parser::parse_with_lexer(&lexer, text, edits, cache, |state| {
89 let checkpoint = state.checkpoint();
90
91 while state.not_at_end() && !state.at(AplTokenType::Eof) {
92 if state.at(AplTokenType::Newline) || state.at(AplTokenType::Whitespace) {
93 state.advance();
94 continue;
95 }
96
97 if state.at(AplTokenType::Comment) {
98 state.advance();
99 continue;
100 }
101
102 self.parse_statement(state)?;
103
104 if state.at(AplTokenType::Diamond) {
105 state.advance();
106 }
107 }
108
109 Ok(state.finish_at(checkpoint, AplElementType::Root))
110 })
111 }
112}