Skip to main content

oak_prolog/parser/
mod.rs

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