1use super::{
2 repr::{Clause, ClauseDataset, Expr, Term},
3 CloseParenToken, CommaToken, DotToken, HornToken, Ident, NegationToken, OpenParenToken, Parse,
4 ParseBuffer,
5};
6use crate::{ClauseDatasetIn, ClauseIn, Error, ExprIn, Intern, NameIn, Result, TermIn};
7use std::{
8 borrow::Borrow,
9 fmt::{self, Debug, Display},
10 hash::Hash,
11 ops,
12};
13
14impl<'int, Int: Intern> Parse<'int, Int> for ClauseDatasetIn<'int, Int> {
15 fn parse(buf: &mut ParseBuffer<'_>, interner: &'int Int) -> Result<Self> {
16 let mut v = Vec::new();
17 while let Some(moved_buf) = {
18 let mut peek = *buf;
19 ClauseIn::<'int, Int>::parse(&mut peek, interner)
20 .ok()
21 .map(|c| (c, peek))
22 } {
23 let (clause, moved) = moved_buf;
24 v.push(clause);
25 *buf = moved;
26 }
27 Ok(ClauseDataset(v))
28 }
29}
30
31impl<'int, Int: Intern> Parse<'int, Int> for ClauseIn<'int, Int> {
32 fn parse(buf: &mut ParseBuffer<'_>, interner: &'int Int) -> Result<Self> {
33 let head = TermIn::<'int, Int>::parse(buf, interner)?;
34
35 let body = if let Some((_, mut body_buf)) = buf.peek_parse::<Int, HornToken>(interner) {
36 let dot = body_buf
37 .cur_text()
38 .find('.')
39 .ok_or(Error::from("clause must end with `.`"))?;
40 body_buf.end = body_buf.start + dot;
41 let body = ExprIn::<'int, Int>::parse(&mut body_buf, interner)?;
42
43 buf.start = body_buf.end + 1; Some(body)
45 } else {
46 let _ = buf.parse::<Int, DotToken>(interner)?;
47 None
48 };
49
50 Ok(Clause { head, body })
51 }
52}
53
54impl<'int, Int: Intern> Parse<'int, Int> for ExprIn<'int, Int> {
55 fn parse(buf: &mut ParseBuffer<'_>, interner: &'int Int) -> Result<Self> {
57 Expr::<Name<()>>::parse_or(*buf, interner)
58 }
59}
60
61impl<'int, Int: Intern> Parse<'int, Int> for TermIn<'int, Int> {
62 fn parse(buf: &mut ParseBuffer<'_>, interner: &'int Int) -> Result<Self> {
63 let functor = Name::parse(buf, interner)?;
64 let args = Term::parse_args(buf, interner)?;
65 Ok(Term { functor, args })
66 }
67}
68
69impl Expr<Name<()>> {
74 fn parse_or<'int, Int: Intern>(
75 buf: ParseBuffer<'_>,
76 interner: &'int Int,
77 ) -> Result<ExprIn<'int, Int>> {
78 Self::parse_by_delimiter(buf, interner, ';', Self::parse_and, Expr::Or)
79 }
80
81 fn parse_and<'int, Int: Intern>(
82 buf: ParseBuffer<'_>,
83 interner: &'int Int,
84 ) -> Result<ExprIn<'int, Int>> {
85 Self::parse_by_delimiter(buf, interner, ',', Self::parse_not, Expr::And)
86 }
87
88 fn parse_not<'int, Int: Intern>(
89 buf: ParseBuffer<'_>,
90 interner: &'int Int,
91 ) -> Result<ExprIn<'int, Int>> {
92 if let Some((_, moved_buf)) = buf.peek_parse::<Int, NegationToken>(interner) {
93 let inner = Self::parse_not(moved_buf, interner)?;
94 Ok(Expr::Not(Box::new(inner)))
95 } else {
96 Self::parse_paren(buf, interner)
97 }
98 }
99
100 fn parse_paren<'int, Int: Intern>(
101 buf: ParseBuffer<'_>,
102 interner: &'int Int,
103 ) -> Result<ExprIn<'int, Int>> {
104 if let Some((_, mut moved_buf)) = buf.peek_parse::<Int, OpenParenToken>(interner) {
105 let r = moved_buf.cur_text().rfind(')').unwrap();
106 moved_buf.end = moved_buf.start + r;
107 ExprIn::<'int, Int>::parse(&mut moved_buf, interner)
108 } else {
109 Self::parse_term(buf, interner)
110 }
111 }
112
113 fn parse_term<'int, Int: Intern>(
114 mut buf: ParseBuffer<'_>,
115 interner: &'int Int,
116 ) -> Result<ExprIn<'int, Int>> {
117 if buf.cur_text().chars().all(|c: char| c.is_whitespace()) {
118 Err("expected a non-empty term expression".into())
119 } else {
120 TermIn::<'int, Int>::parse(&mut buf, interner).map(Expr::Term)
121 }
122 }
123
124 fn parse_by_delimiter<'int, Int: Intern>(
125 buf: ParseBuffer<'_>,
126 interner: &'int Int,
127 del: char,
128 parse_partial: fn(ParseBuffer<'_>, &'int Int) -> Result<ExprIn<'int, Int>>,
129 wrap_vec: fn(Vec<ExprIn<'int, Int>>) -> ExprIn<'int, Int>,
130 ) -> Result<ExprIn<'int, Int>> {
131 let mut v = Vec::new();
132 let (mut l, mut r) = (buf.start, buf.start);
133 let mut open = 0;
134
135 for c in buf.cur_text().chars() {
136 if c == del && open == 0 {
137 let buf = ParseBuffer {
138 text: buf.text,
139 start: l,
140 end: r,
141 };
142 let partial = parse_partial(buf, interner)?;
143 v.push(partial);
144 l = r + c.len_utf8();
145 } else if c == '(' {
146 open += 1;
147 } else if c == ')' {
148 open -= 1;
149 }
150 r += c.len_utf8();
151 }
152
153 let buf = ParseBuffer {
154 text: buf.text,
155 start: l,
156 end: r,
157 };
158 let last = parse_partial(buf, interner)?;
159
160 if !v.is_empty() {
161 v.push(last);
162 Ok(wrap_vec(v))
163 } else {
164 Ok(last)
165 }
166 }
167}
168
169impl Term<Name<()>> {
170 fn parse_args<'int, Int: Intern>(
171 buf: &mut ParseBuffer<'_>,
172 interner: &'int Int,
173 ) -> Result<Vec<TermIn<'int, Int>>> {
174 let mut open = 0;
175 while let Some((_, moved_buf)) = buf.peek_parse::<Int, OpenParenToken>(interner) {
176 *buf = moved_buf;
177 open += 1;
178 }
179
180 if open == 0 {
181 return Ok([].into());
182 }
183
184 let mut args = Vec::new();
185 let mut well_seperated = true;
186 loop {
187 if let Some((_, moved_buf)) = buf.peek_parse::<Int, CloseParenToken>(interner) {
188 *buf = moved_buf;
189 open -= 1;
190 break;
191 }
192
193 if !well_seperated {
194 return Err(format!("expected `,` from {}", buf.cur_text()).into());
195 }
196
197 let arg = TermIn::<'int, Int>::parse(buf, interner)?;
198 args.push(arg);
199
200 let comma = buf.parse::<Int, CommaToken>(interner);
201 well_seperated = comma.is_ok();
202 }
203
204 for _ in 0..open {
205 buf.parse::<Int, CloseParenToken>(interner)?;
206 }
207
208 Ok(args)
209 }
210}
211
212#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
214pub struct Name<T>(T);
215
216impl<T: AsRef<str>> Name<T> {
217 pub fn new(s: T) -> Self {
218 assert!(!s.as_ref().is_empty());
219 Self(s)
220 }
221}
222
223impl Name<()> {
224 pub fn with_intern<'int, Int: Intern>(s: &str, interner: &'int Int) -> NameIn<'int, Int> {
225 assert!(!s.is_empty());
226 let interned = interner.intern_str(s);
227 Name(interned)
228 }
229}
230
231impl<'int, Int: Intern> Parse<'int, Int> for NameIn<'int, Int> {
232 fn parse(buf: &mut ParseBuffer<'_>, interner: &'int Int) -> Result<Self> {
233 let ident = buf.parse::<Int, Ident>(interner)?;
234 let interned = interner.intern_str(ident.to_text(buf.text));
235 Ok(Self(interned))
236 }
237}
238
239impl<T> Borrow<T> for Name<T> {
240 fn borrow(&self) -> &T {
241 &self.0
242 }
243}
244
245impl<T: Borrow<str>> Borrow<str> for Name<T> {
246 fn borrow(&self) -> &str {
247 self.0.borrow()
248 }
249}
250
251impl<T: AsRef<str>> AsRef<str> for Name<T> {
252 fn as_ref(&self) -> &str {
253 self.0.as_ref()
254 }
255}
256
257impl<T: PartialEq<str>> PartialEq<str> for Name<T> {
258 fn eq(&self, other: &str) -> bool {
259 self.0.eq(other)
260 }
261}
262
263impl<T: PartialOrd<str>> PartialOrd<str> for Name<T> {
264 fn partial_cmp(&self, other: &str) -> Option<std::cmp::Ordering> {
265 self.0.partial_cmp(other)
266 }
267}
268
269impl<T> ops::Deref for Name<T> {
270 type Target = T;
271
272 fn deref(&self) -> &Self::Target {
273 &self.0
274 }
275}
276
277impl<T: Display> Display for Name<T> {
278 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
279 self.0.fmt(f)
280 }
281}
282
283impl<T: Debug> Debug for Name<T> {
284 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
285 self.0.fmt(f)
286 }
287}