Skip to main content

logic_eval/parse/
text.rs

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; // Next to the dot
44            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    /// Caller is supposed to give the exact buffer for an Expr.
56    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
69// Precedence: `Paren ()` -> `Not \+` -> `And ,` -> `Or ;`.
70// - So, `parse_or` is the entry point to parse an Expr.
71// - Plus, caller is supposed to give the exact buffer for an Expr. This can be done by detecting
72//   end of clause or something like that. That's why methods here don't take `&mut ParseBuffer`.
73impl 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/// Non-empty string.
213#[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}