Skip to content

Commit e35ac6c

Browse files
committed
Separate peg::for_each_child and peg::on_first_child
1 parent 8e34434 commit e35ac6c

File tree

3 files changed

+151
-114
lines changed

3 files changed

+151
-114
lines changed

GraphQLGrammar.h

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,25 @@ namespace peg {
1515
using namespace tao::graphqlpeg;
1616

1717
template <typename _Rule>
18-
void for_each_child(const ast_node& n, std::function<bool(const ast_node&)>&& func)
18+
void for_each_child(const ast_node& n, std::function<void(const ast_node&)>&& func)
1919
{
2020
for (const auto& child : n.children)
2121
{
22-
if (child->is<_Rule>()
23-
&& !func(*child))
22+
if (child->is<_Rule>())
2423
{
24+
func(*child);
25+
}
26+
}
27+
}
28+
29+
template <typename _Rule>
30+
void on_first_child(const ast_node& n, std::function<void(const ast_node&)>&& func)
31+
{
32+
for (const auto& child : n.children)
33+
{
34+
if (child->is<_Rule>())
35+
{
36+
func(*child);
2537
return;
2638
}
2739
}

GraphQLService.cpp

Lines changed: 119 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,6 @@ rapidjson::Document Request::resolve(const peg::ast_node& root, const std::strin
358358
[&fragmentVisitor](const peg::ast_node& child)
359359
{
360360
fragmentVisitor.visit(child);
361-
return true;
362361
});
363362

364363
auto fragments = fragmentVisitor.getFragments();
@@ -368,7 +367,6 @@ rapidjson::Document Request::resolve(const peg::ast_node& root, const std::strin
368367
[&operationVisitor](const peg::ast_node& child)
369368
{
370369
operationVisitor.visit(child);
371-
return true;
372370
});
373371

374372
return operationVisitor.getValue();
@@ -406,10 +404,28 @@ void SelectionVisitor::visit(const peg::ast_node& selection)
406404

407405
void SelectionVisitor::visitField(const peg::ast_node& field)
408406
{
409-
const bool hasAlias = field.children.front()->is<peg::alias_name>();
410-
const std::string name(field.children[hasAlias ? 1 : 0]->content());
411-
const std::string alias(hasAlias ? field.children.front()->content() : name);
412-
auto itr = _resolvers.find(name);
407+
std::string name;
408+
409+
peg::on_first_child<peg::field_name>(field,
410+
[&name](const peg::ast_node& child)
411+
{
412+
name = child.content();
413+
});
414+
415+
std::string alias;
416+
417+
peg::on_first_child<peg::alias_name>(field,
418+
[&alias](const peg::ast_node& child)
419+
{
420+
alias = child.content();
421+
});
422+
423+
if (alias.empty())
424+
{
425+
alias = name;
426+
}
427+
428+
const auto itr = _resolvers.find(name);
413429

414430
if (itr == _resolvers.cend())
415431
{
@@ -425,11 +441,10 @@ void SelectionVisitor::visitField(const peg::ast_node& field)
425441

426442
bool skip = false;
427443

428-
peg::for_each_child<peg::directives>(field,
444+
peg::on_first_child<peg::directives>(field,
429445
[this, &skip](const peg::ast_node& child)
430446
{
431447
skip = shouldSkip(&child.children);
432-
return false;
433448
});
434449

435450
if (skip)
@@ -439,7 +454,7 @@ void SelectionVisitor::visitField(const peg::ast_node& field)
439454

440455
rapidjson::Document arguments(rapidjson::Type::kObjectType);
441456

442-
peg::for_each_child<peg::arguments>(field,
457+
peg::on_first_child<peg::arguments>(field,
443458
[this, &arguments](const peg::ast_node& child)
444459
{
445460
ValueVisitor visitor(_variables);
@@ -454,17 +469,14 @@ void SelectionVisitor::visitField(const peg::ast_node& field)
454469
argumentValue.CopyFrom(visitor.getValue(), argumentAllocator);
455470
arguments.AddMember(argumentName, argumentValue, argumentAllocator);
456471
}
457-
458-
return false;
459472
});
460473

461474
const peg::ast_node* selection = nullptr;
462475

463-
peg::for_each_child<peg::selection_set>(field,
476+
peg::on_first_child<peg::selection_set>(field,
464477
[&selection](const peg::ast_node& child)
465478
{
466479
selection = &child;
467-
return false;;
468480
});
469481

470482
auto& selectionAllocator = _values.GetAllocator();
@@ -497,11 +509,10 @@ void SelectionVisitor::visitFragmentSpread(const peg::ast_node& fragmentSpread)
497509

498510
if (!skip)
499511
{
500-
peg::for_each_child<peg::directives>(fragmentSpread,
512+
peg::on_first_child<peg::directives>(fragmentSpread,
501513
[this, &skip](const peg::ast_node& child)
502514
{
503515
skip = shouldSkip(&child.children);
504-
return false;
505516
});
506517
}
507518

@@ -510,26 +521,24 @@ void SelectionVisitor::visitFragmentSpread(const peg::ast_node& fragmentSpread)
510521
return;
511522
}
512523

513-
peg::for_each_child<peg::selection_set>(fragmentSpread,
524+
peg::on_first_child<peg::selection_set>(fragmentSpread,
514525
[this](const peg::ast_node& child)
515526
{
516527
for (const auto& selection : child.children)
517528
{
518529
visit(*selection);
519530
}
520-
return false;
521531
});
522532
}
523533

524534
void SelectionVisitor::visitInlineFragment(const peg::ast_node& inlineFragment)
525535
{
526536
bool skip = false;
527537

528-
peg::for_each_child<peg::directives>(inlineFragment,
538+
peg::on_first_child<peg::directives>(inlineFragment,
529539
[this, &skip](const peg::ast_node& child)
530540
{
531541
skip = shouldSkip(&child.children);
532-
return false;
533542
});
534543

535544
if (skip)
@@ -539,41 +548,23 @@ void SelectionVisitor::visitInlineFragment(const peg::ast_node& inlineFragment)
539548

540549
const peg::ast_node* typeCondition = nullptr;
541550

542-
for (const auto& child : inlineFragment.children)
551+
peg::on_first_child<peg::type_condition>(inlineFragment,
552+
[&typeCondition](const peg::ast_node& child)
543553
{
544-
if (child->is<peg::type_condition>())
545-
{
546-
typeCondition = child.get();
547-
break;
548-
}
549-
}
554+
typeCondition = &child;
555+
});
550556

551557
if (typeCondition == nullptr
552558
|| _typeNames.count(typeCondition->children.front()->content()) > 0)
553559
{
554-
for (const auto& child : inlineFragment.children)
560+
peg::on_first_child<peg::selection_set>(inlineFragment,
561+
[this](const peg::ast_node& child)
555562
{
556-
if (child->is<peg::selection_set>())
563+
for (const auto& selection : child.children)
557564
{
558-
for (const auto& selection : child->children)
559-
{
560-
if (selection->is<peg::field>())
561-
{
562-
visitField(*selection);
563-
}
564-
else if (selection->is<peg::fragment_spread>())
565-
{
566-
visitFragmentSpread(*selection);
567-
}
568-
else if (selection->is<peg::inline_fragment>())
569-
{
570-
visitInlineFragment(*selection);
571-
}
572-
}
573-
574-
break;
565+
visit(*selection);
575566
}
576-
}
567+
});
577568
}
578569
}
579570

@@ -586,7 +577,14 @@ bool SelectionVisitor::shouldSkip(const std::vector<std::unique_ptr<peg::ast_nod
586577

587578
for (const auto& directive : *directives)
588579
{
589-
const std::string name(directive->children.front()->content());
580+
std::string name;
581+
582+
peg::on_first_child<peg::directive_name>(*directive,
583+
[&name](const peg::ast_node& child)
584+
{
585+
name = child.content();
586+
});
587+
590588
const bool include = (name == "include");
591589
const bool skip = (!include && (name == "skip"));
592590

@@ -595,10 +593,40 @@ bool SelectionVisitor::shouldSkip(const std::vector<std::unique_ptr<peg::ast_nod
595593
continue;
596594
}
597595

598-
const auto argument = (directive->children.back()->is<peg::arguments>() && directive->children.back()->children.size() == 1)
599-
? directive->children.back()->children.front().get()
600-
: nullptr;
601-
const std::string argumentName((argument != nullptr) ? argument->children.front()->content() : "");
596+
peg::ast_node* argument = nullptr;
597+
std::string argumentName;
598+
bool argumentTrue = false;
599+
bool argumentFalse = false;
600+
601+
peg::on_first_child<peg::arguments>(*directive,
602+
[&argument, &argumentName, &argumentTrue, &argumentFalse](const peg::ast_node& child)
603+
{
604+
if (child.children.size() == 1)
605+
{
606+
argument = child.children.front().get();
607+
608+
peg::on_first_child<peg::argument_name>(*argument,
609+
[&argumentName](const peg::ast_node& nameArg)
610+
{
611+
argumentName = nameArg.content();
612+
});
613+
614+
peg::on_first_child<peg::true_keyword>(*argument,
615+
[&argumentTrue](const peg::ast_node& nameArg)
616+
{
617+
argumentTrue = true;
618+
});
619+
620+
if (!argumentTrue)
621+
{
622+
peg::on_first_child<peg::false_keyword>(*argument,
623+
[&argumentFalse](const peg::ast_node& nameArg)
624+
{
625+
argumentFalse = true;
626+
});
627+
}
628+
}
629+
});
602630

603631
if (argumentName != "if")
604632
{
@@ -622,11 +650,11 @@ bool SelectionVisitor::shouldSkip(const std::vector<std::unique_ptr<peg::ast_nod
622650
throw schema_exception({ error.str() });
623651
}
624652

625-
if (argument->children.back()->is<peg::true_keyword>())
653+
if (argumentTrue)
626654
{
627655
return skip;
628656
}
629-
else if (argument->children.back()->is<peg::false_keyword>())
657+
else if (argumentFalse)
630658
{
631659
return !skip;
632660
}
@@ -843,17 +871,26 @@ rapidjson::Document OperationDefinitionVisitor::getValue()
843871

844872
void OperationDefinitionVisitor::visit(const peg::ast_node& operationDefinition)
845873
{
874+
std::string operation;
875+
876+
peg::on_first_child<peg::operation_type>(operationDefinition,
877+
[&operation](const peg::ast_node& child)
878+
{
879+
operation = child.content();
880+
});
881+
882+
if (operation.empty())
883+
{
884+
operation = "query";
885+
}
886+
846887
auto position = operationDefinition.begin();
847-
auto operation = operationDefinition.children.front()->is<peg::operation_type>()
848-
? operationDefinition.children.front()->content()
849-
: std::string("query");
850888
std::string name;
851889

852-
peg::for_each_child<peg::operation_name>(operationDefinition,
890+
peg::on_first_child<peg::operation_name>(operationDefinition,
853891
[&name](const peg::ast_node& child)
854892
{
855893
name = child.content();
856-
return false;
857894
});
858895

859896
if (!_operationName.empty()
@@ -910,35 +947,44 @@ void OperationDefinitionVisitor::visit(const peg::ast_node& operationDefinition)
910947

911948
auto operationVariables = rapidjson::Document(rapidjson::Type::kObjectType);
912949

913-
peg::for_each_child<peg::variable_definitions>(operationDefinition,
950+
peg::on_first_child<peg::variable_definitions>(operationDefinition,
914951
[this, &operationVariables](const peg::ast_node& child)
915952
{
916-
auto& variableAllocator = operationVariables.GetAllocator();
917-
918-
for (const auto& variable : child.children)
953+
peg::for_each_child<peg::variable>(child,
954+
[this, &operationVariables](const peg::ast_node& variable)
919955
{
920-
const auto& nameNode = *variable->children.front();
921-
const auto& defaultValueNode = *variable->children.back();
922-
rapidjson::Value nameVar(nameNode.content().c_str() + 1, variableAllocator);
923-
rapidjson::Value valueVar;
956+
std::string variableName;
957+
958+
peg::on_first_child<peg::variable_name>(variable,
959+
[&variableName](const peg::ast_node& name)
960+
{
961+
// Skip the $ prefix
962+
variableName = name.content().c_str() + 1;
963+
});
964+
965+
rapidjson::Value nameVar(rapidjson::StringRef(variableName.c_str()));
924966
auto itrVar = _variables.FindMember(nameVar);
967+
auto& variableAllocator = operationVariables.GetAllocator();
968+
rapidjson::Value valueVar;
925969

926970
if (itrVar != _variables.MemberEnd())
927971
{
928972
valueVar.CopyFrom(itrVar->value, variableAllocator);
929973
}
930-
else if (defaultValueNode.is<peg::default_value>())
974+
else
931975
{
932-
ValueVisitor visitor(_variables);
976+
peg::on_first_child<peg::default_value>(variable,
977+
[this, &variableAllocator, &valueVar](const peg::ast_node& defaultValue)
978+
{
979+
ValueVisitor visitor(_variables);
933980

934-
visitor.visit(*defaultValueNode.children.front());
935-
valueVar.CopyFrom(visitor.getValue(), variableAllocator);
981+
visitor.visit(*defaultValue.children.front());
982+
valueVar.CopyFrom(visitor.getValue(), variableAllocator);
983+
});
936984
}
937985

938986
operationVariables.AddMember(nameVar, valueVar, variableAllocator);
939-
}
940-
941-
return false;
987+
});
942988
});
943989

944990
_result = rapidjson::Document(rapidjson::Type::kObjectType);

0 commit comments

Comments
 (0)