1use crate::ast::*;
7use anyhow::{anyhow, Result};
8use std::collections::HashMap;
9use std::iter::Peekable;
10use std::str::Chars;
11
12pub struct Parser {
14 chars: Peekable<Chars<'static>>,
15 position: usize,
16 line: usize,
17 column: usize,
18}
19
20impl Parser {
21 pub fn new(input: &str) -> Self {
22 let input: &'static str = unsafe { std::mem::transmute(input) };
24 Self {
25 chars: input.chars().peekable(),
26 position: 0,
27 line: 1,
28 column: 1,
29 }
30 }
31
32 pub fn parse_document(&mut self) -> Result<Document> {
34 self.skip_whitespace();
35 let mut definitions = Vec::new();
36
37 while self.chars.peek().is_some() {
38 definitions.push(self.parse_definition()?);
39 self.skip_whitespace();
40 }
41
42 if definitions.is_empty() {
43 return Err(anyhow!("Empty document"));
44 }
45
46 Ok(Document { definitions })
47 }
48
49 fn parse_definition(&mut self) -> Result<Definition> {
50 self.skip_whitespace();
51
52 if self.peek_keyword("query")
53 || self.peek_keyword("mutation")
54 || self.peek_keyword("subscription")
55 || self.peek_char('{')
56 {
57 Ok(Definition::Operation(self.parse_operation_definition()?))
58 } else if self.peek_keyword("fragment") {
59 Ok(Definition::Fragment(self.parse_fragment_definition()?))
60 } else {
61 Err(anyhow!("Unexpected definition at line {}", self.line))
62 }
63 }
64
65 fn parse_operation_definition(&mut self) -> Result<OperationDefinition> {
66 self.skip_whitespace();
67
68 let operation_type = if self.peek_char('{') {
69 OperationType::Query } else {
71 self.parse_operation_type()?
72 };
73
74 let name = if self.peek_name() && !self.peek_char('{') {
75 Some(self.parse_name()?)
76 } else {
77 None
78 };
79
80 let variable_definitions = if self.peek_char('(') {
81 self.parse_variable_definitions()?
82 } else {
83 Vec::new()
84 };
85
86 let directives = self.parse_directives()?;
87 let selection_set = self.parse_selection_set()?;
88
89 Ok(OperationDefinition {
90 operation_type,
91 name,
92 variable_definitions,
93 directives,
94 selection_set,
95 })
96 }
97
98 fn parse_operation_type(&mut self) -> Result<OperationType> {
99 let keyword = self.parse_name()?;
100 match keyword.as_str() {
101 "query" => Ok(OperationType::Query),
102 "mutation" => Ok(OperationType::Mutation),
103 "subscription" => Ok(OperationType::Subscription),
104 _ => Err(anyhow!("Invalid operation type: {}", keyword)),
105 }
106 }
107
108 fn parse_variable_definitions(&mut self) -> Result<Vec<VariableDefinition>> {
109 self.expect_char('(')?;
110 let mut definitions = Vec::new();
111
112 while !self.peek_char(')') {
113 definitions.push(self.parse_variable_definition()?);
114 if self.peek_char(',') {
115 self.next_char();
116 }
117 self.skip_whitespace();
118 }
119
120 self.expect_char(')')?;
121 Ok(definitions)
122 }
123
124 fn parse_variable_definition(&mut self) -> Result<VariableDefinition> {
125 let variable = self.parse_variable()?;
126 self.expect_char(':')?;
127 let type_ = self.parse_type()?;
128
129 let default_value = if self.peek_char('=') {
130 self.next_char();
131 Some(self.parse_value()?)
132 } else {
133 None
134 };
135
136 let directives = self.parse_directives()?;
137
138 Ok(VariableDefinition {
139 variable,
140 type_,
141 default_value,
142 directives,
143 })
144 }
145
146 fn parse_variable(&mut self) -> Result<Variable> {
147 self.expect_char('$')?;
148 let name = self.parse_name()?;
149 Ok(Variable { name })
150 }
151
152 fn parse_type(&mut self) -> Result<Type> {
153 self.skip_whitespace();
154 let mut type_ = if self.peek_char('[') {
155 self.next_char(); let inner_type = self.parse_type()?;
157 self.expect_char(']')?;
158 Type::ListType(Box::new(inner_type))
159 } else {
160 let name = self.parse_name()?;
161 Type::NamedType(name)
162 };
163
164 if self.peek_char('!') {
165 self.next_char();
166 type_ = Type::NonNullType(Box::new(type_));
167 }
168
169 Ok(type_)
170 }
171
172 fn parse_selection_set(&mut self) -> Result<SelectionSet> {
173 self.expect_char('{')?;
174 let mut selections = Vec::new();
175
176 while !self.peek_char('}') {
177 selections.push(self.parse_selection()?);
178 self.skip_whitespace();
179 }
180
181 self.expect_char('}')?;
182 Ok(SelectionSet { selections })
183 }
184
185 fn parse_selection(&mut self) -> Result<Selection> {
186 self.skip_whitespace();
187
188 if self.peek_keyword("...") {
189 self.consume_keyword("...")?;
190 if self.peek_keyword("on") {
191 Ok(Selection::InlineFragment(self.parse_inline_fragment()?))
192 } else {
193 Ok(Selection::FragmentSpread(self.parse_fragment_spread()?))
194 }
195 } else {
196 Ok(Selection::Field(self.parse_field()?))
197 }
198 }
199
200 fn parse_field(&mut self) -> Result<Field> {
201 let mut name = self.parse_name()?;
202 let mut alias = None;
203
204 if self.peek_char(':') {
206 self.next_char();
207 alias = Some(name);
208 name = self.parse_name()?;
209 }
210
211 let arguments = if self.peek_char('(') {
212 self.parse_arguments()?
213 } else {
214 Vec::new()
215 };
216
217 let directives = self.parse_directives()?;
218
219 let selection_set = if self.peek_char('{') {
220 Some(self.parse_selection_set()?)
221 } else {
222 None
223 };
224
225 Ok(Field {
226 alias,
227 name,
228 arguments,
229 directives,
230 selection_set,
231 })
232 }
233
234 fn parse_arguments(&mut self) -> Result<Vec<Argument>> {
235 self.expect_char('(')?;
236 let mut arguments = Vec::new();
237
238 while !self.peek_char(')') {
239 arguments.push(self.parse_argument()?);
240 if self.peek_char(',') {
241 self.next_char();
242 }
243 self.skip_whitespace();
244 }
245
246 self.expect_char(')')?;
247 Ok(arguments)
248 }
249
250 fn parse_argument(&mut self) -> Result<Argument> {
251 let name = self.parse_name()?;
252 self.expect_char(':')?;
253 let value = self.parse_value()?;
254
255 Ok(Argument { name, value })
256 }
257
258 fn parse_value(&mut self) -> Result<Value> {
259 self.skip_whitespace();
260
261 if self.peek_char('$') {
262 Ok(Value::Variable(self.parse_variable()?))
263 } else if self.peek_char('"') {
264 Ok(Value::StringValue(self.parse_string()?))
265 } else if self.peek_char('[') {
266 Ok(Value::ListValue(self.parse_list_value()?))
267 } else if self.peek_char('{') {
268 Ok(Value::ObjectValue(self.parse_object_value()?))
269 } else if self.peek_keyword("null") {
270 self.consume_keyword("null")?;
271 Ok(Value::NullValue)
272 } else if self.peek_keyword("true") {
273 self.consume_keyword("true")?;
274 Ok(Value::BooleanValue(true))
275 } else if self.peek_keyword("false") {
276 self.consume_keyword("false")?;
277 Ok(Value::BooleanValue(false))
278 } else if self.peek_numeric() {
279 self.parse_numeric_value()
280 } else {
281 let name = self.parse_name()?;
283 Ok(Value::EnumValue(name))
284 }
285 }
286
287 fn parse_string(&mut self) -> Result<String> {
288 self.expect_char('"')?;
289 let mut value = String::new();
290
291 while !self.peek_char('"') {
292 if self.peek_char('\\') {
293 self.next_char(); match self.next_char() {
295 Some('"') => value.push('"'),
296 Some('\\') => value.push('\\'),
297 Some('/') => value.push('/'),
298 Some('b') => value.push('\u{0008}'),
299 Some('f') => value.push('\u{000C}'),
300 Some('n') => value.push('\n'),
301 Some('r') => value.push('\r'),
302 Some('t') => value.push('\t'),
303 Some('u') => {
304 let mut hex = String::new();
306 for _ in 0..4 {
307 if let Some(ch) = self.next_char() {
308 hex.push(ch);
309 } else {
310 return Err(anyhow!("Incomplete unicode escape"));
311 }
312 }
313 let code = u32::from_str_radix(&hex, 16)
314 .map_err(|_| anyhow!("Invalid unicode escape"))?;
315 if let Some(unicode_char) = std::char::from_u32(code) {
316 value.push(unicode_char);
317 } else {
318 return Err(anyhow!("Invalid unicode code point"));
319 }
320 }
321 Some(ch) => return Err(anyhow!("Invalid escape sequence: \\{}", ch)),
322 None => return Err(anyhow!("Unterminated string")),
323 }
324 } else {
325 match self.next_char() {
326 Some(ch) => value.push(ch),
327 None => return Err(anyhow!("Unterminated string")),
328 }
329 }
330 }
331
332 self.expect_char('"')?;
333 Ok(value)
334 }
335
336 fn parse_list_value(&mut self) -> Result<Vec<Value>> {
337 self.expect_char('[')?;
338 let mut values = Vec::new();
339
340 while !self.peek_char(']') {
341 values.push(self.parse_value()?);
342 if self.peek_char(',') {
343 self.next_char();
344 }
345 self.skip_whitespace();
346 }
347
348 self.expect_char(']')?;
349 Ok(values)
350 }
351
352 fn parse_object_value(&mut self) -> Result<HashMap<String, Value>> {
353 self.expect_char('{')?;
354 let mut object = HashMap::new();
355
356 while !self.peek_char('}') {
357 let name = self.parse_name()?;
358 self.expect_char(':')?;
359 let value = self.parse_value()?;
360 object.insert(name, value);
361
362 if self.peek_char(',') {
363 self.next_char();
364 }
365 self.skip_whitespace();
366 }
367
368 self.expect_char('}')?;
369 Ok(object)
370 }
371
372 fn parse_numeric_value(&mut self) -> Result<Value> {
373 let mut number = String::new();
374
375 if self.peek_char('-') {
377 number.push(
378 self.next_char()
379 .expect("peeked character should be available"),
380 );
381 }
382
383 while let Some(&ch) = self.chars.peek() {
385 if ch.is_ascii_digit() {
386 number.push(
387 self.next_char()
388 .expect("peeked character should be available"),
389 );
390 } else {
391 break;
392 }
393 }
394
395 if self.peek_char('.') {
397 number.push(
398 self.next_char()
399 .expect("peeked character should be available"),
400 );
401
402 while let Some(&ch) = self.chars.peek() {
403 if ch.is_ascii_digit() {
404 number.push(
405 self.next_char()
406 .expect("peeked character should be available"),
407 );
408 } else {
409 break;
410 }
411 }
412
413 number
415 .parse::<f64>()
416 .map(Value::FloatValue)
417 .map_err(|_| anyhow!("Invalid float: {}", number))
418 } else {
419 if self.peek_char('e') || self.peek_char('E') {
421 number.push(
422 self.next_char()
423 .expect("peeked character should be available"),
424 );
425
426 if self.peek_char('+') || self.peek_char('-') {
427 number.push(
428 self.next_char()
429 .expect("peeked character should be available"),
430 );
431 }
432
433 while let Some(&ch) = self.chars.peek() {
434 if ch.is_ascii_digit() {
435 number.push(
436 self.next_char()
437 .expect("peeked character should be available"),
438 );
439 } else {
440 break;
441 }
442 }
443
444 number
446 .parse::<f64>()
447 .map(Value::FloatValue)
448 .map_err(|_| anyhow!("Invalid float: {}", number))
449 } else {
450 number
452 .parse::<i64>()
453 .map(Value::IntValue)
454 .map_err(|_| anyhow!("Invalid integer: {}", number))
455 }
456 }
457 }
458
459 fn parse_fragment_definition(&mut self) -> Result<FragmentDefinition> {
460 self.consume_keyword("fragment")?;
461 let name = self.parse_name()?;
462 self.consume_keyword("on")?;
463 let type_condition = self.parse_name()?;
464 let directives = self.parse_directives()?;
465 let selection_set = self.parse_selection_set()?;
466
467 Ok(FragmentDefinition {
468 name,
469 type_condition,
470 directives,
471 selection_set,
472 })
473 }
474
475 fn parse_fragment_spread(&mut self) -> Result<FragmentSpread> {
476 let fragment_name = self.parse_name()?;
477 let directives = self.parse_directives()?;
478
479 Ok(FragmentSpread {
480 fragment_name,
481 directives,
482 })
483 }
484
485 fn parse_inline_fragment(&mut self) -> Result<InlineFragment> {
486 let type_condition = if self.peek_keyword("on") {
487 self.consume_keyword("on")?;
488 Some(self.parse_name()?)
489 } else {
490 None
491 };
492
493 let directives = self.parse_directives()?;
494 let selection_set = self.parse_selection_set()?;
495
496 Ok(InlineFragment {
497 type_condition,
498 directives,
499 selection_set,
500 })
501 }
502
503 fn parse_directives(&mut self) -> Result<Vec<Directive>> {
504 let mut directives = Vec::new();
505
506 while self.peek_char('@') {
507 directives.push(self.parse_directive()?);
508 }
509
510 Ok(directives)
511 }
512
513 fn parse_directive(&mut self) -> Result<Directive> {
514 self.expect_char('@')?;
515 let name = self.parse_name()?;
516
517 let arguments = if self.peek_char('(') {
518 self.parse_arguments()?
519 } else {
520 Vec::new()
521 };
522
523 Ok(Directive { name, arguments })
524 }
525
526 fn parse_name(&mut self) -> Result<String> {
527 self.skip_whitespace();
528 let mut name = String::new();
529
530 match self.chars.peek() {
532 Some(&ch) if ch.is_alphabetic() || ch == '_' => {
533 name.push(
534 self.next_char()
535 .expect("peeked character should be available"),
536 );
537 }
538 _ => return Err(anyhow!("Expected name at line {}", self.line)),
539 }
540
541 while let Some(&ch) = self.chars.peek() {
543 if ch.is_alphanumeric() || ch == '_' {
544 name.push(
545 self.next_char()
546 .expect("peeked character should be available"),
547 );
548 } else {
549 break;
550 }
551 }
552
553 Ok(name)
554 }
555
556 fn next_char(&mut self) -> Option<char> {
559 if let Some(ch) = self.chars.next() {
560 self.position += 1;
561 if ch == '\n' {
562 self.line += 1;
563 self.column = 1;
564 } else {
565 self.column += 1;
566 }
567 Some(ch)
568 } else {
569 None
570 }
571 }
572
573 fn peek_char(&mut self, expected: char) -> bool {
574 self.skip_whitespace();
575 self.chars.peek() == Some(&expected)
576 }
577
578 fn peek_name(&mut self) -> bool {
579 self.skip_whitespace();
580 matches!(self.chars.peek(), Some(&ch) if ch.is_alphabetic() || ch == '_')
581 }
582
583 fn peek_numeric(&mut self) -> bool {
584 self.skip_whitespace();
585 matches!(self.chars.peek(), Some(&ch) if ch.is_ascii_digit() || ch == '-')
586 }
587
588 fn peek_keyword(&mut self, keyword: &str) -> bool {
589 self.skip_whitespace();
590
591 let chars: Vec<char> = self.chars.clone().take(keyword.len()).collect();
592 let word: String = chars.into_iter().collect();
593
594 if word == keyword {
595 let keyword_is_alpha = keyword
601 .chars()
602 .next()
603 .map(|c| c.is_alphabetic())
604 .unwrap_or(false);
605
606 if keyword_is_alpha {
607 let next_chars: Vec<char> =
608 self.chars.clone().skip(keyword.len()).take(1).collect();
609 if let Some(&next_ch) = next_chars.first() {
610 !next_ch.is_alphanumeric() && next_ch != '_'
611 } else {
612 true
613 }
614 } else {
615 true
616 }
617 } else {
618 false
619 }
620 }
621
622 fn consume_keyword(&mut self, keyword: &str) -> Result<()> {
623 self.skip_whitespace();
624
625 for expected_ch in keyword.chars() {
626 match self.next_char() {
627 Some(ch) if ch == expected_ch => continue,
628 Some(ch) => return Err(anyhow!("Expected '{}', found '{}'", expected_ch, ch)),
629 None => return Err(anyhow!("Unexpected end of input")),
630 }
631 }
632
633 Ok(())
634 }
635
636 fn expect_char(&mut self, expected: char) -> Result<()> {
637 self.skip_whitespace();
638 match self.next_char() {
639 Some(ch) if ch == expected => Ok(()),
640 Some(ch) => Err(anyhow!("Expected '{}', found '{}'", expected, ch)),
641 None => Err(anyhow!("Expected '{}', found end of input", expected)),
642 }
643 }
644
645 fn skip_whitespace(&mut self) {
646 while let Some(&ch) = self.chars.peek() {
647 if ch.is_whitespace() {
648 self.next_char();
649 } else if ch == '#' {
650 while let Some(&ch) = self.chars.peek() {
652 self.next_char();
653 if ch == '\n' {
654 break;
655 }
656 }
657 } else {
658 break;
659 }
660 }
661 }
662}
663
664pub fn parse_document(input: &str) -> Result<Document> {
666 let mut parser = Parser::new(input);
667 parser.parse_document()
668}
669
670#[cfg(test)]
671mod tests {
672 use super::*;
673
674 #[test]
675 fn test_simple_query() {
676 let query = "{ hello }";
677 let doc = parse_document(query).expect("should succeed");
678
679 assert_eq!(doc.definitions.len(), 1);
680 if let Definition::Operation(op) = &doc.definitions[0] {
681 assert!(matches!(op.operation_type, OperationType::Query));
682 assert_eq!(op.selection_set.selections.len(), 1);
683 }
684 }
685
686 #[test]
687 fn test_named_query() {
688 let query = "query GetUser { user { id name } }";
689 let doc = parse_document(query).expect("should succeed");
690
691 assert_eq!(doc.definitions.len(), 1);
692 if let Definition::Operation(op) = &doc.definitions[0] {
693 assert!(matches!(op.operation_type, OperationType::Query));
694 assert_eq!(op.name, Some("GetUser".to_string()));
695 }
696 }
697
698 #[test]
699 fn test_query_with_arguments() {
700 let query = r#"{ user(id: "123") { name } }"#;
701 let doc = parse_document(query).expect("should succeed");
702
703 assert_eq!(doc.definitions.len(), 1);
704 if let Definition::Operation(op) = &doc.definitions[0] {
705 if let Selection::Field(field) = &op.selection_set.selections[0] {
706 assert_eq!(field.name, "user");
707 assert_eq!(field.arguments.len(), 1);
708 assert_eq!(field.arguments[0].name, "id");
709 }
710 }
711 }
712
713 #[test]
714 fn test_query_with_variables() {
715 let query = "query GetUser($id: ID!) { user(id: $id) { name } }";
716 let doc = parse_document(query).expect("should succeed");
717
718 assert_eq!(doc.definitions.len(), 1);
719 if let Definition::Operation(op) = &doc.definitions[0] {
720 assert_eq!(op.variable_definitions.len(), 1);
721 assert_eq!(op.variable_definitions[0].variable.name, "id");
722 }
723 }
724
725 #[test]
726 fn test_fragment() {
727 let query = "fragment UserFields on User { id name email }";
728 let doc = parse_document(query).expect("should succeed");
729
730 assert_eq!(doc.definitions.len(), 1);
731 if let Definition::Fragment(frag) = &doc.definitions[0] {
732 assert_eq!(frag.name, "UserFields");
733 assert_eq!(frag.type_condition, "User");
734 assert_eq!(frag.selection_set.selections.len(), 3);
735 }
736 }
737}