openfga_dsl_parser/parser/
mod.rs1use std::fmt::Display;
2
3use crate::ast::{Alias, AliasKind, Document, Relation, Type};
4use crate::lexer::{
5 token::{Token, TokenKind},
6 Lexer,
7};
8
9pub type ParseResult<T> = Result<T, ParserError>;
11
12pub struct Parser {
13 lex: Lexer,
14 curr: Token,
15 peek: Token,
16}
17
18#[derive(Debug, PartialEq, Eq)]
19pub enum ParserError {
20 UnexpectedToken(TokenKind, TokenKind),
21 UnexpectedKeyword(TokenKind),
22 UnexpectedEOF,
23}
24
25impl Parser {
26 pub fn new(input: &str) -> Self {
27 let mut lex = Lexer::new(input);
28 let curr = lex.next_token();
29 let peek = lex.next_token();
30 Self { lex, curr, peek }
31 }
32
33 pub fn from_lexer(mut lex: Lexer) -> Self {
34 let curr = lex.next_token();
35 let peek = lex.next_token();
36 Self { lex, curr, peek }
37 }
38
39 pub fn parse_document(&mut self) -> ParseResult<Document> {
40 let mut types = Vec::new();
41 while self.curr.kind() != TokenKind::EOF {
42 if self.curr.kind() != TokenKind::Type {
43 return Err(ParserError::UnexpectedToken(
44 TokenKind::Type,
45 self.curr.kind(),
46 ));
47 }
48 let ty = self.parse_type()?;
49 types.push(ty);
50 self.next_token();
51 }
52 Ok(Document { types })
53 }
54
55 fn parse_type(&mut self) -> ParseResult<Type> {
56 self.expect_peek(TokenKind::Text)?;
57 let kind = self.curr.literal().to_string();
58 let mut relations = Vec::new();
59
60 if self.peek.kind() != TokenKind::EOF && self.peek.kind() != TokenKind::Type {
61 self.expect_peek(TokenKind::Relations)?;
62
63 while self.peek.kind() == TokenKind::Define {
64 self.next_token();
65 let rel = self.parse_relation()?;
66 relations.push(rel);
67 }
68 }
69
70 Ok(Type { kind, relations })
71 }
72
73 fn parse_relation(&mut self) -> ParseResult<Relation> {
74 self.expect_peek(TokenKind::Text)?;
75 let kind = self.curr.literal().to_string();
76 self.next_token();
77 if self.curr.kind() != TokenKind::As {
78 return Ok(Relation {
80 kind,
81 aliases: Vec::new(),
82 });
83 }
84
85 self.next_token();
86 let mut aliases = Vec::new();
87 let first_alias = self.parse_alias()?;
88 aliases.push(first_alias);
89 while self.peek.kind() == TokenKind::Or || self.peek.kind() == TokenKind::But {
90 let alias = if self.peek.kind() == TokenKind::But {
91 self.next_token();
92 self.parse_but_not()?
93 } else {
94 self.next_token();
95 self.next_token();
96 self.parse_alias()?
97 };
98 aliases.push(alias)
99 }
100
101 Ok(Relation { kind, aliases })
102 }
103
104 fn parse_alias(&mut self) -> ParseResult<Alias> {
105 let kind = match self.curr.kind() {
106 TokenKind::This => AliasKind::This,
107 TokenKind::Text => AliasKind::Named(self.curr.literal().to_string()),
108 TokenKind::EOF => return Err(ParserError::UnexpectedEOF),
109 _ => return Err(ParserError::UnexpectedKeyword(self.curr.kind())),
110 };
111
112 let parent = self.parse_alias_parent()?;
113 Ok(Alias { kind, parent })
114 }
115
116 fn parse_but_not(&mut self) -> ParseResult<Alias> {
117 self.expect_peek(TokenKind::Not)?;
118 self.expect_peek(TokenKind::Text)?;
119 let kind = AliasKind::Negative(self.curr.literal().to_string());
120 let parent = self.parse_alias_parent()?;
121
122 Ok(Alias { kind, parent })
123 }
124
125 fn parse_alias_parent(&mut self) -> ParseResult<Option<String>> {
126 if self.peek.kind() == TokenKind::From {
127 self.next_token();
128 self.expect_peek(TokenKind::Text)?;
129 let parent = Some(self.curr.literal().to_string());
130 Ok(parent)
131 } else {
132 Ok(None)
133 }
134 }
135
136 fn next_token(&mut self) {
137 let prev = std::mem::replace(&mut self.peek, self.lex.next_token());
138 self.curr = prev;
139 }
140
141 fn expect_peek(&mut self, expected: TokenKind) -> ParseResult<()> {
142 if self.peek.kind() == expected {
143 self.next_token();
144 Ok(())
145 } else {
146 Err(ParserError::UnexpectedToken(expected, self.peek.kind()))
147 }
148 }
149}
150
151impl Display for ParserError {
152 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
153 use ParserError::*;
154 match self {
155 UnexpectedToken(exp, got) => {
156 write!(f, "Unexpected token: expected {exp:?}, got {got:?}")
157 }
158 UnexpectedKeyword(got) => write!(f, "Unexpected keyword: {got:?}"),
159 UnexpectedEOF => write!(f, "received an unexpected EOF"),
160 }
161 }
162}
163
164#[cfg(test)]
165mod tests {
166 use super::*;
167
168 #[test]
169 fn can_parse_types() {
170 let i = "type document
171type org";
172 let lex = Lexer::new(i);
173 let mut parser = Parser::from_lexer(lex);
174 let exp = Document {
175 types: vec![
176 Type {
177 kind: "document".into(),
178 relations: Vec::new(),
179 },
180 Type {
181 kind: "org".into(),
182 relations: Vec::new(),
183 },
184 ],
185 };
186 assert_eq!(Ok(exp), parser.parse_document());
187 }
188
189 #[test]
190 fn can_parse_relation_self() {
191 let i = "define write as self";
192 let exp = Relation {
193 kind: "write".into(),
194 aliases: vec![Alias {
195 kind: AliasKind::This,
196 parent: None,
197 }],
198 };
199
200 let lex = Lexer::new(i);
201 let mut parser = Parser::from_lexer(lex);
202 assert_eq!(Ok(exp), parser.parse_relation());
203 }
204
205 #[test]
206 fn can_parse_but_not_alias() {
207 let i = "define write as self but not owner from parent";
208 let exp = Relation {
209 kind: "write".into(),
210 aliases: vec![
211 Alias {
212 kind: AliasKind::This,
213 parent: None,
214 },
215 Alias {
216 kind: AliasKind::Negative("owner".into()),
217 parent: Some("parent".into()),
218 },
219 ],
220 };
221
222 let lex = Lexer::new(i);
223 let mut parser = Parser::from_lexer(lex);
224 assert_eq!(Ok(exp), parser.parse_relation());
225 }
226
227 #[test]
228 fn error_eof_missing_relation_type() {
229 let i = "define write as";
230 let exp = Err(ParserError::UnexpectedEOF);
231
232 let lex = Lexer::new(i);
233 let mut parser = Parser::from_lexer(lex);
234 assert_eq!(exp, parser.parse_relation());
235 }
236
237 #[test]
238 fn error_expected_keyword_relation_type() {
239 let i = "define write as type";
240 let exp = Err(ParserError::UnexpectedKeyword(TokenKind::Type));
241
242 let lex = Lexer::new(i);
243 let mut parser = Parser::from_lexer(lex);
244 assert_eq!(exp, parser.parse_relation());
245 }
246
247 #[test]
248 fn can_parse_relation_multiple_alias() {
249 let i = "define write as self or owner or thing";
250 let exp = Relation {
251 kind: "write".into(),
252 aliases: vec![
253 Alias {
254 kind: AliasKind::This,
255 parent: None,
256 },
257 Alias {
258 kind: AliasKind::Named("owner".into()),
259 parent: None,
260 },
261 Alias {
262 kind: AliasKind::Named("thing".into()),
263 parent: None,
264 },
265 ],
266 };
267
268 let lex = Lexer::new(i);
269 let mut parser = Parser::from_lexer(lex);
270 assert_eq!(Ok(exp), parser.parse_relation());
271 }
272
273 #[test]
274 fn can_parse_relation_parent_alias() {
275 let i = "define write as self or owner from parent or thing";
276 let exp = Relation {
277 kind: "write".into(),
278 aliases: vec![
279 Alias {
280 kind: AliasKind::This,
281 parent: None,
282 },
283 Alias {
284 kind: AliasKind::Named("owner".into()),
285 parent: Some("parent".into()),
286 },
287 Alias {
288 kind: AliasKind::Named("thing".into()),
289 parent: None,
290 },
291 ],
292 };
293
294 let lex = Lexer::new(i);
295 let mut parser = Parser::from_lexer(lex);
296 assert_eq!(Ok(exp), parser.parse_relation());
297 }
298
299 #[test]
300 fn can_parse_doc() {
301 let i = "type organization
302 relations
303 define member as self
304type document
305 relations
306 define owner as self
307 define can_share as owner or editor or owner from parent";
308 let exp = Document {
309 types: vec![
310 Type {
311 kind: "organization".into(),
312 relations: vec![Relation {
313 kind: "member".into(),
314 aliases: vec![Alias {
315 kind: AliasKind::This,
316 parent: None,
317 }],
318 }],
319 },
320 Type {
321 kind: "document".into(),
322 relations: vec![
323 Relation {
324 kind: "owner".into(),
325 aliases: vec![Alias {
326 kind: AliasKind::This,
327 parent: None,
328 }],
329 },
330 Relation {
331 kind: "can_share".into(),
332 aliases: vec![
333 Alias {
334 kind: AliasKind::Named("owner".into()),
335 parent: None,
336 },
337 Alias {
338 kind: AliasKind::Named("editor".into()),
339 parent: None,
340 },
341 Alias {
342 kind: AliasKind::Named("owner".into()),
343 parent: Some("parent".into()),
344 },
345 ],
346 },
347 ],
348 },
349 ],
350 };
351
352 let lex = Lexer::new(i);
353 let mut parser = Parser::from_lexer(lex);
354 assert_eq!(Ok(exp), parser.parse_document());
355 }
356}