Skip to main content

oak_prolog/parser/
mod.rs

1pub mod element_type;
2
3use crate::{
4    language::PrologLanguage,
5    lexer::{PrologLexer, token_type::PrologTokenType},
6    parser::element_type::PrologElementType,
7};
8use oak_core::{
9    GreenNode, OakError,
10    parser::{ParseCache, ParseOutput, Parser, ParserState},
11    source::{Source, TextEdit},
12};
13
14pub struct PrologParser {
15    language: PrologLanguage,
16}
17
18impl PrologParser {
19    pub fn new(language: PrologLanguage) -> Self {
20        Self { language }
21    }
22
23    fn parse_directive<'s, S: Source + ?Sized>(&self, state: &mut ParserState<'s, PrologLanguage, S>) {
24        let checkpoint = state.checkpoint();
25        state.expect(PrologTokenType::ColonMinus).ok();
26        while !state.at(PrologTokenType::Dot) && state.not_at_end() {
27            state.bump()
28        }
29        state.expect(PrologTokenType::Dot).ok();
30        state.finish_at(checkpoint, crate::parser::element_type::PrologElementType::Directive);
31    }
32
33    fn parse_query<'s, S: Source + ?Sized>(&self, state: &mut ParserState<'s, PrologLanguage, S>) {
34        let checkpoint = state.checkpoint();
35        state.expect(PrologTokenType::QuestionMinus).ok();
36        while !state.at(PrologTokenType::Dot) && state.not_at_end() {
37            state.bump()
38        }
39        state.expect(PrologTokenType::Dot).ok();
40        state.finish_at(checkpoint, crate::parser::element_type::PrologElementType::Query);
41    }
42
43    fn parse_clause<'s, S: Source + ?Sized>(&self, state: &mut ParserState<'s, PrologLanguage, S>) {
44        let checkpoint = state.checkpoint();
45        while !state.at(PrologTokenType::Dot) && state.not_at_end() {
46            state.bump()
47        }
48        state.expect(PrologTokenType::Dot).ok();
49        state.finish_at(checkpoint, crate::parser::element_type::PrologElementType::Clause);
50    }
51
52    fn parse_root_internal<'s, S: Source + ?Sized>(&self, state: &mut ParserState<'s, PrologLanguage, S>) -> Result<&'s GreenNode<'s, PrologLanguage>, OakError> {
53        let checkpoint = state.checkpoint();
54        while state.not_at_end() {
55            if state.at(PrologTokenType::ColonMinus) {
56                self.parse_directive(state)
57            }
58            else if state.at(PrologTokenType::QuestionMinus) {
59                self.parse_query(state)
60            }
61            else {
62                self.parse_clause(state)
63            }
64        }
65        Ok(state.finish_at(checkpoint, crate::parser::element_type::PrologElementType::Root))
66    }
67}
68
69impl Parser<PrologLanguage> for PrologParser {
70    fn parse<'s, S: Source + ?Sized>(&self, text: &'s S, edits: &[TextEdit], cache: &'s mut impl ParseCache<PrologLanguage>) -> ParseOutput<'s, PrologLanguage> {
71        let lexer = PrologLexer::new(&self.language);
72        oak_core::parser::parse_with_lexer(&lexer, text, edits, cache, |state| self.parse_root_internal(state))
73    }
74}