Skip to content

Commit c5c44b0

Browse files
committed
added more parsers; more tests
1 parent 72af54e commit c5c44b0

File tree

2 files changed

+133
-38
lines changed

2 files changed

+133
-38
lines changed

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// #![deny(missing_docs)]
2+
13
#[macro_use]
24
extern crate chomp;
35

src/parser.rs

Lines changed: 131 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,29 @@
1+
// #![deny(missing_docs)]
2+
13
use std::collections::HashMap;
24

35
use std::marker::PhantomData;
46

57
use combine::{Parser, ParseResult, Stream};
68
use combine::char::{tab, char, crlf, string, letter, alpha_num};
7-
use combine::combinator::{many, none_of, or, optional, value};
9+
use combine::combinator::{between, many, none_of, or, optional, value};
810

911
pub type Name = String;
1012
pub type SelectionSet = Vec<Selection>;
1113

12-
#[derive(Debug,PartialEq)]
14+
#[derive(Debug,PartialEq,Clone)]
1315
pub struct Document {
1416
definitions: Vec<Definition>,
1517
}
1618

17-
#[derive(Debug,PartialEq)]
19+
#[derive(Debug,PartialEq,Clone)]
1820
pub enum Definition {
1921
Operation(Operation),
2022
SelectionSet(SelectionSet),
2123
Fragment(Fragment),
2224
}
2325

24-
#[derive(Debug,PartialEq)]
26+
#[derive(Debug,PartialEq,Clone)]
2527
pub struct Operation {
2628
op_type: OperationType,
2729
name: Option<Name>,
@@ -44,29 +46,39 @@ impl Operation {
4446
}
4547
}
4648

47-
#[derive(Debug,PartialEq)]
49+
#[derive(Debug,PartialEq,Clone)]
4850
pub enum OperationType {
4951
Query,
5052
Mutation,
5153
}
5254

53-
#[derive(Debug,PartialEq)]
55+
#[derive(Debug,PartialEq,Clone)]
5456
pub struct VariableDefinition {
5557
variable: Variable,
5658
var_type: Type,
5759
default_value: Option<Value>,
5860
}
5961

60-
type Variable = String;
62+
impl VariableDefinition {
63+
fn new(variable: Variable, var_type: Type, default_value: Option<Value>) -> VariableDefinition {
64+
VariableDefinition {
65+
variable: variable,
66+
var_type: var_type,
67+
default_value: default_value,
68+
}
69+
}
70+
}
71+
72+
pub type Variable = String;
6173

62-
#[derive(Debug,PartialEq)]
74+
#[derive(Debug,PartialEq,Clone)]
6375
pub enum Type {
6476
Named(Name),
6577
List(Box<Type>),
6678
NonNull(Box<Type>),
6779
}
6880

