1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
use crate::vm::{Callable, Func};
use alloc::boxed::Box;
use alloc::vec::Vec;
use core::fmt;
use object_query::Query;
use serde::Deserialize;
#[derive(Debug)]
pub enum MatchError {
Nlsd(nlsd::Error),
MismatchedStaticToken,
EmptyQuery,
UnknownQueryVar,
UnknownDataVar,
UnfilledVar,
UnexpectedEof,
ExpectedEof,
InvalidCtx,
}
pub struct Matcher<'a> {
src: &'a str,
}
impl<'a> Matcher<'a> {
pub fn new(src: &'a str) -> Self {
Self { src }
}
pub fn next_static(&mut self) -> Result<&'a str, MatchError> {
if let Ok((_, tok, rest)) = nl_parser::parse_token(self.src) {
self.src = rest;
Ok(tok)
} else {
Err(MatchError::UnexpectedEof)
}
}
pub fn next_query(&mut self) -> Result<Vec<Query<'a>>, MatchError> {
let mut nloq_de = nloq::Deserializer::from_str(self.src);
let query = nloq_de.query();
if query.is_empty() {
Err(MatchError::EmptyQuery)
} else {
self.src = nloq_de.rest();
Ok(query)
}
}
pub fn next_query_owned(&mut self) -> Result<Vec<Query<'static>>, MatchError> {
Ok(self
.next_query()?
.into_iter()
.map(|q| q.to_owned())
.collect())
}
pub fn next_data<T>(&mut self) -> Result<T, MatchError>
where
T: Deserialize<'a>,
{
let mut nlsd_de = nlsd::Deserializer::from_str(self.src);
let out = T::deserialize(&mut nlsd_de)?;
self.src = nlsd_de.rest();
Ok(out)
}
pub fn is_empty(&self) -> bool {
self.src.trim_start().is_empty()
}
}
pub trait Match<'a, C>: Sized {
fn match_str(ctx: &mut C, string: &'a str) -> Result<Self, MatchError>;
}
pub type FuncMatcher<'a, C> = fn(&mut C, &'a str) -> Result<Func<'a>, MatchError>;
pub trait MatchFunc<'a, C>: 'a + Match<'a, C> + Callable {
fn match_func(ctx: &mut C, string: &'a str) -> Result<Func<'a>, MatchError> {
Self::match_str(ctx, string).map(|this| Box::new(this) as Box<dyn Callable>)
}
}
impl<'a, C, T> MatchFunc<'a, C> for T where T: 'a + Match<'a, C> + Callable {}
impl From<nlsd::Error> for MatchError {
fn from(err: nlsd::Error) -> Self {
Self::Nlsd(err)
}
}
impl fmt::Display for MatchError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Nlsd(err) => f.write_fmt(format_args!("NLSD err: {}", err)),
Self::MismatchedStaticToken => f.write_str("mismatched static token"),
Self::EmptyQuery => f.write_str("empty NLOQ query"),
Self::UnknownQueryVar => f.write_str("mismatched query variable name"),
Self::UnknownDataVar => f.write_str("mismatched data variable name"),
Self::UnfilledVar => f.write_str("variable not set"),
Self::UnexpectedEof => f.write_str("unexpected end of file"),
Self::ExpectedEof => f.write_str("clause has extra tokens"),
Self::InvalidCtx => f.write_str("context error when parsing"),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for MatchError {}