patch_prolog_frontend/parser/
query.rs1use super::{Parser, ProgramDirectives};
5use crate::parse_error::ParseError;
6use crate::tokenizer::{TokenKind, Tokenizer};
7use plg_shared::{Clause, StringInterner, Term, VarId};
8use std::collections::HashMap;
9
10impl<'a> Parser<'a> {
11 pub fn parse_program(
15 input: &str,
16 interner: &mut StringInterner,
17 ) -> Result<Vec<Clause>, ParseError> {
18 let (clauses, _) = Self::parse_program_with_directives(input, interner)?;
19 Ok(clauses)
20 }
21
22 pub fn parse_program_with_directives(
26 input: &str,
27 interner: &mut StringInterner,
28 ) -> Result<(Vec<Clause>, ProgramDirectives), ParseError> {
29 let tokens = Tokenizer::tokenize(input)?;
30 let mut parser = Parser::from_tokens(tokens, interner);
31 parser.parse_program_body()
32 }
33
34 pub fn parse_program_with_spans(
38 input: &str,
39 interner: &mut StringInterner,
40 ) -> Result<(Vec<Clause>, ProgramDirectives, Vec<super::CallSite>), ParseError> {
41 let tokens = Tokenizer::tokenize(input)?;
42 let mut parser = Parser::from_tokens(tokens, interner);
43 let (clauses, directives) = parser.parse_program_body()?;
44 Ok((clauses, directives, parser.call_sites))
45 }
46
47 fn parse_program_body(&mut self) -> Result<(Vec<Clause>, ProgramDirectives), ParseError> {
50 let mut clauses = Vec::new();
51 let mut directives = ProgramDirectives::default();
52 while !self.at_eof() {
53 self.reset_vars();
54 if self.current_kind() == Some(&TokenKind::Neck) {
55 self.advance();
56 let body = self.parse_term()?;
57 self.expect(&TokenKind::Dot)?;
58 self.process_directive(body, &mut directives)?;
59 } else {
60 clauses.push(self.parse_clause()?);
61 }
62 }
63 Ok((clauses, directives))
64 }
65
66 pub fn parse_query(
69 input: &str,
70 interner: &mut StringInterner,
71 ) -> Result<Vec<Term>, ParseError> {
72 let tokens = Tokenizer::tokenize(input)?;
73 let mut parser = Parser::from_tokens(tokens, interner);
74 if parser.current_kind() == Some(&TokenKind::QueryOp) {
76 parser.advance();
77 }
78 let goals = parser.parse_goal_list()?;
79 if parser.current_kind() == Some(&TokenKind::Dot) {
81 parser.advance();
82 }
83 if !parser.at_eof() {
88 let pos = parser.current().unwrap();
89 let msg = format!("unexpected {} after query", pos.kind);
90 return Err(parser.error_here(msg));
91 }
92 Ok(goals)
93 }
94
95 pub fn parse_query_with_vars(
97 input: &str,
98 interner: &mut StringInterner,
99 ) -> Result<(Vec<Term>, HashMap<String, VarId>), ParseError> {
100 let tokens = Tokenizer::tokenize(input)?;
101 let mut parser = Parser::from_tokens(tokens, interner);
102 if parser.current_kind() == Some(&TokenKind::QueryOp) {
103 parser.advance();
104 }
105 let goals = parser.parse_goal_list()?;
106 if parser.current_kind() == Some(&TokenKind::Dot) {
107 parser.advance();
108 }
109 if !parser.at_eof() {
111 let pos = parser.current().unwrap();
112 let msg = format!("unexpected {} after query", pos.kind);
113 return Err(parser.error_here(msg));
114 }
115 let vars = parser.var_map;
116 Ok((goals, vars))
117 }
118
119 pub(super) fn parse_goal_list(&mut self) -> Result<Vec<Term>, ParseError> {
120 let body = self.parse_goal_disjunction()?;
123 Ok(vec![body])
124 }
125
126 pub(super) fn parse_goal_disjunction(&mut self) -> Result<Term, ParseError> {
128 let left = self.parse_goal_conjunction()?;
129 if self.current_kind() == Some(&TokenKind::Semicolon) {
130 self.advance();
131 let right = self.parse_goal_disjunction()?;
132 let functor = self.interner.intern(";");
133 Ok(Term::Compound {
134 functor,
135 args: vec![left, right],
136 })
137 } else {
138 Ok(left)
139 }
140 }
141
142 fn parse_goal_conjunction(&mut self) -> Result<Term, ParseError> {
144 let first = self.parse_term()?;
145 if self.current_kind() == Some(&TokenKind::Comma) {
146 let mut goals = vec![first];
147 while self.current_kind() == Some(&TokenKind::Comma) {
148 self.advance();
149 goals.push(self.parse_term()?);
150 }
151 let comma = self.interner.intern(",");
153 let mut result = goals.pop().unwrap();
154 while let Some(g) = goals.pop() {
155 result = Term::Compound {
156 functor: comma,
157 args: vec![g, result],
158 };
159 }
160 Ok(result)
161 } else {
162 Ok(first)
163 }
164 }
165}
166
167#[cfg(test)]
168mod tests;