69-
#[derive(Debug,PartialEq)]
81+
#[derive(Debug,PartialEq,Clone)]
7082
pub enum Value {
7183
Variable(Variable),
7284
Int(i32),
@@ -79,26 +91,26 @@ pub enum Value {
7991
Object(HashMap<String, Value>),
8092
}
8193

82-
#[derive(Debug,PartialEq)]
94+
#[derive(Debug,PartialEq,Clone)]
8395
pub struct Directive {
8496
name: Name,
8597
arguments: Vec<Argument>,
8698
}
8799

88-
#[derive(Debug,PartialEq)]
100+
#[derive(Debug,PartialEq,Clone)]
89101
pub struct Argument {
90102
name: Name,
91103
value: Value,
92104
}
93105

94-
#[derive(Debug,PartialEq)]
106+
#[derive(Debug,PartialEq,Clone)]
95107
pub enum Selection {
96108
Field(Field),
97109
FragmentSpread(Name, Vec<Directive>),
98110
InlineFragment(Option<Type>, Vec<Directive>, SelectionSet),
99111
}
100112

101-
#[derive(Debug,PartialEq)]
113+
#[derive(Debug,PartialEq,Clone)]
102114
pub struct Field {
103115
alias: Option<Name>,
104116
name: Name,
@@ -124,7 +136,7 @@ impl Field {
124136
}
125137
}
126138

127-
#[derive(Debug,PartialEq)]
139+
#[derive(Debug,PartialEq,Clone)]
128140
pub struct Fragment {
129141
name: Name,
130142
type_condition: Type,
@@ -139,11 +151,14 @@ macro_rules! make_parser {
139151

140152
($name:ident ($input_var:ident : $input_item_type:ty) -> $output_type:ty { $($tmpl:tt)* } $($rest:tt)*) => {
141153

142-
pub struct $name<T> {
154+
#[derive(Clone)]
155+
#[allow(missing_docs)]
156+
pub struct $name<T: Clone> {
143157
_phantom: PhantomData<T>,
144158
}
145159

146-
impl<T> $name<T> {
160+
impl<T: Clone> $name<T> {
161+
#[allow(missing_docs)]
147162
pub fn new() -> Self {
148163
$name {
149164
_phantom: PhantomData
@@ -166,12 +181,15 @@ macro_rules! make_parser {
166181
($name:ident ($input_var:ident : $input_item_type:ty , $($field:ident : &$typ:ty),*)
167182
-> $output_type:ty { $($tmpl:tt)* } $($rest:tt)*) => {
168183

169-
pub struct $name<'a, T> {
184+
#[derive(Clone)]
185+
#[allow(missing_docs)]
186+
pub struct $name<'a, T: Clone> {
170187
_phantom: PhantomData<T>,
171188
$( $field: &'a $typ),*
172189
}
173190

174-
impl<'a, T> $name<'a, T> {
191+
impl<'a, T: Clone> $name<'a, T> {
192+
#[allow(missing_docs)]
175193
pub fn new($($field: &'a $typ),*) -> Self {
176194
$name {
177195
_phantom: PhantomData,
@@ -234,15 +252,33 @@ make_parser!(
234252
);
235253

236254
make_parser!(
237-
OperationTypeP(input: char) -> OperationType {
255+
OperationDefinition(input: char) -> Operation {
256+
OperationTypeParserarser::new()
257+
.and(optional(NameParser::new()))
258+
.and(optional(VariableDefinitions::new()))
259+
.map(|((op_type,name),defns)| {
260+
let variable_definitions = match defns {
261+
Some(ds) => ds,
262+
None => Vec::new()
263+
};
264+
265+
Operation::new(op_type, name, variable_definitions, Vec::new())
266+
})
267+
.parse_stream(input)
268+
}
269+
);
270+
271+
make_parser!(
272+
OperationTypeParserarser(input: char) -> OperationType {
238273
string("query").map(|_| OperationType::Query)
239274
.or(string("mutation").map(|_| OperationType::Mutation))
275+
.skip(many::<Vec<_>,_>(or(WhiteSpace::new(), LineTerminator::new(&true))))
240276
.parse_stream(input)
241277
}
242278
);
243279

244280
make_parser!(
245-
NameP(input: char) -> Name {
281+
NameParser(input: char) -> Name {
246282
or(letter(),char('_'))
247283
.map(|c| {
248284
let mut result = String::new();
@@ -254,35 +290,69 @@ make_parser!(
254290
f.push_str(&r);
255291
f
256292
})
293+
.skip(many::<Vec<_>,_>(or(WhiteSpace::new(), LineTerminator::new(&true))))
257294
.parse_stream(input)
258295
}
259296
);
260297

261298
make_parser!(
262-
Alias(input: char) -> Name {
263-
NameP::new()
299+
VariableDefinitions(input: char) -> Vec<VariableDefinition> {
300+
between(char('('), char(')'), many(VariableDefinitionP::new()))
301+
.parse_stream(input)
302+
}
303+
);
304+
305+
make_parser!(
306+
VariableDefinitionP(input: char) -> VariableDefinition {
307+
VariableParser::new()
308+
.and(TypeParser::new())
309+
.map(|(variable,var_type)| {
310+
VariableDefinition::new(variable, var_type, None)
311+
})
312+
.parse_stream(input)
313+
}
314+
);
315+
316+
make_parser!(
317+
VariableParser(input: char) -> Variable {
318+
char('$')
319+
.with(NameParser::new()) // skip the $
320+
.parse_stream(input)
321+
}
322+
);
323+
324+
make_parser!(
325+
TypeParser(input: char) -> Type {
326+
let named_type = NameParser::new().map(Type::Named);
327+
let list_type = between(char('['),char(']'), TypeParser::new()).map(|t| Type::List(Box::new(t)));
328+
329+
// i can't clone for some reason -.-
330+
let non_null_type = char('!')
331+
.with(or(
332+
NameParser::new().map(Type::Named),
333+
between(char('['),char(']'), TypeParser::new()).map(|t| Type::List(Box::new(t)))
334+
))
335+
.map(|t| Type::NonNull(Box::new(t)));
336+
337+
non_null_type.or(named_type).or(list_type)
264338
.skip(many::<Vec<_>,_>(or(WhiteSpace::new(), LineTerminator::new(&true))))
265-
.skip(char(':'))
266339
.parse_stream(input)
267340
}
268341
);
269342

270343
make_parser!(
271-
OperationDefinition(input: char) -> Operation {
272-
OperationTypeP::new()
344+
Alias(input: char) -> Name {
345+
NameParser::new()
273346
.skip(many::<Vec<_>,_>(or(WhiteSpace::new(), LineTerminator::new(&true))))
274-
.and(optional(NameP::new()))
275-
.map(|(op_type,name)| {
276-
Operation::new(op_type, name, Vec::new(), Vec::new())
277-
})
347+
.skip(char(':'))
278348
.parse_stream(input)
279349
}
280350
);
281351

282352
#[cfg(test)]
283353
mod tests {
284354
use super::*;
285-
use combine::{Parser,State};
355+
use combine::{State, Parser};
286356

287357
macro_rules! assert_successful_parse {
288358
($parser:ident,$input:expr,$result:expr) => {
@@ -297,17 +367,19 @@ mod tests {
297367

298368
#[test]
299369
fn test_parse_operationtype() {
300-
assert_successful_parse!(OperationTypeP, "query", OperationType::Query);
301-
assert_successful_parse!(OperationTypeP, "mutation", OperationType::Mutation);
370+
assert_successful_parse!(OperationTypeParserarser, "query", OperationType::Query);
371+
assert_successful_parse!(OperationTypeParserarser,
372+
"mutation",
373+
OperationType::Mutation);
302374
}
303375

304376
#[test]
305377
fn test_parse_name() {
306-
assert_successful_parse!(NameP, "_asd", String::from("_asd"));
307-
assert_successful_parse!(NameP, "aasd", String::from("aasd"));
308-
assert_successful_parse!(NameP, "zasd", String::from("zasd"));
309-
assert_successful_parse!(NameP, "Aasd", String::from("Aasd"));
310-
assert_successful_parse!(NameP, "Zasd", String::from("Zasd"));
378+
assert_successful_parse!(NameParser, "_asd", String::from("_asd"));
379+
assert_successful_parse!(NameParser, "aasd", String::from("aasd"));
380+
assert_successful_parse!(NameParser, "zasd", String::from("zasd"));
381+
assert_successful_parse!(NameParser, "Aasd", String::from("Aasd"));
382+
assert_successful_parse!(NameParser, "Zasd", String::from("Zasd"));
311383
}
312384

313385
#[test]
@@ -321,7 +393,10 @@ mod tests {
321393
fn test_parse_operation() {
322394
// named operation
323395
{
324-
let result = Operation::new(OperationType::Mutation, Some(String::from("test")), Vec::new(), Vec::new());
396+
let result = Operation::new(OperationType::Mutation,
397+
Some(String::from("test")),
398+
Vec::new(),
399+
Vec::new());
325400
assert_successful_parse!(OperationDefinition, "mutation test", result);
326401
}
327402

@@ -331,4 +406,22 @@ mod tests {
331406
assert_successful_parse!(OperationDefinition, "mutation", result);
332407
}
333408
}
409+
410+
#[test]
411+
fn test_parse_type() {
412+
assert_successful_parse!(TypeParser, "User", Type::Named(String::from("User")));
413+
assert_successful_parse!(TypeParser,
414+
"[User]",
415+
Type::List(Box::new(Type::Named(String::from("User")))));
416+
}
417+
418+
#[test]
419+
fn test_parse_nonnull_type() {
420+
assert_successful_parse!(TypeParser,
421+
"!User",
422+
Type::NonNull(Box::new(Type::Named(String::from("User")))));
423+
assert_successful_parse!(TypeParser,
424+
"![User]",
425+
Type::NonNull(Box::new(Type::List(Box::new(Type::Named(String::from("User")))))));
426+
}
334427
}

0 commit comments

Comments
 (0)