Skip to main content

logic_eval/parse/
text.rs

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