Skip to main content

oak_prolog/parser/
mod.rs

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