Feb 15th 2023 update

This commit is contained in:
Ned Wright
2023-02-15 19:09:38 +00:00
parent f7934cd09d
commit 6a9b33ff93
159 changed files with 16474 additions and 2096 deletions

View File

@@ -1,2 +1,3 @@
add_subdirectory(graphqlparser)
add_subdirectory(yajl)
add_subdirectory(yq)

326
external/graphqlparser/.clang-tidy vendored Normal file
View File

@@ -0,0 +1,326 @@
---
Checks: 'clang-diagnostic-*,clang-analyzer-*,-clang-analyzer-alpha*,cppcoreguidelines*,modernize*,performance*,readability*,google*,-cppcoreguidelines-pro-type-cstyle-cast,-cppcoreguidelines-pro-type-reinterpret-cast,-readability-implicit-bool*,-cppcoreguidelines-pro-bounds-array-to-pointer-decay'
WarningsAsErrors: ''
HeaderFilterRegex: ''
AnalyzeTemporaryDtors: false
CheckOptions:
- key: cert-oop11-cpp.UseCERTSemantics
value: '1'
- key: cppcoreguidelines-pro-bounds-constant-array-index.GslHeader
value: ''
- key: cppcoreguidelines-pro-bounds-constant-array-index.IncludeStyle
value: '0'
- key: cppcoreguidelines-pro-type-member-init.IgnoreArrays
value: '0'
- key: google-readability-braces-around-statements.ShortStatementLines
value: '1'
- key: google-readability-function-size.StatementThreshold
value: '800'
- key: google-readability-namespace-comments.ShortNamespaceLines
value: '10'
- key: google-readability-namespace-comments.SpacesBeforeComments
value: '2'
- key: modernize-loop-convert.MaxCopySize
value: '16'
- key: modernize-loop-convert.MinConfidence
value: reasonable
- key: modernize-loop-convert.NamingStyle
value: CamelCase
- key: modernize-pass-by-value.IncludeStyle
value: llvm
- key: modernize-replace-auto-ptr.IncludeStyle
value: llvm
- key: modernize-use-auto.RemoveStars
value: '0'
- key: modernize-use-emplace.ContainersWithPushBack
value: '::std::vector;::std::list;::std::deque'
- key: modernize-use-emplace.SmartPointers
value: '::std::shared_ptr;::std::unique_ptr;::std::auto_ptr;::std::weak_ptr'
- key: modernize-use-nullptr.NullMacros
value: 'NULL'
- key: performance-faster-string-find.StringLikeClasses
value: 'std::basic_string'
- key: performance-for-range-copy.WarnOnAllAutoCopies
value: '0'
- key: performance-unnecessary-value-param.IncludeStyle
value: llvm
- key: readability-braces-around-statements.ShortStatementLines
value: '0'
- key: readability-function-size.BranchThreshold
value: '4294967295'
- key: readability-function-size.LineThreshold
value: '4294967295'
- key: readability-function-size.StatementThreshold
value: '800'
- key: readability-identifier-naming.AbstractClassCase
value: aNy_CasE
- key: readability-identifier-naming.AbstractClassPrefix
value: ''
- key: readability-identifier-naming.AbstractClassSuffix
value: ''
- key: readability-identifier-naming.ClassCase
value: aNy_CasE
- key: readability-identifier-naming.ClassConstantCase
value: aNy_CasE
- key: readability-identifier-naming.ClassConstantPrefix
value: ''
- key: readability-identifier-naming.ClassConstantSuffix
value: ''
- key: readability-identifier-naming.ClassMemberCase
value: aNy_CasE
- key: readability-identifier-naming.ClassMemberPrefix
value: ''
- key: readability-identifier-naming.ClassMemberSuffix
value: ''
- key: readability-identifier-naming.ClassMethodCase
value: aNy_CasE
- key: readability-identifier-naming.ClassMethodPrefix
value: ''
- key: readability-identifier-naming.ClassMethodSuffix
value: ''
- key: readability-identifier-naming.ClassPrefix
value: ''
- key: readability-identifier-naming.ClassSuffix
value: ''
- key: readability-identifier-naming.ConstantCase
value: aNy_CasE
- key: readability-identifier-naming.ConstantMemberCase
value: aNy_CasE
- key: readability-identifier-naming.ConstantMemberPrefix
value: ''
- key: readability-identifier-naming.ConstantMemberSuffix
value: ''
- key: readability-identifier-naming.ConstantParameterCase
value: aNy_CasE
- key: readability-identifier-naming.ConstantParameterPrefix
value: ''
- key: readability-identifier-naming.ConstantParameterSuffix
value: ''
- key: readability-identifier-naming.ConstantPrefix
value: ''
- key: readability-identifier-naming.ConstantSuffix
value: ''
- key: readability-identifier-naming.ConstexprFunctionCase
value: aNy_CasE
- key: readability-identifier-naming.ConstexprFunctionPrefix
value: ''
- key: readability-identifier-naming.ConstexprFunctionSuffix
value: ''
- key: readability-identifier-naming.ConstexprMethodCase
value: aNy_CasE
- key: readability-identifier-naming.ConstexprMethodPrefix
value: ''
- key: readability-identifier-naming.ConstexprMethodSuffix
value: ''
- key: readability-identifier-naming.ConstexprVariableCase
value: aNy_CasE
- key: readability-identifier-naming.ConstexprVariablePrefix
value: ''
- key: readability-identifier-naming.ConstexprVariableSuffix
value: ''
- key: readability-identifier-naming.EnumCase
value: aNy_CasE
- key: readability-identifier-naming.EnumConstantCase
value: aNy_CasE
- key: readability-identifier-naming.EnumConstantPrefix
value: ''
- key: readability-identifier-naming.EnumConstantSuffix
value: ''
- key: readability-identifier-naming.EnumPrefix
value: ''
- key: readability-identifier-naming.EnumSuffix
value: ''
- key: readability-identifier-naming.FunctionCase
value: aNy_CasE
- key: readability-identifier-naming.FunctionPrefix
value: ''
- key: readability-identifier-naming.FunctionSuffix
value: ''
- key: readability-identifier-naming.GlobalConstantCase
value: aNy_CasE
- key: readability-identifier-naming.GlobalConstantPrefix
value: ''
- key: readability-identifier-naming.GlobalConstantSuffix
value: ''
- key: readability-identifier-naming.GlobalFunctionCase
value: aNy_CasE
- key: readability-identifier-naming.GlobalFunctionPrefix
value: ''
- key: readability-identifier-naming.GlobalFunctionSuffix
value: ''
- key: readability-identifier-naming.GlobalVariableCase
value: aNy_CasE
- key: readability-identifier-naming.GlobalVariablePrefix
value: ''
- key: readability-identifier-naming.GlobalVariableSuffix
value: ''
- key: readability-identifier-naming.IgnoreFailedSplit
value: '0'
- key: readability-identifier-naming.InlineNamespaceCase
value: aNy_CasE
- key: readability-identifier-naming.InlineNamespacePrefix
value: ''
- key: readability-identifier-naming.InlineNamespaceSuffix
value: ''
- key: readability-identifier-naming.LocalConstantCase
value: aNy_CasE
- key: readability-identifier-naming.LocalConstantPrefix
value: ''
- key: readability-identifier-naming.LocalConstantSuffix
value: ''
- key: readability-identifier-naming.LocalVariableCase
value: aNy_CasE
- key: readability-identifier-naming.LocalVariablePrefix
value: ''
- key: readability-identifier-naming.LocalVariableSuffix
value: ''
- key: readability-identifier-naming.MacroDefinitionCase
value: aNy_CasE
- key: readability-identifier-naming.MacroDefinitionPrefix
value: ''
- key: readability-identifier-naming.MacroDefinitionSuffix
value: ''
- key: readability-identifier-naming.MemberCase
value: aNy_CasE
- key: readability-identifier-naming.MemberPrefix
value: ''
- key: readability-identifier-naming.MemberSuffix
value: ''
- key: readability-identifier-naming.MethodCase
value: aNy_CasE
- key: readability-identifier-naming.MethodPrefix
value: ''
- key: readability-identifier-naming.MethodSuffix
value: ''
- key: readability-identifier-naming.NamespaceCase
value: aNy_CasE
- key: readability-identifier-naming.NamespacePrefix
value: ''
- key: readability-identifier-naming.NamespaceSuffix
value: ''
- key: readability-identifier-naming.ParameterCase
value: aNy_CasE
- key: readability-identifier-naming.ParameterPackCase
value: aNy_CasE
- key: readability-identifier-naming.ParameterPackPrefix
value: ''
- key: readability-identifier-naming.ParameterPackSuffix
value: ''
- key: readability-identifier-naming.ParameterPrefix
value: ''
- key: readability-identifier-naming.ParameterSuffix
value: ''
- key: readability-identifier-naming.PrivateMemberCase
value: aNy_CasE
- key: readability-identifier-naming.PrivateMemberPrefix
value: ''
- key: readability-identifier-naming.PrivateMemberSuffix
value: ''
- key: readability-identifier-naming.PrivateMethodCase
value: aNy_CasE
- key: readability-identifier-naming.PrivateMethodPrefix
value: ''
- key: readability-identifier-naming.PrivateMethodSuffix
value: ''
- key: readability-identifier-naming.ProtectedMemberCase
value: aNy_CasE
- key: readability-identifier-naming.ProtectedMemberPrefix
value: ''
- key: readability-identifier-naming.ProtectedMemberSuffix
value: ''
- key: readability-identifier-naming.ProtectedMethodCase
value: aNy_CasE
- key: readability-identifier-naming.ProtectedMethodPrefix
value: ''
- key: readability-identifier-naming.ProtectedMethodSuffix
value: ''
- key: readability-identifier-naming.PublicMemberCase
value: aNy_CasE
- key: readability-identifier-naming.PublicMemberPrefix
value: ''
- key: readability-identifier-naming.PublicMemberSuffix
value: ''
- key: readability-identifier-naming.PublicMethodCase
value: aNy_CasE
- key: readability-identifier-naming.PublicMethodPrefix
value: ''
- key: readability-identifier-naming.PublicMethodSuffix
value: ''
- key: readability-identifier-naming.StaticConstantCase
value: aNy_CasE
- key: readability-identifier-naming.StaticConstantPrefix
value: ''
- key: readability-identifier-naming.StaticConstantSuffix
value: ''
- key: readability-identifier-naming.StaticVariableCase
value: aNy_CasE
- key: readability-identifier-naming.StaticVariablePrefix
value: ''
- key: readability-identifier-naming.StaticVariableSuffix
value: ''
- key: readability-identifier-naming.StructCase
value: aNy_CasE
- key: readability-identifier-naming.StructPrefix
value: ''
- key: readability-identifier-naming.StructSuffix
value: ''
- key: readability-identifier-naming.TemplateParameterCase
value: aNy_CasE
- key: readability-identifier-naming.TemplateParameterPrefix
value: ''
- key: readability-identifier-naming.TemplateParameterSuffix
value: ''
- key: readability-identifier-naming.TemplateTemplateParameterCase
value: aNy_CasE
- key: readability-identifier-naming.TemplateTemplateParameterPrefix
value: ''
- key: readability-identifier-naming.TemplateTemplateParameterSuffix
value: ''
- key: readability-identifier-naming.TypeAliasCase
value: aNy_CasE
- key: readability-identifier-naming.TypeAliasPrefix
value: ''
- key: readability-identifier-naming.TypeAliasSuffix
value: ''
- key: readability-identifier-naming.TypeTemplateParameterCase
value: aNy_CasE
- key: readability-identifier-naming.TypeTemplateParameterPrefix
value: ''
- key: readability-identifier-naming.TypeTemplateParameterSuffix
value: ''
- key: readability-identifier-naming.TypedefCase
value: aNy_CasE
- key: readability-identifier-naming.TypedefPrefix
value: ''
- key: readability-identifier-naming.TypedefSuffix
value: ''
- key: readability-identifier-naming.UnionCase
value: aNy_CasE
- key: readability-identifier-naming.UnionPrefix
value: ''
- key: readability-identifier-naming.UnionSuffix
value: ''
- key: readability-identifier-naming.ValueTemplateParameterCase
value: aNy_CasE
- key: readability-identifier-naming.ValueTemplateParameterPrefix
value: ''
- key: readability-identifier-naming.ValueTemplateParameterSuffix
value: ''
- key: readability-identifier-naming.VariableCase
value: aNy_CasE
- key: readability-identifier-naming.VariablePrefix
value: ''
- key: readability-identifier-naming.VariableSuffix
value: ''
- key: readability-identifier-naming.VirtualMethodCase
value: aNy_CasE
- key: readability-identifier-naming.VirtualMethodPrefix
value: ''
- key: readability-identifier-naming.VirtualMethodSuffix
value: ''
- key: readability-simplify-boolean-expr.ChainedConditionalAssignment
value: '0'
- key: readability-simplify-boolean-expr.ChainedConditionalReturn
value: '0'
...

23
external/graphqlparser/.gitignore vendored Normal file
View File

@@ -0,0 +1,23 @@
bison.tab.cpp
bison.tab.hpp
*.o
parser.output
dump_json_ast
Ast.h
Ast.cpp
AstVisitor.h
*.dSYM
CMakeCache.txt
CMakeFiles
CMakeScripts
Makefile
cmake_install.cmake
*.a
*.dylib
*.so
GraphQLParser.py
install_manifest.txt
build/
libgraphqlparser.pc
JsonVisitor.cpp.inc
JsonVisitor.h.inc

21
external/graphqlparser/.travis.yml vendored Normal file
View File

@@ -0,0 +1,21 @@
language: cpp
compiler:
- clang
- gcc
addons:
apt:
packages:
- valgrind
before_install:
# Versions of g++ prior to 4.8 don't have very good C++11 support.
- wget https://codeload.github.com/google/googletest/zip/release-1.8.0
&& cd test
&& unzip ../release-1.8.0
&& cd ..
&& rm release-1.8.0
script: mkdir build && cd build && cmake .. -Dtest=ON -DCMAKE_BUILD_TYPE=Debug && make && test/runTests && make memcheck

36
external/graphqlparser/AstNode.h vendored Normal file
View File

@@ -0,0 +1,36 @@
/**
* Copyright 2019-present, GraphQL Foundation
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include "location.hh"
namespace facebook {
namespace graphql {
namespace ast {
namespace visitor {
class AstVisitor;
}
class Node {
yy::location location_;
public:
explicit Node(const yy::location &location)
: location_(location) {}
virtual ~Node() {}
const yy::location &getLocation() const
{ return location_; }
virtual void accept(visitor::AstVisitor *visitor) const = 0;
};
}
}
}

148
external/graphqlparser/CMakeLists.txt vendored Normal file
View File

@@ -0,0 +1,148 @@
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(libgraphqlparser C CXX)
SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" "${CMAKE_MODULE_PATH}")
INCLUDE(version)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
FIND_PACKAGE(PythonInterp 2 REQUIRED)
IF (NOT PYTHON_VERSION_MAJOR EQUAL 2)
MESSAGE(FATAL_ERROR "Python 2 is required.")
ENDIF()
FIND_PROGRAM(CTYPESGEN_FOUND ctypesgen.py)
FIND_PACKAGE(BISON 3)
FIND_PACKAGE(FLEX)
IF (BISON_FOUND)
BISON_TARGET(graphqlparser_bison parser.ypp ${CMAKE_CURRENT_BINARY_DIR}/parser.tab.cpp)
SET(BISON_LOCATION_HEADER ${CMAKE_CURRENT_BINARY_DIR}/location.hh)
ELSE()
SET(BISON_graphqlparser_bison_OUTPUT_SOURCE ${CMAKE_CURRENT_BINARY_DIR}/parser.tab.cpp)
SET(BISON_graphqlparser_bison_OUTPUT_HEADER ${CMAKE_CURRENT_BINARY_DIR}/parser.tab.hpp)
SET(BISON_graphqlparser_bison_OUTPUTS
${BISON_graphqlparser_bison_OUTPUT_SOURCE}
${BISON_graphqlparser_bison_OUTPUT_HEADER}
${CMAKE_CURRENT_BINARY_DIR}/location.hh
${CMAKE_CURRENT_BINARY_DIR}/position.hh
${CMAKE_CURRENT_BINARY_DIR}/stack.hh)
SET(BISON_LOCATION_HEADER ${CMAKE_CURRENT_BINARY_DIR}/location.hh)
FILE(COPY
${CMAKE_CURRENT_SOURCE_DIR}/parsergen/parser.tab.cpp
${CMAKE_CURRENT_SOURCE_DIR}/parsergen/parser.tab.hpp
${CMAKE_CURRENT_SOURCE_DIR}/parsergen/location.hh
${CMAKE_CURRENT_SOURCE_DIR}/parsergen/position.hh
${CMAKE_CURRENT_SOURCE_DIR}/parsergen/stack.hh
DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
ENDIF()
IF(FLEX_FOUND)
FLEX_TARGET(GraphQLScanner lexer.lpp ${CMAKE_CURRENT_BINARY_DIR}/lexer.cpp COMPILE_FLAGS "--header-file=${CMAKE_CURRENT_BINARY_DIR}/lexer.h")
IF (BISON_FOUND)
ADD_FLEX_BISON_DEPENDENCY(GraphQLScanner graphqlparser_bison)
ENDIF()
ELSE()
SET(FLEX_GraphQLScanner_OUTPUTS ${CMAKE_CURRENT_BINARY_DIR}/lexer.cpp)
FILE(COPY
${CMAKE_CURRENT_SOURCE_DIR}/parsergen/lexer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/parsergen/lexer.h
DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
ENDIF()
FILE(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/c)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
ADD_LIBRARY(graphqlparser
JsonVisitor.cpp
${CMAKE_CURRENT_BINARY_DIR}/Ast.h
${CMAKE_CURRENT_BINARY_DIR}/Ast.cpp
${CMAKE_CURRENT_BINARY_DIR}/AstVisitor.h
${CMAKE_CURRENT_BINARY_DIR}/c/GraphQLAst.h
${CMAKE_CURRENT_BINARY_DIR}/c/GraphQLAst.cpp
${CMAKE_CURRENT_BINARY_DIR}/c/GraphQLAstForEachConcreteType.h
${CMAKE_CURRENT_BINARY_DIR}/JsonVisitor.h.inc
${CMAKE_CURRENT_BINARY_DIR}/JsonVisitor.cpp.inc
${BISON_graphqlparser_bison_OUTPUTS}
${FLEX_GraphQLScanner_OUTPUTS}
c/GraphQLAstNode.cpp
c/GraphQLAstToJSON.cpp
c/GraphQLAstVisitor.h
c/GraphQLAstVisitor.cpp
c/GraphQLParser.cpp
GraphQLParser.cpp)
# Enable this and remove CMAKE_CXX_FLAGS fiddle above when we are able
# to upgrade to CMake 2.8.12. Blocker seems to be Travis CI being on
# Ubuntu Precise; Trusty has 2.8.12.
# TARGET_COMPILE_OPTIONS(graphqlparser PUBLIC -std=gnu++11)
ADD_EXECUTABLE(dump_json_ast dump_json_ast.cpp)
TARGET_LINK_LIBRARIES(dump_json_ast graphqlparser)
FUNCTION(GENERATE_AST_FILE FILE_TYPE FILE_RELATIVE_PATH)
ADD_CUSTOM_COMMAND(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${FILE_RELATIVE_PATH}
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/ast/ast.py ${FILE_TYPE} ${CMAKE_CURRENT_SOURCE_DIR}/ast/ast.ast > ${CMAKE_CURRENT_BINARY_DIR}/${FILE_RELATIVE_PATH}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/ast/ast.ast ${CMAKE_CURRENT_SOURCE_DIR}/ast/ast.py ${CMAKE_CURRENT_SOURCE_DIR}/ast/${FILE_TYPE}.py)
ENDFUNCTION(GENERATE_AST_FILE)
GENERATE_AST_FILE(cxx Ast.h)
GENERATE_AST_FILE(cxx_visitor AstVisitor.h)
GENERATE_AST_FILE(cxx_impl Ast.cpp)
GENERATE_AST_FILE(c c/GraphQLAst.h)
GENERATE_AST_FILE(c_impl c/GraphQLAst.cpp)
GENERATE_AST_FILE(c_visitor_impl c/GraphQLAstForEachConcreteType.h)
GENERATE_AST_FILE(cxx_json_visitor_header JsonVisitor.h.inc)
GENERATE_AST_FILE(cxx_json_visitor_impl JsonVisitor.cpp.inc)
ADD_SUBDIRECTORY(python)
OPTION(test "Build tests." OFF)
INSTALL(DIRECTORY c ${CMAKE_CURRENT_BINARY_DIR}/c DESTINATION include/graphqlparser
FILES_MATCHING PATTERN "*.h"
PATTERN "build" EXCLUDE)
INSTALL(FILES
${CMAKE_CURRENT_BINARY_DIR}/Ast.h
AstNode.h
${CMAKE_CURRENT_BINARY_DIR}/AstVisitor.h
GraphQLParser.h
JsonVisitor.h
${BISON_LOCATION_HEADER}
DESTINATION include/graphqlparser)
INSTALL(TARGETS graphqlparser
LIBRARY DESTINATION lib)
if (UNIX)
# generate pkgconfig file
include(FindPkgConfig QUIET)
if(PKG_CONFIG_FOUND)
# generate .pc and install
configure_file("libgraphqlparser.pc.in" "libgraphqlparser.pc" @ONLY)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libgraphqlparser.pc"
DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/pkgconfig")
endif()
endif()
IF (test)
ADD_SUBDIRECTORY(test)
if(UNIX)
# setup valgrind
ADD_CUSTOM_TARGET(memcheck
valgrind --leak-check=full --suppressions=./test/valgrind.supp --dsymutil=yes --error-exitcode=1 ./test/runTests >/dev/null
)
endif()
ENDIF()

23
external/graphqlparser/CONTRIBUTING.md vendored Normal file
View File

@@ -0,0 +1,23 @@
# Contributing to libgraphqlparser
Please see the Code of Conduct featured at https://github.com/graphql/foundation
## Pull Requests
We actively welcome your pull requests.
1. Fork the repo and create your branch from `master`.
2. If you've added code that should be tested, add tests
3. If you've changed APIs, update the documentation.
4. Ensure the test suite passes.
5. Make sure your code lints.
## Issues
We use GitHub issues to track public bugs. Please ensure your description is
clear and has sufficient instructions to be able to reproduce the issue.
If you find a security bug, please contact the project administrators,
and do not file a public issue.
## License
By contributing to libgraphqlparser, you agree that your contributions
will be licensed under the LICENSE file in the project root directory.

View File

@@ -0,0 +1,76 @@
/**
* Copyright 2019-present, GraphQL Foundation
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "GraphQLParser.h"
#include "AstNode.h"
#include "parser.tab.hpp"
#include "lexer.h"
#include "syntaxdefs.h"
namespace facebook {
namespace graphql {
// Given properly-configured yylex, run the parser and return the
// result.
static std::unique_ptr<ast::Node> doParse(const char **outError, yyscan_t scanner, bool enableSchema) {
Node *outAST = nullptr;
yy::GraphQLParserImpl parser(enableSchema, &outAST, outError, scanner);
int failure = parser.parse();
if (failure) {
delete outAST;
}
return !failure ? std::unique_ptr<ast::Node>(outAST) : nullptr;
}
static std::unique_ptr<ast::Node> parseStringImpl(const char *text, const char **error, bool enableSchema) {
yyscan_t scanner;
struct LexerExtra extra;
yylex_init_extra(&extra, &scanner);
YY_BUFFER_STATE buffer = yy_scan_string(text, scanner);
yy_switch_to_buffer(buffer, scanner);
auto result = doParse(error, scanner, enableSchema);
yylex_destroy(scanner);
return result;
}
std::unique_ptr<ast::Node> parseString(const char *text, const char **error) {
return parseStringImpl(text, error, false);
}
std::unique_ptr<ast::Node> parseStringWithExperimentalSchemaSupport(
const char *text, const char **error) {
return parseStringImpl(text, error, true);
}
static std::unique_ptr<ast::Node> parseFileImpl(
FILE *file, const char **error, bool enableSchema) {
yyscan_t scanner;
struct LexerExtra extra;
yylex_init_extra(&extra, &scanner);
yyset_in(file, scanner);
auto result = doParse(error, scanner, enableSchema);
yylex_destroy(scanner);
return result;
}
std::unique_ptr<ast::Node> parseFile(FILE *file, const char **error) {
return parseFileImpl(file, error, false);
}
std::unique_ptr<ast::Node> parseFileWithExperimentalSchemaSupport(
FILE *file, const char **error) {
return parseFileImpl(file, error, true);
}
} // namespace graphql
} // namespace facebook

55
external/graphqlparser/GraphQLParser.h vendored Normal file
View File

@@ -0,0 +1,55 @@
/**
* Copyright 2019-present, GraphQL Foundation
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* The purpose of this file is to provide a nice interface to parsing
* GraphQL, rather than the old-fashioned interface provided by bison
* and flex.
*/
#pragma once
#include <memory>
#include <stdio.h>
namespace facebook {
namespace graphql {
namespace ast {
class Node;
}
/**
* Parse the given GraphQL source string, returning an AST. Returns
* nullptr on error and, if error is not null, places a string
* describing what went wrong in error that must be freed with free(3).
*/
std::unique_ptr<ast::Node> parseString(const char *text, const char **error);
/**
* Like parseString, but enables support for the experimental type
* definition syntax from https://github.com/facebook/graphql/pull/90 .
*/
std::unique_ptr<ast::Node> parseStringWithExperimentalSchemaSupport(
const char *text, const char **error);
/**
* Read and parse GraphQL source from the given file, returning an
* AST. Returns nullptr on error and, if error is not null, places an
* error string in error that must be freed with free(3).
*/
std::unique_ptr<ast::Node> parseFile(FILE *file, const char **error);
/**
* Like parseFile, but enables support for the experimental type
* definition syntax from https://github.com/facebook/graphql/pull/90 .
*/
std::unique_ptr<ast::Node> parseFileWithExperimentalSchemaSupport(
FILE *file, const char **error);
}
}

161
external/graphqlparser/JsonVisitor.cpp vendored Normal file
View File

@@ -0,0 +1,161 @@
/**
* Copyright 2019-present, GraphQL Foundation
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "position.hh"
#include "JsonVisitor.h"
#include <cassert>
#include <iterator>
namespace facebook {
namespace graphql {
namespace ast {
namespace visitor {
static std::string escape(const char *s) {
static char hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
std::string result;
while (unsigned char ch = *s++) {
if (ch >= '\0' && ch <= '\x1f') {
result.push_back('\\');
result.push_back('u');
result.push_back('0');
result.push_back('0');
result.push_back(ch >= 16 ? '1' : '0');
result.push_back(hex[ch % 16]);
} else if (ch == '"') {
result.push_back('\\');
result.push_back('"');
} else if (ch == '\\') {
result.push_back('\\');
result.push_back('\\');
} else {
result.push_back(ch);
}
}
return result;
}
JsonVisitor::NodeFieldPrinter::NodeFieldPrinter(
JsonVisitor &visitor,
const char *nodeKind,
const Node &node)
: visitor_(visitor)
{
if (!visitor_.printed_.empty()) {
nextChild_ = visitor_.printed_.back().begin();
}
// NOTE: If you're an Emacs user and this file's use of C++11 raw
// strings doesn't highlight correctly in c++-mode, try upgrading to
// Emacs 26 if you can.
out_ << R"({"kind":")" << nodeKind << R"(","loc":)";
printLocation(out_, node.getLocation());
}
std::string JsonVisitor::NodeFieldPrinter::finishPrinting() {
assert(!out_.str().empty());
out_ << '}';
auto result(out_.str());
#ifndef NDEBUG
out_.str("");
#endif
return result;
}
void JsonVisitor::NodeFieldPrinter::printFieldSeparator()
{
out_ << ',';
}
void JsonVisitor::NodeFieldPrinter::printSingularPrimitiveField(
const char *fieldName,
const char *value) {
printFieldSeparator();
out_ << '"' << fieldName << R"(":)";
out_ << '"' << escape(value) << '"';
}
void JsonVisitor::NodeFieldPrinter::printSingularBooleanField(
const char *fieldName,
bool value) {
printFieldSeparator();
out_ << '"' << fieldName << R"(":)";
out_ << (value ? "true" : "false");
}
void JsonVisitor::NodeFieldPrinter::printSingularObjectField(const char *fieldName) {
printFieldSeparator();
out_ << '"' << fieldName << R"(":)";
assert(!visitor_.printed_.empty());
out_ << *nextChild_++;
}
void JsonVisitor::NodeFieldPrinter::printNullableSingularObjectField(
const char *fieldName,
const void *value) {
printFieldSeparator();
out_ << '"' << fieldName << R"(":)";
if (value != nullptr) {
assert(!visitor_.printed_.empty());
out_ << *nextChild_++;
} else {
out_ << "null";
}
}
// Method invariant: printed_ contains strings for this node's children.
void JsonVisitor::NodeFieldPrinter::printLocation(
std::ostringstream &out,
const yy::location &location)
{
out << R"({"start": {"line": )" << location.begin.line
<< R"(,"column":)" << location.begin.column
<< R"(}, "end": {"line":)" << location.end.line
<< R"(,"column":)" << location.end.column
<< "}}";
}
void JsonVisitor::NodeFieldPrinter::printChildList(
std::ostringstream &out,
const std::vector<std::string>::const_iterator &childIterator,
size_t numChildren) {
out << '[';
for (size_t ii = 0; ii < numChildren; ++ii) {
if (ii != 0) {
out << ',';
}
out << *(childIterator + ii);
}
out << ']';
}
JsonVisitor::JsonVisitor() {
printed_.emplace_back();
}
void JsonVisitor::visitNode() {
printed_.emplace_back();
}
void JsonVisitor::endVisitNode(std::string &&str) {
printed_.pop_back();
printed_.back().emplace_back(std::move(str));
}
std::string JsonVisitor::getResult() const {
assert(printed_.size() == 1);
assert(printed_[0].size() == 1);
return printed_[0][0];
}
#include "JsonVisitor.cpp.inc"
} // namespace visitor
} // namespace ast
} // namespace graphql
} // namespace facebook

121
external/graphqlparser/JsonVisitor.h vendored Normal file
View File

@@ -0,0 +1,121 @@
/**
* Copyright 2019-present, GraphQL Foundation
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include "AstNode.h"
#include "AstVisitor.h"
#include <sstream>
#include <vector>
namespace facebook {
namespace graphql {
namespace ast {
namespace visitor {
/**
* Produces a JSON string describing the visited AST, in a format that
* would be a valid graphql-js AST when parsed.
*/
class JsonVisitor : public AstVisitor {
private:
using ChildrenList = std::vector<std::string>;
// Stack of lists of printed children.
// Postvisit method precondition: printed.back() contains strings
// for this node's children.
// Postvisit method postcondition: *(printed.rbegin() - 1) has had this
std::vector<ChildrenList> printed_;
// Interface to print fields for each kind of node.
// Note that, because of the post-order traversal for printing,
// field values need not be passed explicitly; they are grabbed from
// the passed-in visitor!
class NodeFieldPrinter {
private:
JsonVisitor &visitor_;
ChildrenList::const_iterator nextChild_;
std::ostringstream out_;
void printFieldSeparator();
// Prints a non-null array of n children from the given
// iterator. Does not update the iterator.
void printChildList(
std::ostringstream &out,
const std::vector<std::string>::const_iterator &childIterator,
size_t numChildren);
void printLocation(std::ostringstream &out, const yy::location &location);
public:
// Begin printing the fields for a node of the given kind at the
// given location.
NodeFieldPrinter(
JsonVisitor &visitor,
const char *nodeKind,
const Node &node);
std::string finishPrinting();
void printSingularPrimitiveField(const char *fieldName, const char *value);
void printSingularBooleanField(const char *fieldName, bool value);
void printSingularObjectField(const char *fieldName);
void printNullableSingularObjectField(const char *fieldName, const void *value);
template <typename T>
void printPluralField(
const char *fieldName,
const std::vector<std::unique_ptr<T>> &value) {
printFieldSeparator();
out_ << '"' << fieldName << "\":";
printChildList(out_, nextChild_, value.size());
nextChild_ += value.size();
}
template <typename T>
void printNullablePluralField(
const char *fieldName,
const std::vector<std::unique_ptr<T>> *value) {
printFieldSeparator();
out_ << '"' << fieldName << "\":";
if (value == nullptr) {
out_ << "null";
} else {
printChildList(out_, nextChild_, value->size());
nextChild_ += value->size();
}
}
};
// Must be called at the start of all visit methods for node types
// that have children. Maintains printed_.
void visitNode();
// Must be called at the end of all visit methods for node types
// that have children, passing the text for this node. Maintains
// printed_.
void endVisitNode(std::string &&str);
// Prints one of the many FooValue types that is prepresented with a
// single string.
template <typename ValueNode>
void endVisitValueRepresentedAsString(const char *valueKind, const ValueNode &value);
public:
JsonVisitor();
~JsonVisitor() {}
std::string getResult() const;
#include "JsonVisitor.h.inc"
};
}
}
}
}

21
external/graphqlparser/LICENSE vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) GraphQL Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,7 @@
* readability-implicit-bool is disabled because I disagree with it.
* cppcoreguidelines-pro-type-reinterpret-cast is disabled because we use it
to implement our C API.
* cppcoreguidelines-pro-bounds-array-to-pointer-decay is disabled
because it fires a false positive on every use of assert().

94
external/graphqlparser/README.md vendored Normal file
View File

@@ -0,0 +1,94 @@
# libgraphqlparser
libgraphqlparser is a parser for
[GraphQL](http://graphql.org/), a query language for describing data
requirements on complex application data models, implemented in C++11.
It can be used on its own in C++ code (or in C code via the pure C API
defined in the `c` subdirectory), or you can use it as the basis for an
extension module for your favorite programming language instead of writing
your own parser from scratch.
## Example
The provided `dump_json_ast` is a simple program that reads GraphQL
text on stdin and prints a JSON representation of the AST to stdout.
The `python` subdirectory contains an example Python binding for the
pure C API.
## Requirements
libgraphqlparser requires a C++ compiler that supports C++11. It
also requires Mac OS X or Linux.
To run tests, first, compile and install the library as described above. Then,
please download googletest from
https://github.com/google/googletest/archive/release-1.8.0.zip
and unzip it in the `test` subdirectory. In consequence, a folder
`googletest-release-1.8.0` should be contained in `test`. Next, within the
`test` folder, run `cmake .` and `make` to generate the `runTests` binary.
To execute the tests run `./test/runTests` from the main folder.
## Building libgraphqlparser
libgraphqlparser is built with [CMake](http://www.cmake.org/). If a
sufficiently-recent version of [Flex](http://flex.sourceforge.net/) and [Bison](http://www.gnu.org/software/bison/) are installed on your
system, it will use them; otherwise, it will rely on the checked-in
`parser.tab.{c,h}pp` and `lexer.{h,cpp}`.
To build libgraphqlparser from source:
```
$ # inside the project root:
$ cmake .
$ make
```
Then, to install it on your system:
```
$ make install
```
## How libgraphqlparser works
libgraphqlparser uses flex and bison to generate a C++ parser for
GraphQL. These tools work well but have idiosyncratic interfaces by
modern standards, so GraphQLParser.h provides a simple interface to
parse GraphQL.
In order to make it simpler to write code based around the GraphQL
AST, libgraphqlparser includes an extremely simple code generation
framework in the `ast/` subdirectory. This framework is used to build
the AST classes themselves, as well as a visitor over the AST. It may
be easier to understand the output of the generation steps directly
(i.e., Ast.h, Ast.cpp, and AstVisitor.h) rather than trying to read
the generation scripts. Simply building libgraphqlparser will cause
these files to be generated.
libgraphqlparser also uses the AST generation framework to build a
pure C API in the `c` subdirectory. This API can be used from C code,
and it should also simplify the task of creating bindings to other
programming languages.
## License
libgraphqlparser is MIT-licensed.
## Related Projects
- [graphql-parser (Ruby interface)](https://github.com/Shopify/graphql-parser)
- [py-graphqlparser (Python interface)](https://github.com/elastic-coders/py-graphqlparser)
- [graphql_parser (Elixir interface)](https://github.com/aarvay/graphql_parser)
- [graphql-parser-php (PHP interface)](https://github.com/dosten/graphql-parser-php)
- [graphql-libgraphqlparser (Ruby interface)](https://github.com/rmosolgo/graphql-libgraphqlparser-ruby)
## Contributing to this repo
This repository is managed by EasyCLA. Project participants must sign the free ([GraphQL Specification Membership agreement](https://preview-spec-membership.graphql.org) before making a contribution. You only need to do this one time, and it can be signed by [individual contributors](http://individual-spec-membership.graphql.org/) or their [employers](http://corporate-spec-membership.graphql.org/).
To initiate the signature process please open a PR against this repo. The EasyCLA bot will block the merge if we still need a membership agreement from you.
You can find [detailed information here](https://github.com/graphql/graphql-wg/tree/main/membership). If you have issues, please email [operations@graphql.org](mailto:operations@graphql.org).
If your company benefits from GraphQL and you would like to provide essential financial support for the systems and people that power our community, please also consider membership in the [GraphQL Foundation](https://foundation.graphql.org/join).

1
external/graphqlparser/ast/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
*.pyc

203
external/graphqlparser/ast/ast.ast vendored Normal file
View File

@@ -0,0 +1,203 @@
# Copyright 2019-present, GraphQL Foundation
# Mini-language for AST definition.
# All AST nodes extend AstNode.
# All AST nodes are visitible.
# All AST fields have a getter and a setter and are a constructor argument.
# We have concrete types (code T) and unions (code U).
# S for singular field, P for plural, ? for nullable.
# O for option in a union.
# Scalar type ontology: string, boolean
# Definitions other than OperationDefinition and FragmentDefinition
# are experimental additions for schema parsing. (We don't support
# nested unions in the AST mini-language, so I've flattened and elided
# TypeSystemDefinition and TypeDefinition.)
U Definition
O OperationDefinition
O FragmentDefinition
O SchemaDefinition
O ScalarTypeDefinition
O ObjectTypeDefinition
O InterfaceTypeDefinition
O UnionTypeDefinition
O EnumTypeDefinition
O InputObjectTypeDefinition
O TypeExtensionDefinition
O DirectiveDefinition
T Document
P Definition definitions
T OperationDefinition
S OperationKind operation
S? Name name
P? VariableDefinition variableDefinitions
P? Directive directives
S SelectionSet selectionSet
T VariableDefinition
S Variable variable
S Type type
S? Value defaultValue
T SelectionSet
P Selection selections
U Selection
O Field
O FragmentSpread
O InlineFragment
T Field
S? Name alias
S Name name
P? Argument arguments
P? Directive directives
S? SelectionSet selectionSet
T Argument
S Name name
S Value value
T FragmentSpread
S Name name
P? Directive directives
T InlineFragment
S? NamedType typeCondition
P? Directive directives
S SelectionSet selectionSet
T FragmentDefinition
S Name name
S NamedType typeCondition
P? Directive directives
S SelectionSet selectionSet
U Value
O Variable
O IntValue
O FloatValue
O StringValue
O BooleanValue
O NullValue
O EnumValue
O ListValue
O ObjectValue
T Variable
S Name name
T IntValue
S string value
T FloatValue
S string value
T StringValue
S string value
T BooleanValue
S boolean value
T NullValue
T EnumValue
S string value
T ListValue
P Value values
T ObjectValue
P ObjectField fields
T ObjectField
S Name name
S Value value
T Directive
S Name name
P? Argument arguments
U Type
O NamedType
O ListType
O NonNullType
T NamedType
S Name name
T ListType
S Type type
T NonNullType
# JS version prohibits nesting nonnull in nonnull, we can't because we
# can't support multiple unions. Fix?
S Type type
T Name
S string value
T SchemaDefinition
P? Directive directives
P OperationTypeDefinition operationTypes
T OperationTypeDefinition
S OperationKind operation
S NamedType type
T ScalarTypeDefinition
S Name name
P? Directive directives
T ObjectTypeDefinition
S Name name
P? NamedType interfaces
P? Directive directives
P FieldDefinition fields
T FieldDefinition
S Name name
P? InputValueDefinition arguments
S Type type
P? Directive directives
T InputValueDefinition
S Name name
S Type type
S? Value defaultValue
P? Directive directives
T InterfaceTypeDefinition
S Name name
P? Directive directives
P FieldDefinition fields
T UnionTypeDefinition
S Name name
P? Directive directives
P NamedType types
T EnumTypeDefinition
S Name name
P? Directive directives
P EnumValueDefinition values
T EnumValueDefinition
S Name name
P? Directive directives
T InputObjectTypeDefinition
S Name name
P? Directive directives
P InputValueDefinition fields
T TypeExtensionDefinition
S ObjectTypeDefinition definition
T DirectiveDefinition
S Name name
P? InputValueDefinition arguments
P Name locations

61
external/graphqlparser/ast/ast.py vendored Normal file
View File

@@ -0,0 +1,61 @@
#!/usr/bin/env python
# Copyright 2019-present, GraphQL Foundation
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
from importlib import import_module
def load_lang(lang):
return import_module(lang).Printer()
def print_ast(lang_module, input_file):
lang_module.start_file()
line = input_file.readline()
while line:
line = line.strip()
if line.startswith('#') or not line:
line = input_file.readline()
continue
code, rest = line.split(None, 1)
if code[0] == 'T':
lang_module.start_type(rest)
field_line = input_file.readline().strip()
while field_line:
if field_line.startswith('#'):
field_line = input_file.readline().strip()
continue
field_kind, field_type, field_name = field_line.split()
nullable = len(field_kind) > 1 and field_kind[1] == '?'
if field_kind[0] == 'S':
plural = False
elif field_kind[0] == 'P':
plural = True
else:
raise Error('Unknown field kind: ' + field_kind)
lang_module.field(field_type, field_name, nullable, plural)
field_line = input_file.readline().strip()
lang_module.end_type(rest)
elif code[0] == 'U':
lang_module.start_union(rest)
field_line = input_file.readline().strip()
while field_line:
option_code, option_type = field_line.split()
if option_code != 'O':
raise Error('Unknown code in union: ' + option_code)
lang_module.union_option(option_type)
field_line = input_file.readline().strip()
lang_module.end_union(rest)
line = input_file.readline()
lang_module.end_file()
if __name__ == '__main__':
import sys
lang = sys.argv[1]
filename = sys.argv[2]
lang_module = load_lang(lang)
print_ast(lang_module, open(filename, 'r'))

100
external/graphqlparser/ast/c.py vendored Normal file
View File

@@ -0,0 +1,100 @@
# Copyright 2019-present, GraphQL Foundation
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
from casing import snake
from license import C_LICENSE_COMMENT
def struct_name(type):
return 'GraphQLAst' + type
def return_type(type):
if type == 'OperationKind' or type == 'string':
return 'const char *'
if type == 'boolean':
return 'int'
return 'const struct %s *' % struct_name(type)
def field_prototype(owning_type, type, name, nullable, plural):
st_name = struct_name(owning_type)
if plural:
return 'int %s_get_%s_size(const struct %s *node)' % (
st_name, snake(name), st_name)
else:
ret_type = return_type(type)
return '%s %s_get_%s(const struct %s *node)' % (
ret_type, st_name, snake(name), st_name)
class Printer(object):
'''Printer for the pure C interface to the AST.
Merely a set of wrappers around the C++ interface; makes it possible
to use the AST from C code and simplifies the task of writing
bindings for other langugages.
The mapping is as follows:
- For each concrete type, you get an opaque C struct type,
accessible only by pointer.
- For each singular field of a concrete type, you get an accessor
function, returning said field in the obvious way.
- For each plural field of a concrete type, you get an accessor
function telling you its size. For access to elements of a plural
field, you can use the visitor API.
- For each union type, you get nothing specific (REVIEW), but you
can use the visitor API to work around this entirely.
'''
def __init__(self):
self._current_type = None
def start_file(self):
print C_LICENSE_COMMENT + '''/** @generated */
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
'''
def end_file(self):
print '''
#ifdef __cplusplus
}
#endif
'''
def start_type(self, name):
# Forward declarations for AST nodes.
st_name = struct_name(name)
print 'struct ' + st_name + ';'
self._current_type = name
def field(self, type, name, nullable, plural):
print field_prototype(self._current_type, type, name, nullable, plural) + ';'
def end_type(self, name):
print
def start_union(self, name):
print 'struct ' + struct_name(name) + ';'
def union_option(self, option):
pass
def end_union(self, name):
print

61
external/graphqlparser/ast/c_impl.py vendored Normal file
View File

@@ -0,0 +1,61 @@
# Copyright 2019-present, GraphQL Foundation
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
from c import field_prototype, return_type, struct_name
from casing import title
from license import C_LICENSE_COMMENT
class Printer(object):
'''Printer for the implementation of the pure C interface to the AST.
'''
def __init__(self):
self._current_type = None
def start_file(self):
print C_LICENSE_COMMENT + '''/** @generated */
#include "GraphQLAst.h"
#include "../Ast.h"
using namespace facebook::graphql::ast; // NOLINT
'''
def end_file(self):
pass
def start_type(self, name):
self._current_type = name
def field(self, type, name, nullable, plural):
print field_prototype(self._current_type, type, name, nullable, plural) + ' {'
print ' const auto *realNode = reinterpret_cast<const %s *>(node);' % self._current_type
title_name = title(name)
call_get = 'realNode->get%s()' % title_name
if plural:
if nullable:
print ' return %s ? %s->size() : 0;' % (call_get, call_get)
else:
print ' return %s.size();' % call_get
else:
if type in ['string', 'OperationKind', 'boolean']:
print ' return %s;' % call_get
else:
fmt = ' return reinterpret_cast<const struct %s *>(%s%s);'
print fmt % (struct_name(type), '' if nullable else '&', call_get)
print '}'
def end_type(self, name):
pass
def start_union(self, name):
pass
def union_option(self, option):
pass
def end_union(self, name):
pass

View File

@@ -0,0 +1,39 @@
# Copyright 2019-present, GraphQL Foundation
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
from casing import snake
from license import C_LICENSE_COMMENT
class Printer(object):
'''Printer for a simple list of types to be visited by the C visitor.
'''
def __init__(self):
self._types = []
def start_file(self):
print C_LICENSE_COMMENT + '/** @generated */'
print '#define FOR_EACH_CONCRETE_TYPE(MACRO) \\'
def start_type(self, name):
self._types.append(name)
def field(self, type, name, nullable, plural):
pass
def end_type(self, name):
pass
def end_file(self):
print ' \\\n'.join('MACRO(%s, %s)' % (name, snake(name)) for name in self._types)
def start_union(self, name):
pass
def union_option(self, option):
pass
def end_union(self, name):
pass

26
external/graphqlparser/ast/casing.py vendored Normal file
View File

@@ -0,0 +1,26 @@
# Copyright 2019-present, GraphQL Foundation
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
def title(s):
'''Capitalize the first character of s.'''
return s[0].capitalize() + s[1:]
def camel(s):
'''Lowercase the first character of s.'''
return s[0].lower() + s[1:]
def snake(s):
'''Convert from title or camelCase to snake_case.'''
if len(s) < 2:
return s.lower()
out = s[0].lower()
for c in s[1:]:
if c.isupper():
out += '_'
c = c.lower()
out += c
return out

197
external/graphqlparser/ast/cxx.py vendored Normal file
View File

@@ -0,0 +1,197 @@
# Copyright 2019-present, GraphQL Foundation
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
import cStringIO as StringIO
from casing import title
from license import C_LICENSE_COMMENT
class Printer(object):
def __init__(self):
self._type_name = None
# Map concrete type to base class
self._bases = {}
# HACK: Defer everything we print so that forward declarations for
# all classes come first. Avoids having to do 2 passes over the
# input file.
self._deferredOutput = StringIO.StringIO()
self._fields = []
def start_file(self):
print C_LICENSE_COMMENT + '''/** @generated */
#pragma once
#include "AstNode.h"
#include <memory>
#include <string>
#include <utility>
#include <vector>
namespace facebook {
namespace graphql {
namespace ast {
// The parser uses strdup to move from yytext to the heap, so we need
// to use free instead of delete.
struct CDeleter {
void operator()(const char *p) const { free((void *)p); }
};
'''
def end_file(self):
print
print self._deferredOutput.getvalue()
print '}'
print '}'
print '}'
def _base_class(self, type):
return self._bases.get(type, 'Node')
def start_type(self, name):
self._type_name = name
base = self._base_class(name)
# non-deferred!
print 'class %s;' % name
print >> self._deferredOutput, 'class %s : public %s {' % (name, base)
self._fields = []
def field(self, type, name, nullable, plural):
if type == 'OperationKind':
type = 'string'
self._fields.append((type, name, nullable, plural))
def end_type(self, name):
self._print_fields()
print >> self._deferredOutput, ' public:'
self._print_constructor()
print >> self._deferredOutput
self._print_destructor_prototype()
print >> self._deferredOutput
self._print_noncopyable()
print >> self._deferredOutput
self._print_getters()
print >> self._deferredOutput, ' void accept(visitor::AstVisitor *visitor) const override;'
print >> self._deferredOutput, '};'
print >> self._deferredOutput
print >> self._deferredOutput
self._type_name = None
self._fields = []
def _storage_type(self, type):
if type == 'string':
return 'std::unique_ptr<const char, CDeleter>'
elif type == 'boolean':
return 'bool'
else:
return 'std::unique_ptr<%s>' % type
def _print_fields(self):
for (type, name, nullable, plural) in self._fields:
storage_type = self._storage_type(type)
if plural:
storage_type = 'std::unique_ptr<std::vector<%s>>' % storage_type
print >> self._deferredOutput, ' %s %s_;' % (storage_type, name)
def _ctor_singular_type(self, type):
if type == 'string':
return 'const char *'
elif type == 'boolean':
return 'bool'
else:
return '%s *' % type
def _ctor_plural_type(self, type):
return 'std::vector<%s> *' % self._storage_type(type)
def _print_constructor(self):
print >> self._deferredOutput, ' explicit %s(' % self._type_name
print >> self._deferredOutput, ' const yy::location &location%s' % (',' if self._fields else '')
def ctor_arg(type, name, plural):
if plural:
ctor_type = self._ctor_plural_type(type)
else:
ctor_type = self._ctor_singular_type(type)
return ' %s %s' % (ctor_type, name)
print >> self._deferredOutput, ',\n'.join(ctor_arg(type, name, plural)
for (type, name, nullable, plural) in self._fields)
print >> self._deferredOutput, ' )'
def ctor_init(type, name, plural):
# Strings are const char *, just pass.
# Vectors are passed by pointer and we take ownership.
# Node types are passed in by pointer and we take ownership.
value = name
return ' %s_(%s)' % (name, value)
print >> self._deferredOutput, ' : %s(location)%s' % (self._base_class(self._type_name), ',' if self._fields else '')
print >> self._deferredOutput, ',\n'.join(ctor_init(type, name, plural)
for (type, name, nullable, plural)
in self._fields)
print >> self._deferredOutput, ' {}'
def _getter_type(self, type, nullable, plural):
if plural and nullable:
return 'const std::vector<%s>*' % self._storage_type(type)
elif plural:
return 'const std::vector<%s>&' % self._storage_type(type)
if type == 'string':
assert not nullable
return 'const char *'
elif type == 'boolean':
assert not nullable
return 'bool'
elif nullable:
return 'const %s*' % type
else:
return 'const %s&' % type
def _getter_value_to_return(self, raw_value, type, nullable, plural):
if plural and nullable:
return raw_value + '.get()'
elif plural:
return '*%s' % raw_value
elif type == 'boolean':
return raw_value
elif nullable or type == 'string':
return '%s.get()' % raw_value
else:
return '*%s' % raw_value
def _print_getters(self):
for (type, name, nullable, plural) in self._fields:
print >> self._deferredOutput, ' %s get%s() const' % (
self._getter_type(type, nullable, plural),
title(name))
print >> self._deferredOutput, ' { return %s; }' % (
self._getter_value_to_return(name + '_', type, nullable, plural))
print >> self._deferredOutput
def _print_destructor_prototype(self):
print >> self._deferredOutput, ' ~%s() {}' % self._type_name
def _print_noncopyable(self):
print >> self._deferredOutput, ' %s(const %s&) = delete;' % (
self._type_name, self._type_name)
print >> self._deferredOutput, ' %s& operator=(const %s&) = delete;' % (
self._type_name, self._type_name)
def start_union(self, name):
self._type_name = name
# non-deferred!
print 'class %s;' % name
print >> self._deferredOutput, 'class %s : public Node {' % name
print >> self._deferredOutput, ' public:'
self._print_constructor()
print >> self._deferredOutput, '};'
print >> self._deferredOutput
def union_option(self, type):
assert type not in self._bases, '%s cannot appear in more than one union!' % type
self._bases[type] = self._type_name
def end_union(self, name):
pass

61
external/graphqlparser/ast/cxx_impl.py vendored Normal file
View File

@@ -0,0 +1,61 @@
# Copyright 2019-present, GraphQL Foundation
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
from license import C_LICENSE_COMMENT
class Printer(object):
def __init__(self):
pass
def start_file(self):
print C_LICENSE_COMMENT + '''/** @generated */
#include "Ast.h"
#include "AstVisitor.h"
namespace facebook {
namespace graphql {
namespace ast {
'''
def end_file(self):
print '} // namespace ast'
print '} // namespace graphql'
print '} // namespace facebook'
def start_type(self, name):
print '''void %s::accept(visitor::AstVisitor *visitor) const {
if (visitor->visit%s(*this)) {
''' % (name, name)
def field(self, type, name, nullable, plural):
if type in ['OperationKind', 'string', 'boolean']:
return
if plural:
accept = '{ for (const auto &x : *%s_) { x->accept(visitor); } }' % name
if nullable:
accept = 'if (%s_) %s' % (name, accept)
print ' ' + accept
else:
accept = '%s_->accept(visitor);' % name
if nullable:
accept = 'if (%s_) { %s }' % (name, accept)
print ' ' + accept
def end_type(self, name):
print ''' }
visitor->endVisit%s(*this);
}
''' % name
def start_union(self, name):
pass
def union_option(self, option):
pass
def end_union(self, name):
pass

View File

@@ -0,0 +1,42 @@
# Copyright 2019-present, GraphQL Foundation
# All rights reserved.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
from casing import title
from license import C_LICENSE_COMMENT
class Printer(object):
def __init__(self):
self._anyFieldIsANode = False
def start_file(self):
print C_LICENSE_COMMENT + '/** @generated */'
def end_file(self):
pass
def start_type(self, name):
self._anyFieldIsANode = False
def end_type(self, name):
titleName = title(name)
if self._anyFieldIsANode:
print 'bool visit%s(const %s &node) override;' % (titleName, titleName)
print 'void endVisit%s(const %s &node) override;' % (titleName, titleName)
print
def field(self, type, name, nullable, plural):
if (not self._anyFieldIsANode and
type not in ('OperationKind', 'string', 'boolean')):
self._anyFieldIsANode = True
def start_union(self, name):
pass
def union_option(self, option):
pass
def end_union(self, name):
pass

View File

@@ -0,0 +1,80 @@
# Copyright 2019-present, GraphQL Foundation
# All rights reserved.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
from casing import title
from license import C_LICENSE_COMMENT
class Printer(object):
def __init__(self):
self._fields = []
def start_file(self):
print C_LICENSE_COMMENT + '/** @generated */'
def end_file(self):
pass
def start_type(self, name):
self._fields = []
def field(self, type, name, nullable, plural):
if type == 'OperationKind':
type = 'string'
self._fields.append((type, name, nullable, plural))
def end_type(self, name):
titleName = title(name)
anyFieldIsANode = any(type not in ('string, boolean')
for (type, _, _ ,_) in self._fields)
if anyFieldIsANode:
print '''bool JsonVisitor::visit%s(const %s &node) {
visitNode();
return true;
}
''' % (titleName, titleName)
print '''void JsonVisitor::endVisit%(tn)s(const %(tn)s &node) {
NodeFieldPrinter fields(*this, "%(tn)s", node);''' % {'tn': titleName}
for (type, fieldName, nullable, plural) in self._fields:
funcName = None
if type == 'string':
assert not plural, 'plural string fields not supported yet'
funcName = 'printSingularPrimitiveField'
elif type == 'boolean':
assert not plural, 'plural boolean fields not supported yet'
funcName = 'printSingularBooleanField'
elif not nullable and not plural:
# Special case: singular object fields don't need the value passed.
print ' fields.printSingularObjectField("%s");' % fieldName
continue
else:
nullable_str = 'Nullable' if nullable else ''
plural_str = 'Plural' if plural else 'SingularObject'
funcName = 'print%s%sField' % (nullable_str, plural_str)
assert funcName is not None
print ' fields.%s("%s", node.get%s());' % (
funcName, fieldName, title(fieldName))
if anyFieldIsANode:
print '''
endVisitNode(fields.finishPrinting());
}
'''
else:
print '''
printed_.back().emplace_back(fields.finishPrinting());
}
'''
def start_union(self, name):
pass
def union_option(self, option):
pass
def end_union(self, name):
pass

View File

@@ -0,0 +1,64 @@
# Copyright 2019-present, GraphQL Foundation
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
from casing import camel, title
from license import C_LICENSE_COMMENT
class Printer(object):
def __init__(self):
pass
def start_file(self):
print C_LICENSE_COMMENT + '''/** @generated */
#pragma once
#include "Ast.h"
namespace facebook {
namespace graphql {
namespace ast {
namespace visitor {
class AstVisitor {
public:
virtual ~AstVisitor() {}
'''
def end_file(self):
print '};' # end AstVisitor
print
print '}'
print '}'
print '}'
print '}'
def start_type(self, name):
titleName = title(name)
camelName = camel(titleName)
print ' virtual bool visit%s(const %s &%s) { return true; }' % (
titleName,
titleName,
camelName)
print ' virtual void endVisit%s(const %s &%s) { }' % (
titleName,
titleName,
camelName)
print
def end_type(self, name):
pass
def field(self, type, name, nullable, plural):
pass
def start_union(self, name):
pass
def union_option(self, option):
pass
def end_union(self, name):
pass

65
external/graphqlparser/ast/js.py vendored Normal file
View File

@@ -0,0 +1,65 @@
# Copyright 2019-present, GraphQL Foundation
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
class Printer(object):
def __init__(self):
pass
def start_file(self):
print '''/* @flow */
/* @generated */
/* jshint ignore:start */
/**
* Copyright 2019-present, GraphQL Foundation
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
type Node = {
kind: string;
start?: ?number;
end?: ?number;
};
type OperationKind = 'query' | 'mutation' | 'subscription';'''
def end_file(self):
pass
def start_type(self, name):
print
print 'type %s = Node & {' % name
kind = name
if kind == 'GenericType':
kind = 'Type'
print ' kind: \'%s\';' % kind
def end_type(self, name):
print '}'
def _js_type(self, type, plural):
if plural:
type = 'Array<%s>' % type
return type
def field(self, type, name, nullable, plural):
nullable_char = '?' if nullable else ''
js_type = self._js_type(type, plural)
print ' %(name)s%(nullable_char)s: %(nullable_char)s%(js_type)s;' % locals()
def start_union(self, name):
print ('type %s = ' % name),
self._current_options = []
def union_option(self, type):
self._current_options.append(type)
def end_union(self, name):
print '\n | '.join(self._current_options)
print
self._current_options = None

10
external/graphqlparser/ast/license.py vendored Normal file
View File

@@ -0,0 +1,10 @@
# Copyright 2019-present GraphQL Foundation
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
C_LICENSE_COMMENT = '''/**
* Copyright 2019-present GraphQL Foundation
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'''

3
external/graphqlparser/c/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
GraphQLAst.h
GraphQLAst.cpp
GraphQLAstForEachConcreteType.h

View File

@@ -0,0 +1,25 @@
/**
* Copyright 2019-present, GraphQL Foundation
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "GraphQLAstNode.h"
#include "../AstNode.h"
using facebook::graphql::ast::Node;
void graphql_node_get_location(const struct GraphQLAstNode *node,
struct GraphQLAstLocation *location) {
const auto *realNode = reinterpret_cast<const Node *>(node);
const auto &loc = realNode->getLocation();
location->beginLine = loc.begin.line;
location->beginColumn = loc.begin.column;
location->endLine = loc.end.line;
location->endColumn = loc.end.column;
}
void graphql_node_free(struct GraphQLAstNode *node) {
delete reinterpret_cast<Node *>(node);
}

View File

@@ -0,0 +1,33 @@
/**
* Copyright 2019-present, GraphQL Foundation
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/* Opaque type representing a generic AST node. */
struct GraphQLAstNode;
/* A location in the AST. */
struct GraphQLAstLocation {
unsigned int beginLine;
unsigned int beginColumn;
unsigned int endLine;
unsigned int endColumn;
};
/* Fills location with location information for the given node. */
void graphql_node_get_location(const struct GraphQLAstNode *node,
struct GraphQLAstLocation *location);
void graphql_node_free(struct GraphQLAstNode *node);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,21 @@
/**
* Copyright 2019-present, GraphQL Foundation
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "GraphQLAstToJSON.h"
#include <cstring>
#include "../JsonVisitor.h"
#include "../AstNode.h"
const char *graphql_ast_to_json(const struct GraphQLAstNode *node)
{
facebook::graphql::ast::visitor::JsonVisitor visitor;
reinterpret_cast<const facebook::graphql::ast::Node *>(node)->accept(&visitor);
return strdup(visitor.getResult().c_str());
}

View File

@@ -0,0 +1,24 @@
/**
* Copyright 2019-present, GraphQL Foundation
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
struct GraphQLAstNode;
/**
* Serialize the given AST to JSON. The returned C string must be
* freed with free().
*/
const char *graphql_ast_to_json(const struct GraphQLAstNode *node);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,55 @@
/**
* Copyright 2019-present, GraphQL Foundation
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "c/GraphQLAstVisitor.h"
#include "AstVisitor.h"
using namespace facebook::graphql::ast; // NOLINT
#include "c/GraphQLAstForEachConcreteType.h"
#define DECLARE_VISIT(type, snake_type) \
bool visit##type(const type &node) override; \
void endVisit##type(const type &node) override;
class CVisitorBridge : public visitor::AstVisitor {
const struct GraphQLAstVisitorCallbacks *callbacks_;
void *userData_;
public:
explicit CVisitorBridge(const struct GraphQLAstVisitorCallbacks *callbacks,
void *userData)
: callbacks_(callbacks), userData_(userData) {}
FOR_EACH_CONCRETE_TYPE(DECLARE_VISIT)
};
#define IMPLEMENT_VISIT(type, snake_type) \
bool CVisitorBridge::visit##type(const type &node) { \
if (callbacks_->visit_##snake_type) { \
return callbacks_->visit_##snake_type( \
(const struct GraphQLAst##type *)&node, userData_); \
} \
return true; \
} \
void CVisitorBridge::endVisit##type(const type &node) { \
if (callbacks_->end_visit_##snake_type) { \
callbacks_->end_visit_##snake_type( \
(const struct GraphQLAst##type *)&node, userData_); \
} \
}
FOR_EACH_CONCRETE_TYPE(IMPLEMENT_VISIT)
void graphql_node_visit(const struct GraphQLAstNode *node,
const struct GraphQLAstVisitorCallbacks *callbacks,
void *userData)
{
CVisitorBridge visitor(callbacks, userData);
if (node) {
reinterpret_cast<const facebook::graphql::ast::Node *>(node)->accept(&visitor);
}
}

View File

@@ -0,0 +1,53 @@
/**
* Copyright 2019-present, GraphQL Foundation
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include "c/GraphQLAst.h"
#include "c/GraphQLAstForEachConcreteType.h"
#ifdef __cplusplus
extern "C" {
#endif
#define TYPEDEFS(type, snake_type) \
typedef int (*visit_##snake_type##_func)(const struct GraphQLAst##type *snake_type, void *user_data); \
typedef void (*end_visit_##snake_type##_func)(const struct GraphQLAst##type *snake_type, void *user_data);
FOR_EACH_CONCRETE_TYPE(TYPEDEFS)
#define FUNC_MEMBER(type, snake_type) \
visit_##snake_type##_func visit_##snake_type; \
end_visit_##snake_type##_func end_visit_##snake_type;
/**
* Functions to be called when particular AST nodes are encountered.
* visit_* functions are called in pre-order, and may return non-zero to
* continue recursing into children (if any), or zero to skip them. end_visit_*
* functions are called in post-order. Any particular function may be set to
* NULL to indicate that the caller is not interested in the corresponding type
* of AST node. (NULL visit_* functions act as though they simply returned
* non-zero.)
*/
struct GraphQLAstVisitorCallbacks {
FOR_EACH_CONCRETE_TYPE(FUNC_MEMBER)
};
struct GraphQLAstNode;
/**
* Walk the AST rooted at the given node, issuing callbacks from the given
* callbacks struct as appropriate. userData will be passed as the userData
* argument to each callback.
*/
void graphql_node_visit(const struct GraphQLAstNode *node,
const struct GraphQLAstVisitorCallbacks *callbacks,
void *userData);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,35 @@
/**
* Copyright 2019-present, GraphQL Foundation
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "GraphQLParser.h"
#include "../GraphQLParser.h"
#include "../AstNode.h"
#include <cstdlib>
struct GraphQLAstNode *graphql_parse_string(const char *text, const char **error) {
return reinterpret_cast<struct GraphQLAstNode *>(facebook::graphql::parseString(text, error).release());
}
struct GraphQLAstNode *graphql_parse_string_with_experimental_schema_support(
const char *text, const char **error) {
return reinterpret_cast<struct GraphQLAstNode *>(facebook::graphql::parseStringWithExperimentalSchemaSupport(
text, error).release());
}
struct GraphQLAstNode *graphql_parse_file(FILE *file, const char **error) {
return reinterpret_cast<struct GraphQLAstNode *>(facebook::graphql::parseFile(file, error).release());
}
struct GraphQLAstNode *graphql_parse_file_with_experimental_schema_support(
FILE *file, const char **error) {
return reinterpret_cast<struct GraphQLAstNode *>(facebook::graphql::parseFileWithExperimentalSchemaSupport(file, error).release());
}
void graphql_error_free(const char *error) {
std::free((void *)(error)); // NOLINT
}

View File

@@ -0,0 +1,54 @@
/**
* Copyright 2019-present, GraphQL Foundation
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* This file provides C wrappers for ../GraphQLParser.h.
*/
struct GraphQLAstNode;
/**
* Parse the given GraphQL source string, returning an AST. Returns
* NULL on error. Return value must be freed with
* graphql_node_free(). If NULL is returned and error is not NULL, an
* error message is placed in error and must be freed with
* graphql_error_free().
*/
struct GraphQLAstNode *graphql_parse_string(
const char *text, const char **error);
struct GraphQLAstNode *graphql_parse_string_with_experimental_schema_support(
const char *text, const char **error);
/**
* Read and parse GraphQL source from the given file, returning an
* AST. Returns nullptr on error. Return value must be freed with
* graphql_node_free(). If NULL is returned and error is not NULL, an
* error message is placed in error and must be freed with
* graphql_error_free().
*/
struct GraphQLAstNode *graphql_parse_file(FILE *file, const char **error);
struct GraphQLAstNode *graphql_parse_file_with_experimental_schema_support(
FILE *file, const char **error);
/**
* Frees an error.
*/
void graphql_error_free(const char *error);
#ifdef __cplusplus
}
#endif

3
external/graphqlparser/clang-tidy-all.sh vendored Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/sh
# Copyright 2019-present, GraphQL Foundation
find . -name '*.cpp' | grep -v lexer | grep -v googletest | grep -v tab.cpp | xargs clang-tidy -p build

View File

@@ -0,0 +1,16 @@
# Copyright 2019-present, GraphQL Foundation
find_package(Git QUIET)
# default version string
set(LIBGRAPHQLPARSER_VERSION "0.0-dev")
if(GIT_EXECUTABLE AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git)
execute_process(COMMAND ${GIT_EXECUTABLE} describe --tags
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE LIBGRAPHQLPARSER_VERSION
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
string(SUBSTRING ${LIBGRAPHQLPARSER_VERSION} 1 -1 LIBGRAPHQLPARSER_VERSION)
endif()

View File

@@ -0,0 +1,48 @@
/**
* Copyright 2019-present, GraphQL Foundation
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "AstNode.h"
#include "GraphQLParser.h"
#include "c/GraphQLAstToJSON.h"
#include <cstdio>
#include <cstdlib>
#include <iostream>
using std::cout;
using std::cerr;
using std::endl;
using std::fopen;
using std::fclose;
using std::free;
int main(int argc, char **argv) {
const char *error;
FILE * in;
if (argc > 1) {
in = fopen(argv[1], "r"); // NOLINT
} else {
in = stdin;
}
auto AST = facebook::graphql::parseFile(in, &error);
if (argc > 1) {
fclose(in);
}
if (!AST) {
cerr << "Parser failed with error: " << error << endl;
free((void *)error); // NOLINT
return 1;
}
const char *json = graphql_ast_to_json(reinterpret_cast<const struct GraphQLAstNode *>(AST.get()));
puts(json);
free((void *)json); // NOLINT
return 0;
}

1
external/graphqlparser/go/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
go

20
external/graphqlparser/go/README.md vendored Normal file
View File

@@ -0,0 +1,20 @@
# About
This directory contains an example using the libgraphqlparser C library from [Go](https://golang.org/project/).
For an overview of binding to C libraries in Go, please see the [cgo documentation](https://github.com/golang/go/wiki/cgo).
Specifically, please read the overview of [Function pointer callbacks](https://github.com/golang/go/wiki/cgo#function-pointer-callbacks) in Go and C.
## Building and Running
To build with Go, please ensure that you have `pkg-config` installed for your
system.
Assuming pkg-config has been installed, it should be possible to then build
using Go in the normal fashion:
```sh
$ cd libgraphqlparser/go
$ go build
$ ./go
field : myfield
Example error: 1.18-19: syntax error, unexpected on, expecting ( or @ or {
```

18
external/graphqlparser/go/callbacks.go vendored Normal file
View File

@@ -0,0 +1,18 @@
/**
* Copyright 2019-present, GraphQL Foundation
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package main
/*
struct GraphQLAstField;
int printField(struct GraphQLAstField *field, void *unused);
int printField_cgo(struct GraphQLAstField *field, void *unused) {
return printField(field, unused);
}
*/
import "C"

64
external/graphqlparser/go/gotest.go vendored Normal file
View File

@@ -0,0 +1,64 @@
/**
* Copyright 2019-present, GraphQL Foundation
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package main
/*
#cgo pkg-config: libgraphqlparser
#include "c/GraphQLAst.h"
#include "c/GraphQLAstNode.h"
#include "c/GraphQLAstVisitor.h"
#include "c/GraphQLParser.h"
#include <stdlib.h>
int printField_cgo(struct GraphQLAstField *field, void *unused);
*/
import "C"
import "errors"
import "fmt"
import "unsafe"
//export printField
func printField(field *C.struct_GraphQLAstField, unused unsafe.Pointer) int {
fmt.Printf("field : %s\n", C.GoString(C.GraphQLAstName_get_value(C.GraphQLAstField_get_name(field))))
return 0
}
func parse(query string) (*C.struct_GraphQLAstNode, error) {
graphql := C.CString(query)
cError := (*C.char)(nil)
ast := C.graphql_parse_string(graphql, &cError)
C.free(unsafe.Pointer(graphql))
if ast == nil {
err := errors.New(C.GoString(cError))
C.graphql_error_free(cError)
return nil, err
}
return ast, nil
}
func main() {
ast, err := parse("query myquery { myfield }")
if err != nil {
fmt.Printf("BUG: unexpected parse error: %s", err)
return
}
visitor_callbacks := C.struct_GraphQLAstVisitorCallbacks{visit_field: (C.visit_field_func)(C.printField_cgo)}
C.graphql_node_visit(ast, &visitor_callbacks, nil)
C.graphql_node_free(ast)
ast2, err2 := parse("query errorQuery on oops { myfield }")
if err2 != nil {
fmt.Printf("Example error: %s\n", err2)
}
if ast2 != nil {
fmt.Printf("BUG: we should have got a null AST back, but we got %s\n", ast2)
}
}

324
external/graphqlparser/lexer.lpp vendored Normal file
View File

@@ -0,0 +1,324 @@
/**
* Copyright 2019-present, GraphQL Foundation
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
%{
#include <algorithm>
#include <cassert>
#include <cctype>
#include <climits>
#include <cstdio>
#include <string>
#include <vector>
#include "location.hh"
#include "position.hh"
#include "parser.tab.hpp"
#include "syntaxdefs.h"
// Keep track of token lengths.
#define YY_USER_ACTION yyextra->loc.columns(yyleng);
static void escape(char c, char *buf);
static std::string clean_up_block_string(const std::string &str);
%}
%option bison-bridge bison-locations
%option noyywrap batch noinput nounput
%option reentrant
%option extra-type="struct LexerExtra *"
%x STRING_STATE
%x BLOCK_STRING_STATE
%x C_COMMENT_STATE
%x LINE_COMMENT_STATE
FLOAT -?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)?
INTEGER -?(0|[1-9][0-9]*)
IDENTIFIER [_A-Za-z][_0-9A-Za-z]*
VARIABLE $[_0-9A-Za-z]+
BOM \xef\xbb\xbf
CRLF \r\n
BADCHAR [\x00-\x08\x0b\x0c\x0e-\x1f]
GOODCHAR [^\x00-\x08\x0b\x0c\x0e-\x1f]
STRINGCHAR [^\x00-\x1f\\\x22]
blank [ \t,]
newline [\n\r]
notnewline [^\n\r]
%%
%{
yyextra->loc.step();
%}
<STRING_STATE>{
\" {
BEGIN(INITIAL);
yylval->str = yyextra->str.c_str();
*yylloc = yyextra->loc;
return yy::GraphQLParserImpl::token::TOK_STRING;
}
{newline} {
throw make_error(yyextra->loc, "Unterminated string");
}
<<EOF>> {
throw make_error(yyextra->loc, "Unterminated string at EOF");
}
{STRINGCHAR}+ {
char *p = yytext;
while (*p) {
yyextra->str.push_back(*p++);
}
}
\\\" { yyextra->str.push_back('"'); }
\\\\ { yyextra->str.push_back('\\'); }
\\\/ { yyextra->str.push_back('/'); }
\\n { yyextra->str.push_back('\n'); }
\\t { yyextra->str.push_back('\t'); }
\\r { yyextra->str.push_back('\r'); }
\\b { yyextra->str.push_back('\b'); }
\\f { yyextra->str.push_back('\f'); }
\\u[0-9A-Fa-f]{4} {
int ch;
sscanf(yytext + 2, "%x", &ch);
yyextra->str.push_back(ch);
}
\\u { throw make_error(yyextra->loc, "bad Unicode escape sequence"); }
\\. { throw make_error(yyextra->loc, std::string("bad escape sequence \\") + yytext[1]); }
}
<BLOCK_STRING_STATE>{
<<EOF>> {
throw make_error(yyextra->loc, "Unterminated block string at EOF");
}
{BADCHAR} {
throw make_error(yyextra->loc, std::string("Invalid character ") + yytext[0]);
}
{GOODCHAR} {
/* Can't use {GOODCHAR}+ because that would be a better match for
""" than the explicit rule! */
yyextra->str.push_back(*yytext);
}
\\\"\"\" {
yyextra->str.append(3, '"');
}
\"\"\" {
BEGIN(INITIAL);
yyextra->str = clean_up_block_string(yyextra->str);
yylval->str = yyextra->str.c_str();
*yylloc = yyextra->loc;
return yy::GraphQLParserImpl::token::TOK_STRING;
}
}
<LINE_COMMENT_STATE>{
{CRLF} { yyextra->loc.lines(yyleng / 2); yyextra->loc.step(); BEGIN(INITIAL); }
{newline} { yyextra->loc.lines(yyleng); yyextra->loc.step(); BEGIN(INITIAL); }
{notnewline}+ /* eat comment character */
}
<INITIAL>{
{blank}+ { yyextra->loc.step(); }
{BOM}+ { yyextra->loc.step(); yyextra->loc.step(); yyextra->loc.step(); }
{CRLF}+ { yyextra->loc.lines(yyleng / 2); yyextra->loc.step(); }
{newline}+ { yyextra->loc.lines(yyleng); yyextra->loc.step(); }
# {yyextra->loc.step(); BEGIN(LINE_COMMENT_STATE); }
directive { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_DIRECTIVE; }
enum { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_ENUM; }
extend { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_EXTEND; }
false { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_FALSE; }
fragment { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_FRAGMENT; }
implements { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_IMPLEMENTS; }
input { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_INPUT; }
interface { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_INTERFACE; }
mutation { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_MUTATION; }
null { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_NULL; }
on { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_ON; }
query { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_QUERY; }
scalar { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_SCALAR; }
schema { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_SCHEMA; }
subscription { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_SUBSCRIPTION; }
true { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_TRUE; }
type { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_TYPE; }
union { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_UNION; }
{INTEGER} { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_INTEGER; }
{FLOAT} { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_FLOAT; }
{IDENTIFIER} { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_IDENTIFIER; }
{VARIABLE} { yylval->str = yytext + 1; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_VARIABLE; }
"!" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_BANG; }
"(" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_LPAREN; }
")" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_RPAREN; }
"..." { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_ELLIPSIS; }
":" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_COLON; }
"=" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_EQUAL; }
"@" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_AT; }
"[" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_LBRACKET; }
"]" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_RBRACKET; }
"{" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_LBRACE; }
"|" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_PIPE; }
"}" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_RBRACE; }
<<EOF>> { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_EOF; }
\"\"\" {
BEGIN(BLOCK_STRING_STATE);
yyextra->str.clear();
}
\" {
BEGIN(STRING_STATE);
yyextra->str.clear();
}
}
<INITIAL,STRING_STATE,LINE_COMMENT_STATE>. {
char buf[6];
escape(yytext[0], buf);
throw make_error(
yyextra->loc,
std::string("unrecognized character ") + buf);
}
%%
static void escape(char c, char *buf) {
if (std::isgraph(c)) {
*buf = c;
buf[1] = '\0';
} else {
buf[0] = '\\';
buf[2] = '\0';
switch (c) {
case '\a':
buf[1] = 'a';
break;
case '\b':
buf[1] = 'b';
break;
case '\f':
buf[1] = 'f';
break;
case '\n':
buf[1] = 'n';
break;
case '\r':
buf[1] = 'r';
break;
case '\t':
buf[1] = 't';
break;
case '\v':
buf[1] = 'v';
break;
default:
buf[1] = 'x';
std::snprintf(buf + 2, 3, "%x", ((int)c & 0xFF));
break;
}
}
}
static std::vector<std::string> splitLines(const std::string &str) {
std::vector<std::string> lines;
auto it = str.begin();
while (it != str.end()) {
static char terminators[2] = {'\r', '\n'};
auto nextIt = std::find_first_of(it, str.end(), terminators, terminators + sizeof(terminators));
lines.emplace_back(str.data() + (it - str.begin()), nextIt - it);
if (nextIt != str.end()) {
auto advancedIt = nextIt + 1;
if (advancedIt != str.end()) {
if (*nextIt == '\r' && *advancedIt == '\n') {
++advancedIt;
}
}
nextIt = std::move(advancedIt);
}
it = std::move(nextIt);
}
return lines;
}
static int count_leading_whitespace(const std::string &str) {
auto pos = str.find_first_not_of(" \t", 0, strlen(" \t"));
if (pos == std::string::npos) {
return str.length();
}
return pos;
}
static bool is_all_whitespace(const std::string &str) {
return count_leading_whitespace(str) == str.length();
}
static std::string clean_up_block_string(const std::string &str) {
auto lines = splitLines(str);
bool first = true;
int commonIndent = INT_MAX;
for (const auto &line : lines) {
if (first) {
first = false;
continue;
}
const auto indent = count_leading_whitespace(line);
if (indent < line.length()) {
if (indent < commonIndent) {
commonIndent = indent;
}
}
}
if (commonIndent != INT_MAX) {
first = true;
for (auto &line : lines) {
if (first) {
first = false;
continue;
}
line.erase(0, commonIndent);
}
}
const auto firstNonBlankIt = std::find_if(lines.begin(), lines.end(), [](const std::string &line) {
return !is_all_whitespace(line);
});
lines.erase(lines.begin(), firstNonBlankIt);
const auto firstNonBlankReverseIt = std::find_if(lines.rbegin(), lines.rend(), [](const std::string &line) {
return !is_all_whitespace(line);
});
lines.erase(lines.end() - (firstNonBlankReverseIt - lines.rbegin()), lines.end());
std::string formatted;
first = true;
for (const auto &line: lines) {
if (first) {
first = false;
} else {
formatted.push_back('\n');
}
formatted.append(line);
}
return formatted;
}

View File

@@ -0,0 +1,11 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include/graphqlparser
Name: @CMAKE_PROJECT_NAME@
Description: facebook graphql parsing library
Version: @LIBGRAPHQLPARSER_VERSION@
Libs: -L${libdir} -lgraphqlparser
Libs.private:
Cflags: -I${includedir}

693
external/graphqlparser/parser.ypp vendored Normal file
View File

@@ -0,0 +1,693 @@
/**
* Copyright 2019-present, GraphQL Foundation
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
%require "3"
%skeleton "lalr1.cc"
%defines
%define parser_class_name {GraphQLParserImpl}
%define api.token.prefix {TOK_}
%define parse.error verbose
%code requires
{
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <sstream>
#include <string>
#include "Ast.h"
using facebook::graphql::ast::Node;
using facebook::graphql::ast::Name;
using facebook::graphql::ast::Definition;
using facebook::graphql::ast::Document;
using facebook::graphql::ast::OperationDefinition;
using facebook::graphql::ast::VariableDefinition;
using facebook::graphql::ast::Variable;
using facebook::graphql::ast::SelectionSet;
using facebook::graphql::ast::Selection;
using facebook::graphql::ast::Field;
using facebook::graphql::ast::Argument;
using facebook::graphql::ast::FragmentSpread;
using facebook::graphql::ast::InlineFragment;
using facebook::graphql::ast::FragmentDefinition;
using facebook::graphql::ast::Value;
using facebook::graphql::ast::IntValue;
using facebook::graphql::ast::FloatValue;
using facebook::graphql::ast::StringValue;
using facebook::graphql::ast::BooleanValue;
using facebook::graphql::ast::NullValue;
using facebook::graphql::ast::EnumValue;
using facebook::graphql::ast::ListValue;
using facebook::graphql::ast::ObjectValue;
using facebook::graphql::ast::ObjectField;
using facebook::graphql::ast::Directive;
using facebook::graphql::ast::Type;
using facebook::graphql::ast::NamedType;
using facebook::graphql::ast::ListType;
using facebook::graphql::ast::NonNullType;
// Experimental schema support.
using facebook::graphql::ast::SchemaDefinition;
using facebook::graphql::ast::ScalarTypeDefinition;
using facebook::graphql::ast::ObjectTypeDefinition;
using facebook::graphql::ast::InterfaceTypeDefinition;
using facebook::graphql::ast::UnionTypeDefinition;
using facebook::graphql::ast::EnumTypeDefinition;
using facebook::graphql::ast::InputObjectTypeDefinition;
using facebook::graphql::ast::TypeExtensionDefinition;
using facebook::graphql::ast::DirectiveDefinition;
using facebook::graphql::ast::SchemaDefinition;
using facebook::graphql::ast::OperationTypeDefinition;
using facebook::graphql::ast::ScalarTypeDefinition;
using facebook::graphql::ast::ObjectTypeDefinition;
using facebook::graphql::ast::FieldDefinition;
using facebook::graphql::ast::InputValueDefinition;
using facebook::graphql::ast::InterfaceTypeDefinition;
using facebook::graphql::ast::UnionTypeDefinition;
using facebook::graphql::ast::EnumTypeDefinition;
using facebook::graphql::ast::EnumValueDefinition;
using facebook::graphql::ast::InputObjectTypeDefinition;
using facebook::graphql::ast::TypeExtensionDefinition;
using facebook::graphql::ast::DirectiveDefinition;
union yystype { \
const char *str; \
const char *heapStr; \
Name *name; \
Definition *definition; \
Document *document; \
OperationDefinition *operationDefinition; \
VariableDefinition *variableDefinition; \
Variable *variable; \
SelectionSet *selectionSet; \
Selection *selection; \
Field *field; \
Argument *argument; \
FragmentSpread *fragmentSpread; \
InlineFragment *inlineFragment; \
FragmentDefinition *fragmentDefinition; \
Value *value; \
IntValue *intValue; \
FloatValue *floatValue; \
StringValue *stringValue; \
BooleanValue *booleanValue; \
NullValue *nullValue; \
EnumValue *enumValue; \
ListValue *arrayValue; \
ObjectValue *objectValue; \
ObjectField *objectField; \
Directive *directive; \
Type *type; \
NamedType *namedType; \
ListType *listType; \
NonNullType *nonNullType; \
\
std::vector<std::unique_ptr<Definition>> *definitionList; \
std::vector<std::unique_ptr<VariableDefinition>> *variableDefinitionList; \
std::vector<std::unique_ptr<Selection>> *selectionList; \
std::vector<std::unique_ptr<Field>> *fieldList; \
std::vector<std::unique_ptr<Argument>> *argumentList; \
std::vector<std::unique_ptr<Value>> *valueList; \
std::vector<std::unique_ptr<ObjectField>> *objectFieldList; \
std::vector<std::unique_ptr<Directive>> *directiveList; \
\
SchemaDefinition *schemaDefinition; \
ScalarTypeDefinition *scalarTypeDefinition; \
ObjectTypeDefinition *objectTypeDefinition; \
InterfaceTypeDefinition *interfaceTypeDefinition; \
UnionTypeDefinition *unionTypeDefinition; \
EnumTypeDefinition *enumTypeDefinition; \
InputObjectTypeDefinition *inputObjectTypeDefinition; \
TypeExtensionDefinition *typeExtensionDefinition; \
DirectiveDefinition *directiveDefinition; \
OperationTypeDefinition *operationTypeDefinition; \
InputValueDefinition *inputValueDefinition; \
FieldDefinition *fieldDefinition; \
EnumValueDefinition *enumValueDefinition; \
\
std::vector<std::unique_ptr<OperationTypeDefinition>> *operationTypeDefinitionList; \
std::vector<std::unique_ptr<NamedType>> *typeNameList; \
std::vector<std::unique_ptr<InputValueDefinition>> *inputValueDefinitionList; \
std::vector<std::unique_ptr<FieldDefinition>> *fieldDefinitionList; \
std::vector<std::unique_ptr<Name>> *nameList; \
std::vector<std::unique_ptr<EnumValueDefinition>> *enumValueDefinitionList; \
};
#define YYSTYPE union yystype
#define YYLTYPE yy::location
}
%lex-param { void *scanner }
%parse-param { bool enableSchema } { Node **outAST } { const char **outError } { void *scanner }
%locations
%code
{
#include "lexer.h"
#include "syntaxdefs.h"
}
%token EOF 0
%token <str> DIRECTIVE "directive"
%token <str> ENUM "enum"
%token <str> EXTEND "extend"
%token <str> FALSE "false"
%token <str> FRAGMENT "fragment"
%token <str> IMPLEMENTS "implements"
%token <str> INPUT "input"
%token <str> INTERFACE "interface"
%token <str> MUTATION "mutation"
%token <str> NULL "null"
%token <str> QUERY "query"
%token <str> ON "on"
%token <str> SCALAR "scalar"
%token <str> SCHEMA "schema"
%token <str> SUBSCRIPTION "subscription"
%token <str> TRUE "true"
%token <str> TYPE "type"
%token <str> UNION "union"
%token BANG "!"
%token LPAREN "("
%token RPAREN ")"
%token ELLIPSIS "..."
%token COLON ":"
%token EQUAL "="
%token AT "@"
%token LBRACKET "["
%token RBRACKET "]"
%token LBRACE "{"
%token PIPE "|"
%token RBRACE "}"
%token <str> VARIABLE
%token <str> INTEGER
%token <str> FLOAT
%token <str> STRING
%token <str> IDENTIFIER
%type <variable> variable
%type <intValue> int_value
%type <floatValue> float_value
%type <stringValue> string_value
%type <document> start
%type <document> document
%type <name> fragment_name
%type <name> name
%type <name> name_opt
%type <definitionList> definition_list
%type <definition> definition
%type <definition> schema_gate
%type <operationDefinition> operation_definition
%type <variableDefinitionList> variable_definitions
%type <variableDefinitionList> variable_definition_list
%type <variableDefinition> variable_definition
%type <value> default_value_opt
%type <value> default_value
%type <selectionSet> selection_set
%type <selectionSet> selection_set_opt
%type <selectionList> selection_list
%type <selection> selection
%type <field> field
%type <argumentList> arguments_opt
%type <argumentList> arguments
%type <argumentList> argument_list
%type <argument> argument
%type <fragmentSpread> fragment_spread
%type <inlineFragment> inline_fragment
%type <fragmentDefinition> fragment_definition
%type <namedType> type_condition
%type <value> value
%type <value> value_const
%type <booleanValue> boolean_value
%type <nullValue> null_value
%type <enumValue> enum_value
%type <arrayValue> list_value
%type <arrayValue> list_value_const
%type <valueList> value_list
%type <valueList> value_const_list
%type <objectValue> object_value
%type <objectValue> object_value_const
%type <objectFieldList> object_field_list
%type <objectFieldList> object_field_const_list
%type <objectField> object_field
%type <objectField> object_field_const
%type <directiveList> directives
%type <directiveList> directives_opt
%type <directiveList> directive_list
%type <directive> directive
%type <type> type
%type <namedType> type_name
%type <listType> list_type
%type <nonNullType> non_null_type
%type <heapStr> operation_type
%type <schemaDefinition> schema_definition;
%type <scalarTypeDefinition> scalar_type_definition;
%type <objectTypeDefinition> object_type_definition;
%type <interfaceTypeDefinition> interface_type_definition;
%type <unionTypeDefinition> union_type_definition;
%type <enumTypeDefinition> enum_type_definition;
%type <inputObjectTypeDefinition> input_object_type_definition;
%type <typeExtensionDefinition> type_extension_definition;
%type <directiveDefinition> directive_definition;
%type <operationTypeDefinition> operation_type_definition;
%type <operationTypeDefinitionList> operation_type_definition_list;
%type <typeNameList> type_name_list;
%type <typeNameList> implements_interfaces_opt;
%type <typeNameList> union_members;
%type <fieldDefinition> field_definition;
%type <fieldDefinitionList> field_definition_list;
%type <inputValueDefinitionList> arguments_definition_opt;
%type <inputValueDefinitionList> arguments_definition;
%type <inputValueDefinitionList> input_value_definition_list;
%type <inputValueDefinition> input_value_definition;
%type <enumValueDefinition> enum_value_definition;
%type <nameList> directive_locations;
%type <enumValueDefinitionList> enum_value_definition_list;
%destructor { } <str>
%destructor { free((void *)$$); } <heapStr>
%destructor { } <document> /* we steal it and put it in outAST, don't free! */
%destructor { delete $$; } <*>
%printer { yyoutput << $$; } <str>
%%
start: document { *outAST = $1; }
;
/* All of the non-identifier tokens are to accommodate various flavors
of name that don't include those tokens. */
fragment_name: DIRECTIVE { $$ = new Name(@1, strdup($1)); }
| ENUM { $$ = new Name(@1, strdup($1)); }
| EXTEND { $$ = new Name(@1, strdup($1)); }
| FALSE { $$ = new Name(@1, strdup($1)); }
| FRAGMENT { $$ = new Name(@1, strdup($1)); }
| IDENTIFIER { $$ = new Name(@1, strdup($1)); }
| IMPLEMENTS { $$ = new Name(@1, strdup($1)); }
| INPUT { $$ = new Name(@1, strdup($1)); }
| INTERFACE { $$ = new Name(@1, strdup($1)); }
| MUTATION { $$ = new Name(@1, strdup($1)); }
| NULL { $$ = new Name(@1, strdup($1)); }
| QUERY { $$ = new Name(@1, strdup($1)); }
| SCALAR { $$ = new Name(@1, strdup($1)); }
| SCHEMA { $$ = new Name(@1, strdup($1)); }
| SUBSCRIPTION { $$ = new Name(@1, strdup($1)); }
| TRUE { $$ = new Name(@1, strdup($1)); }
| TYPE { $$ = new Name(@1, strdup($1)); }
| UNION { $$ = new Name(@1, strdup($1)); }
;
name: fragment_name
| ON { $$ = new Name(@1, strdup($1)); }
;
name_opt:
%empty {$$ = nullptr;}
| name
;
/* 2.2 Document */
document: definition_list { $$ = new Document(@$, $1); }
;
definition_list:definition { $$ = new std::vector<std::unique_ptr<Definition>>(); $$->emplace_back($1); }
| definition_list definition { $1->emplace_back($2); $$ = $1; }
;
definition: operation_definition { $$ = static_cast<Definition *>($1); }
| fragment_definition { $$ = static_cast<Definition *>($1); }
| schema_gate {
if (!enableSchema) {
error(@$, "schema support disabled");
// %destructor doesn't work with YYERROR. See
// https://www.gnu.org/software/bison/manual/html_node/Destructor-Decl.html
delete $$;
YYERROR;
}
$$ = static_cast<Definition *>($1);
}
;
schema_gate: schema_definition { $$ = static_cast<Definition *>($1); }
| scalar_type_definition { $$ = static_cast<Definition *>($1); }
| object_type_definition { $$ = static_cast<Definition *>($1); }
| interface_type_definition { $$ = static_cast<Definition *>($1); }
| union_type_definition { $$ = static_cast<Definition *>($1); }
| enum_type_definition { $$ = static_cast<Definition *>($1); }
| input_object_type_definition { $$ = static_cast<Definition *>($1); }
| type_extension_definition { $$ = static_cast<Definition *>($1); }
| directive_definition { $$ = static_cast<Definition *>($1); }
;
/* 2.2.1 Operations */
operation_definition:
selection_set { $$ = new OperationDefinition(@$, strdup("query"), nullptr, nullptr, nullptr, $1); }
| operation_type name_opt selection_set { $$ = new OperationDefinition(@$, $1, $2, nullptr, nullptr, $3); }
| operation_type name_opt variable_definitions selection_set { $$ = new OperationDefinition(@$, $1, $2, $3, nullptr, $4); }
| operation_type name_opt directives selection_set { $$ = new OperationDefinition(@$, $1, $2, nullptr, $3, $4); }
| operation_type name_opt variable_definitions directives selection_set { $$ = new OperationDefinition(@$, $1, $2, $3, $4, $5); }
;
operation_type: QUERY { $$ = strdup($1); }
| MUTATION { $$ = strdup($1); }
| SUBSCRIPTION { $$ = strdup($1); }
;
variable_definitions:
"(" variable_definition_list ")" { $$ = $2; }
;
variable_definition_list:
variable_definition { $$ = new std::vector<std::unique_ptr<VariableDefinition>>(); $$->emplace_back($1); }
| variable_definition_list variable_definition { $1->emplace_back($2); $$ = $1; }
;
variable: VARIABLE { $$ = new Variable(@$, new Name(@1, strdup($1))); }
;
variable_definition:
variable ":" type default_value_opt { $$ = new VariableDefinition(@$, $1, $3, $4); }
;
default_value_opt:
%empty { $$ = nullptr; }
| default_value
;
default_value: "=" value_const { $$ = $2; }
;
selection_set:
"{" selection_list "}" { $$ = new SelectionSet(@$, $2); }
;
selection_set_opt:
%empty { $$ = nullptr; }
| selection_set
;
selection_list: selection { $$ = new std::vector<std::unique_ptr<Selection>>(); $$->emplace_back($1); }
| selection_list selection { $1->emplace_back($2); $$ = $1; }
;
selection: field { $$ = static_cast<Selection *>($1); }
| fragment_spread { $$ = static_cast<Selection *>($1); }
| inline_fragment { $$ = static_cast<Selection *>($1); }
;
field: name arguments_opt directives_opt selection_set_opt { $$ = new Field(@$, nullptr, $1, $2, $3, $4); }
| name ":" name arguments_opt directives_opt selection_set_opt { $$ = new Field(@$, $1, $3, $4, $5, $6); }
;
arguments: "(" argument_list ")" { $$ = $2; }
;
arguments_opt: %empty { $$ = nullptr; }
| arguments { $$ = $1; }
;
argument_list: argument { $$ = new std::vector<std::unique_ptr<Argument>>(); $$->emplace_back($1); }
| argument_list argument { $1->emplace_back($2); $$ = $1; }
;
argument: name ":" value { $$ = new Argument(@$, $1, $3); }
;
/* 2.2.6 Fragments */
fragment_spread:
"..." fragment_name directives_opt { $$ = new FragmentSpread(@$, $2, $3); }
;
inline_fragment:
"..." "on" type_condition directives_opt selection_set { $$ = new InlineFragment(@$, $3, $4, $5); }
| "..." directives_opt selection_set { $$ = new InlineFragment(@$, nullptr, $2, $3); }
;
fragment_definition:
"fragment" fragment_name "on" type_condition directives_opt selection_set { $$ = new FragmentDefinition(@$, $2, $4, $5, $6); }
;
type_condition: type_name
;
/* 2.2.7 Input Values */
value: variable { $$ = static_cast<Value *>($1); }
| int_value { $$ = static_cast<Value *>($1); }
| float_value { $$ = static_cast<Value *>($1); }
| string_value { $$ = static_cast<Value *>($1); }
| boolean_value { $$ = static_cast<Value *>($1); }
| null_value { $$ = static_cast<Value *>($1); }
| enum_value { $$ = static_cast<Value *>($1); }
| list_value { $$ = static_cast<Value *>($1); }
| object_value { $$ = static_cast<Value *>($1); }
;
int_value: INTEGER { $$ = new IntValue(@$, strdup($1)); }
;
float_value: FLOAT { $$ = new FloatValue(@$, strdup($1)); }
;
string_value: STRING { $$ = new StringValue(@$, strdup($1)); }
;
value_const: int_value { $$ = static_cast<Value *>($1); }
| float_value { $$ = static_cast<Value *>($1); }
| string_value { $$ = static_cast<Value *>($1); }
| boolean_value { $$ = static_cast<Value *>($1); }
| null_value { $$ = static_cast<Value *>($1); }
| enum_value { $$ = static_cast<Value *>($1); }
| list_value_const { $$ = static_cast<Value *>($1); }
| object_value_const { $$ = static_cast<Value *>($1); }
;
boolean_value: TRUE { $$ = new BooleanValue(@$, true); }
| FALSE { $$ = new BooleanValue(@$, false); }
;
null_value: NULL { $$ = new NullValue(@$); }
;
enum_value: DIRECTIVE { $$ = new EnumValue(@$, strdup($1)); }
| ENUM { $$ = new EnumValue(@$, strdup($1)); }
| EXTEND { $$ = new EnumValue(@$, strdup($1)); }
| FRAGMENT { $$ = new EnumValue(@$, strdup($1)); }
| IDENTIFIER { $$ = new EnumValue(@$, strdup($1)); }
| IMPLEMENTS { $$ = new EnumValue(@$, strdup($1)); }
| INPUT { $$ = new EnumValue(@$, strdup($1)); }
| INTERFACE { $$ = new EnumValue(@$, strdup($1)); }
| MUTATION { $$ = new EnumValue(@$, strdup($1)); }
| ON { $$ = new EnumValue(@$, strdup($1)); }
| QUERY { $$ = new EnumValue(@$, strdup($1)); }
| SCALAR { $$ = new EnumValue(@$, strdup($1)); }
| SCHEMA { $$ = new EnumValue(@$, strdup($1)); }
| SUBSCRIPTION { $$ = new EnumValue(@$, strdup($1)); }
| TYPE { $$ = new EnumValue(@$, strdup($1)); }
| UNION { $$ = new EnumValue(@$, strdup($1)); }
;
/* 2.2.7.6 List Value */
/* REVIEW: the empty case is inefficient; consider implementing
ListValue manually. Don't forget to also do list_value_const. */
list_value: "[" "]" { $$ = new ListValue(@$, new std::vector<std::unique_ptr<Value>>()); }
| "[" value_list "]" { $$ = new ListValue(@$, $2); }
;
value_list: value { $$ = new std::vector<std::unique_ptr<Value>>(); $$->emplace_back($1); }
| value_list value { $1->emplace_back($2); $$ = $1; }
;
list_value_const:
"[" "]" { $$ = new ListValue(@$, new std::vector<std::unique_ptr<Value>>()); }
| "[" value_const_list "]" { $$ = new ListValue(@$, $2); }
;
value_const_list:
value_const { $$ = new std::vector<std::unique_ptr<Value>>(); $$->emplace_back($1); }
| value_const_list value_const { $1->emplace_back($2); $$ = $1; }
;
/* 2.2.7.7 Object Value */
/* REVIEW: Inefficient, like ListValue. */
object_value: "{" "}" { $$ = new ObjectValue(@$, new std::vector<std::unique_ptr<ObjectField>>()); }
| "{" object_field_list "}" { $$ = new ObjectValue(@$, $2); }
;
object_field_list:
object_field { $$ = new std::vector<std::unique_ptr<ObjectField>>(); $$->emplace_back($1); }
| object_field_list object_field { $1->emplace_back($2); $$ = $1; }
;
object_field: name ":" value { $$ = new ObjectField(@$, $1, $3); }
;
object_value_const:
"{" "}" { $$ = new ObjectValue(@$, new std::vector<std::unique_ptr<ObjectField>>()); }
| "{" object_field_const_list "}" { $$ = new ObjectValue(@$, $2); }
;
object_field_const_list:
object_field_const { $$ = new std::vector<std::unique_ptr<ObjectField>>(); $$->emplace_back($1); }
| object_field_const_list object_field_const { $1->emplace_back($2); $$ = $1; }
;
object_field_const: name ":" value_const { $$ = new ObjectField(@$, $1, $3); }
;
/* 2.2.10 Directives */
directives: directive_list
;
directives_opt: %empty { $$ = nullptr; }
| directives
;
directive_list: directive { $$ = new std::vector<std::unique_ptr<Directive>>(); $$->emplace_back($1); }
| directive_list directive { $1->emplace_back($2); $$ = $1; }
;
directive: "@" name arguments_opt { $$ = new Directive(@$, $2, $3); }
;
/* 2.2.9 Types */
type: type_name { $$ = static_cast<Type *>($1); }
| list_type { $$ = static_cast<Type *>($1); }
| non_null_type { $$ = static_cast<Type *>($1); }
;
type_name: name { $$ = new NamedType(@$, $1); }
;
list_type: "[" type "]" { $$ = new ListType(@$, $2); }
;
non_null_type: type_name "!" { $$ = new NonNullType(@$, $1); }
| list_type "!" { $$ = new NonNullType(@$, $1); }
;
/* Experimental schema parsing support. */
schema_definition: SCHEMA directives_opt "{" operation_type_definition_list "}" { $$ = new SchemaDefinition(@$, $2, $4); }
;
operation_type_definition_list:
operation_type_definition { $$ = new std::vector<std::unique_ptr<OperationTypeDefinition>>(); $$->emplace_back($1); }
| operation_type_definition_list operation_type_definition { $1->emplace_back($2); $$ = $1; }
;
operation_type_definition:
operation_type ":" type_name { $$ = new OperationTypeDefinition(@$, $1, $3); }
;
scalar_type_definition: SCALAR name directives_opt { $$ = new ScalarTypeDefinition(@$, $2, $3); }
;
object_type_definition: TYPE name implements_interfaces_opt directives_opt "{" field_definition_list "}" { $$ = new ObjectTypeDefinition(@$, $2, $3, $4, $6); }
;
implements_interfaces_opt: %empty { $$ = nullptr; }
| IMPLEMENTS type_name_list { $$ = $2; }
;
type_name_list: type_name { $$ = new std::vector<std::unique_ptr<NamedType>>(); $$->emplace_back($1); }
| type_name_list type_name { $1->emplace_back($2); $$ = $1; }
;
field_definition: name arguments_definition_opt ":" type directives_opt { $$ = new FieldDefinition(@$, $1, $2, $4, $5); }
;
field_definition_list:
field_definition { $$ = new std::vector<std::unique_ptr<FieldDefinition>>(); $$->emplace_back($1); }
| field_definition_list field_definition { $1->emplace_back($2); $$ = $1; }
;
arguments_definition_opt: %empty { $$ = nullptr; }
| arguments_definition { $$ = $1; }
;
arguments_definition: "(" input_value_definition_list ")" { $$ = $2; }
;
input_value_definition_list: input_value_definition { $$ = new std::vector<std::unique_ptr<InputValueDefinition>>(); $$->emplace_back($1); }
| input_value_definition_list input_value_definition { $1->emplace_back($2); $$ = $1; }
;
input_value_definition: name ":" type default_value_opt directives_opt { $$ = new InputValueDefinition(@$, $1, $3, $4, $5); }
interface_type_definition: INTERFACE name directives_opt "{" field_definition_list "}" { $$ = new InterfaceTypeDefinition(@$, $2, $3, $5); }
;
union_type_definition: UNION name directives_opt "=" union_members { $$ = new UnionTypeDefinition(@$, $2, $3, $5); }
;
union_members: type_name { $$ = new std::vector<std::unique_ptr<NamedType>>(); $$->emplace_back($1); }
| union_members "|" type_name { $1->emplace_back($3); $$ = $1; }
;
enum_type_definition: ENUM name directives_opt "{" enum_value_definition_list "}" { $$ = new EnumTypeDefinition(@$, $2, $3, $5); }
;
enum_value_definition: name directives_opt { $$ = new EnumValueDefinition(@$, $1, $2); }
;
enum_value_definition_list:
enum_value_definition { $$ = new std::vector<std::unique_ptr<EnumValueDefinition>>(); $$->emplace_back($1); }
| enum_value_definition_list enum_value_definition { $1->emplace_back($2); $$ = $1; }
;
input_object_type_definition: INPUT name directives_opt "{" input_value_definition_list "}" { $$ = new InputObjectTypeDefinition(@$, $2, $3, $5); }
;
type_extension_definition: EXTEND object_type_definition { $$ = new TypeExtensionDefinition(@$, $2); }
;
directive_definition: DIRECTIVE "@" name arguments_definition_opt ON directive_locations { $$ = new DirectiveDefinition(@$, $3, $4, $6); }
;
directive_locations:
name { $$ = new std::vector<std::unique_ptr<Name>>(); $$->emplace_back($1); }
| directive_locations "|" name { $1->emplace_back($3); $$ = $1; }
;
%%
void yy::GraphQLParserImpl::error(const yy::location &loc, const std::string &str) {
std::ostringstream out;
out << loc << ": " << str;
if (outError) {
*outError = strdup(out.str().c_str());
}
}
/* Workaround for syntax_error ctor being marked inline, which causes link
errors if used from lexer.lpp. */
yy::GraphQLParserImpl::syntax_error make_error(const yy::location &loc, const std::string &str) {
return yy::GraphQLParserImpl::syntax_error(loc, str);
}

2633
external/graphqlparser/parsergen/lexer.cpp vendored Normal file

File diff suppressed because it is too large Load Diff

528
external/graphqlparser/parsergen/lexer.h vendored Normal file
View File

@@ -0,0 +1,528 @@
#ifndef yyHEADER_H
#define yyHEADER_H 1
#define yyIN_HEADER 1
#line 5 "lexer.h"
#line 7 "lexer.h"
#define YY_INT_ALIGNED short int
/* A lexical scanner generated by flex */
#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 6
#define YY_FLEX_SUBMINOR_VERSION 4
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif
#ifdef yyget_lval
#define yyget_lval_ALREADY_DEFINED
#else
#define yyget_lval yyget_lval
#endif
#ifdef yyset_lval
#define yyset_lval_ALREADY_DEFINED
#else
#define yyset_lval yyset_lval
#endif
#ifdef yyget_lloc
#define yyget_lloc_ALREADY_DEFINED
#else
#define yyget_lloc yyget_lloc
#endif
#ifdef yyset_lloc
#define yyset_lloc_ALREADY_DEFINED
#else
#define yyset_lloc yyset_lloc
#endif
/* First, we deal with platform-specific or compiler-specific issues. */
/* begin standard C headers. */
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
/* end standard C headers. */
/* flex integer type definitions */
#ifndef FLEXINT_H
#define FLEXINT_H
/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
* if you want the limit (max/min) macros for int types.
*/
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS 1
#endif
#include <inttypes.h>
typedef int8_t flex_int8_t;
typedef uint8_t flex_uint8_t;
typedef int16_t flex_int16_t;
typedef uint16_t flex_uint16_t;
typedef int32_t flex_int32_t;
typedef uint32_t flex_uint32_t;
#else
typedef signed char flex_int8_t;
typedef short int flex_int16_t;
typedef int flex_int32_t;
typedef unsigned char flex_uint8_t;
typedef unsigned short int flex_uint16_t;
typedef unsigned int flex_uint32_t;
/* Limits of integral types. */
#ifndef INT8_MIN
#define INT8_MIN (-128)
#endif
#ifndef INT16_MIN
#define INT16_MIN (-32767-1)
#endif
#ifndef INT32_MIN
#define INT32_MIN (-2147483647-1)
#endif
#ifndef INT8_MAX
#define INT8_MAX (127)
#endif
#ifndef INT16_MAX
#define INT16_MAX (32767)
#endif
#ifndef INT32_MAX
#define INT32_MAX (2147483647)
#endif
#ifndef UINT8_MAX
#define UINT8_MAX (255U)
#endif
#ifndef UINT16_MAX
#define UINT16_MAX (65535U)
#endif
#ifndef UINT32_MAX
#define UINT32_MAX (4294967295U)
#endif
#ifndef SIZE_MAX
#define SIZE_MAX (~(size_t)0)
#endif
#endif /* ! C99 */
#endif /* ! FLEXINT_H */
/* begin standard C++ headers. */
/* TODO: this is always defined, so inline it */
#define yyconst const
#if defined(__GNUC__) && __GNUC__ >= 3
#define yynoreturn __attribute__((__noreturn__))
#else
#define yynoreturn
#endif
/* An opaque pointer. */
#ifndef YY_TYPEDEF_YY_SCANNER_T
#define YY_TYPEDEF_YY_SCANNER_T
typedef void* yyscan_t;
#endif
/* For convenience, these vars (plus the bison vars far below)
are macros in the reentrant scanner. */
#define yyin yyg->yyin_r
#define yyout yyg->yyout_r
#define yyextra yyg->yyextra_r
#define yyleng yyg->yyleng_r
#define yytext yyg->yytext_r
#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
#define yy_flex_debug yyg->yy_flex_debug_r
/* Size of default input buffer. */
#ifndef YY_BUF_SIZE
#ifdef __ia64__
/* On IA-64, the buffer size is 16k, not 8k.
* Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
* Ditto for the __ia64__ case accordingly.
*/
#define YY_BUF_SIZE 32768
#else
#define YY_BUF_SIZE 16384
#endif /* __ia64__ */
#endif
#ifndef YY_TYPEDEF_YY_BUFFER_STATE
#define YY_TYPEDEF_YY_BUFFER_STATE
typedef struct yy_buffer_state *YY_BUFFER_STATE;
#endif
#ifndef YY_TYPEDEF_YY_SIZE_T
#define YY_TYPEDEF_YY_SIZE_T
typedef size_t yy_size_t;
#endif
#ifndef YY_STRUCT_YY_BUFFER_STATE
#define YY_STRUCT_YY_BUFFER_STATE
struct yy_buffer_state
{
FILE *yy_input_file;
char *yy_ch_buf; /* input buffer */
char *yy_buf_pos; /* current position in input buffer */
/* Size of input buffer in bytes, not including room for EOB
* characters.
*/
int yy_buf_size;
/* Number of characters read into yy_ch_buf, not including EOB
* characters.
*/
int yy_n_chars;
/* Whether we "own" the buffer - i.e., we know we created it,
* and can realloc() it to grow it, and should free() it to
* delete it.
*/
int yy_is_our_buffer;
/* Whether this is an "interactive" input source; if so, and
* if we're using stdio for input, then we want to use getc()
* instead of fread(), to make sure we stop fetching input after
* each newline.
*/
int yy_is_interactive;
/* Whether we're considered to be at the beginning of a line.
* If so, '^' rules will be active on the next match, otherwise
* not.
*/
int yy_at_bol;
int yy_bs_lineno; /**< The line count. */
int yy_bs_column; /**< The column count. */
/* Whether to try to fill the input buffer when we reach the
* end of it.
*/
int yy_fill_buffer;
int yy_buffer_status;
};
#endif /* !YY_STRUCT_YY_BUFFER_STATE */
void yyrestart ( FILE *input_file , yyscan_t yyscanner );
void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size , yyscan_t yyscanner );
void yy_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
void yy_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
void yypush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
void yypop_buffer_state ( yyscan_t yyscanner );
YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner );
YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner );
YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner );
void *yyalloc ( yy_size_t , yyscan_t yyscanner );
void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner );
void yyfree ( void * , yyscan_t yyscanner );
/* Begin user sect3 */
#define yywrap(yyscanner) (/*CONSTCOND*/1)
#define YY_SKIP_YYWRAP
#define yytext_ptr yytext_r
#ifdef YY_HEADER_EXPORT_START_CONDITIONS
#define INITIAL 0
#define STRING_STATE 1
#define BLOCK_STRING_STATE 2
#define C_COMMENT_STATE 3
#define LINE_COMMENT_STATE 4
#endif
#ifndef YY_NO_UNISTD_H
/* Special case for "unistd.h", since it is non-ANSI. We include it way
* down here because we want the user's section 1 to have been scanned first.
* The user has a chance to override it with an option.
*/
#include <unistd.h>
#endif
#define YY_EXTRA_TYPE struct LexerExtra *
int yylex_init (yyscan_t* scanner);
int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner);
/* Accessor methods to globals.
These are made visible to non-reentrant scanners for convenience. */
int yylex_destroy ( yyscan_t yyscanner );
int yyget_debug ( yyscan_t yyscanner );
void yyset_debug ( int debug_flag , yyscan_t yyscanner );
YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner );
void yyset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner );
FILE *yyget_in ( yyscan_t yyscanner );
void yyset_in ( FILE * _in_str , yyscan_t yyscanner );
FILE *yyget_out ( yyscan_t yyscanner );
void yyset_out ( FILE * _out_str , yyscan_t yyscanner );
int yyget_leng ( yyscan_t yyscanner );
char *yyget_text ( yyscan_t yyscanner );
int yyget_lineno ( yyscan_t yyscanner );
void yyset_lineno ( int _line_number , yyscan_t yyscanner );
int yyget_column ( yyscan_t yyscanner );
void yyset_column ( int _column_no , yyscan_t yyscanner );
YYSTYPE * yyget_lval ( yyscan_t yyscanner );
void yyset_lval ( YYSTYPE * yylval_param , yyscan_t yyscanner );
YYLTYPE *yyget_lloc ( yyscan_t yyscanner );
void yyset_lloc ( YYLTYPE * yylloc_param , yyscan_t yyscanner );
/* Macros after this point can all be overridden by user definitions in
* section 1.
*/
#ifndef YY_SKIP_YYWRAP
#ifdef __cplusplus
extern "C" int yywrap ( yyscan_t yyscanner );
#else
extern int yywrap ( yyscan_t yyscanner );
#endif
#endif
#ifndef yytext_ptr
static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner);
#endif
#ifdef YY_NEED_STRLEN
static int yy_flex_strlen ( const char * , yyscan_t yyscanner);
#endif
#ifndef YY_NO_INPUT
#endif
/* Amount of stuff to slurp up with each read. */
#ifndef YY_READ_BUF_SIZE
#ifdef __ia64__
/* On IA-64, the buffer size is 16k, not 8k */
#define YY_READ_BUF_SIZE 16384
#else
#define YY_READ_BUF_SIZE 8192
#endif /* __ia64__ */
#endif
/* Number of entries by which start-condition stack grows. */
#ifndef YY_START_STACK_INCR
#define YY_START_STACK_INCR 25
#endif
/* Default declaration of generated scanner - a define so the user can
* easily add parameters.
*/
#ifndef YY_DECL
#define YY_DECL_IS_OURS 1
extern int yylex \
(YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner);
#define YY_DECL int yylex \
(YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner)
#endif /* !YY_DECL */
/* yy_get_previous_state - get the state just before the EOB char was reached */
#undef YY_NEW_FILE
#undef YY_FLUSH_BUFFER
#undef yy_set_bol
#undef yy_new_buffer
#undef yy_set_interactive
#undef YY_DO_BEFORE_ACTION
#ifdef YY_DECL_IS_OURS
#undef YY_DECL_IS_OURS
#undef YY_DECL
#endif
#ifndef yy_create_buffer_ALREADY_DEFINED
#undef yy_create_buffer
#endif
#ifndef yy_delete_buffer_ALREADY_DEFINED
#undef yy_delete_buffer
#endif
#ifndef yy_scan_buffer_ALREADY_DEFINED
#undef yy_scan_buffer
#endif
#ifndef yy_scan_string_ALREADY_DEFINED
#undef yy_scan_string
#endif
#ifndef yy_scan_bytes_ALREADY_DEFINED
#undef yy_scan_bytes
#endif
#ifndef yy_init_buffer_ALREADY_DEFINED
#undef yy_init_buffer
#endif
#ifndef yy_flush_buffer_ALREADY_DEFINED
#undef yy_flush_buffer
#endif
#ifndef yy_load_buffer_state_ALREADY_DEFINED
#undef yy_load_buffer_state
#endif
#ifndef yy_switch_to_buffer_ALREADY_DEFINED
#undef yy_switch_to_buffer
#endif
#ifndef yypush_buffer_state_ALREADY_DEFINED
#undef yypush_buffer_state
#endif
#ifndef yypop_buffer_state_ALREADY_DEFINED
#undef yypop_buffer_state
#endif
#ifndef yyensure_buffer_stack_ALREADY_DEFINED
#undef yyensure_buffer_stack
#endif
#ifndef yylex_ALREADY_DEFINED
#undef yylex
#endif
#ifndef yyrestart_ALREADY_DEFINED
#undef yyrestart
#endif
#ifndef yylex_init_ALREADY_DEFINED
#undef yylex_init
#endif
#ifndef yylex_init_extra_ALREADY_DEFINED
#undef yylex_init_extra
#endif
#ifndef yylex_destroy_ALREADY_DEFINED
#undef yylex_destroy
#endif
#ifndef yyget_debug_ALREADY_DEFINED
#undef yyget_debug
#endif
#ifndef yyset_debug_ALREADY_DEFINED
#undef yyset_debug
#endif
#ifndef yyget_extra_ALREADY_DEFINED
#undef yyget_extra
#endif
#ifndef yyset_extra_ALREADY_DEFINED
#undef yyset_extra
#endif
#ifndef yyget_in_ALREADY_DEFINED
#undef yyget_in
#endif
#ifndef yyset_in_ALREADY_DEFINED
#undef yyset_in
#endif
#ifndef yyget_out_ALREADY_DEFINED
#undef yyget_out
#endif
#ifndef yyset_out_ALREADY_DEFINED
#undef yyset_out
#endif
#ifndef yyget_leng_ALREADY_DEFINED
#undef yyget_leng
#endif
#ifndef yyget_text_ALREADY_DEFINED
#undef yyget_text
#endif
#ifndef yyget_lineno_ALREADY_DEFINED
#undef yyget_lineno
#endif
#ifndef yyset_lineno_ALREADY_DEFINED
#undef yyset_lineno
#endif
#ifndef yyget_column_ALREADY_DEFINED
#undef yyget_column
#endif
#ifndef yyset_column_ALREADY_DEFINED
#undef yyset_column
#endif
#ifndef yywrap_ALREADY_DEFINED
#undef yywrap
#endif
#ifndef yyget_lval_ALREADY_DEFINED
#undef yyget_lval
#endif
#ifndef yyset_lval_ALREADY_DEFINED
#undef yyset_lval
#endif
#ifndef yyget_lloc_ALREADY_DEFINED
#undef yyget_lloc
#endif
#ifndef yyset_lloc_ALREADY_DEFINED
#undef yyset_lloc
#endif
#ifndef yyalloc_ALREADY_DEFINED
#undef yyalloc
#endif
#ifndef yyrealloc_ALREADY_DEFINED
#undef yyrealloc
#endif
#ifndef yyfree_ALREADY_DEFINED
#undef yyfree
#endif
#ifndef yytext_ALREADY_DEFINED
#undef yytext
#endif
#ifndef yyleng_ALREADY_DEFINED
#undef yyleng
#endif
#ifndef yyin_ALREADY_DEFINED
#undef yyin
#endif
#ifndef yyout_ALREADY_DEFINED
#undef yyout
#endif
#ifndef yy_flex_debug_ALREADY_DEFINED
#undef yy_flex_debug
#endif
#ifndef yylineno_ALREADY_DEFINED
#undef yylineno
#endif
#ifndef yytables_fload_ALREADY_DEFINED
#undef yytables_fload
#endif
#ifndef yytables_destroy_ALREADY_DEFINED
#undef yytables_destroy
#endif
#ifndef yyTABLES_NAME_ALREADY_DEFINED
#undef yyTABLES_NAME
#endif
#line 205 "lexer.lpp"
#line 526 "lexer.h"
#undef yyIN_HEADER
#endif /* yyHEADER_H */

View File

@@ -0,0 +1,189 @@
// A Bison parser, made by GNU Bison 3.0.5.
// Locations for Bison parsers in C++
// Copyright (C) 2002-2015, 2018 Free Software Foundation, Inc.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// As a special exception, you may create a larger work that contains
// part or all of the Bison parser skeleton and distribute that work
// under terms of your choice, so long as that work isn't itself a
// parser generator using the skeleton or a modified version thereof
// as a parser skeleton. Alternatively, if you modify or redistribute
// the parser skeleton itself, you may (at your option) remove this
// special exception, which will cause the skeleton and the resulting
// Bison output files to be licensed under the GNU General Public
// License without this special exception.
// This special exception was added by the Free Software Foundation in
// version 2.2 of Bison.
/**
** \file location.hh
** Define the yy::location class.
*/
#ifndef YY_YY_LOCATION_HH_INCLUDED
# define YY_YY_LOCATION_HH_INCLUDED
# include "position.hh"
namespace yy {
#line 46 "location.hh" // location.cc:333
/// Abstract a location.
class location
{
public:
/// Construct a location from \a b to \a e.
location (const position& b, const position& e)
: begin (b)
, end (e)
{}
/// Construct a 0-width location in \a p.
explicit location (const position& p = position ())
: begin (p)
, end (p)
{}
/// Construct a 0-width location in \a f, \a l, \a c.
explicit location (std::string* f,
unsigned l = 1u,
unsigned c = 1u)
: begin (f, l, c)
, end (f, l, c)
{}
/// Initialization.
void initialize (std::string* f = YY_NULLPTR,
unsigned l = 1u,
unsigned c = 1u)
{
begin.initialize (f, l, c);
end = begin;
}
/** \name Line and Column related manipulators
** \{ */
public:
/// Reset initial location to final location.
void step ()
{
begin = end;
}
/// Extend the current location to the COUNT next columns.
void columns (int count = 1)
{
end += count;
}
/// Extend the current location to the COUNT next lines.
void lines (int count = 1)
{
end.lines (count);
}
/** \} */
public:
/// Beginning of the located region.
position begin;
/// End of the located region.
position end;
};
/// Join two locations, in place.
inline location& operator+= (location& res, const location& end)
{
res.end = end.end;
return res;
}
/// Join two locations.
inline location operator+ (location res, const location& end)
{
return res += end;
}
/// Add \a width columns to the end position, in place.
inline location& operator+= (location& res, int width)
{
res.columns (width);
return res;
}
/// Add \a width columns to the end position.
inline location operator+ (location res, int width)
{
return res += width;
}
/// Subtract \a width columns to the end position, in place.
inline location& operator-= (location& res, int width)
{
return res += -width;
}
/// Subtract \a width columns to the end position.
inline location operator- (location res, int width)
{
return res -= width;
}
/// Compare two location objects.
inline bool
operator== (const location& loc1, const location& loc2)
{
return loc1.begin == loc2.begin && loc1.end == loc2.end;
}
/// Compare two location objects.
inline bool
operator!= (const location& loc1, const location& loc2)
{
return !(loc1 == loc2);
}
/** \brief Intercept output stream redirection.
** \param ostr the destination output stream
** \param loc a reference to the location to redirect
**
** Avoid duplicate information.
*/
template <typename YYChar>
inline std::basic_ostream<YYChar>&
operator<< (std::basic_ostream<YYChar>& ostr, const location& loc)
{
unsigned end_col = 0 < loc.end.column ? loc.end.column - 1 : 0;
ostr << loc.begin;
if (loc.end.filename
&& (!loc.begin.filename
|| *loc.begin.filename != *loc.end.filename))
ostr << '-' << loc.end.filename << ':' << loc.end.line << '.' << end_col;
else if (loc.begin.line < loc.end.line)
ostr << '-' << loc.end.line << '.' << end_col;
else if (loc.begin.column < end_col)
ostr << '-' << end_col;
return ostr;
}
} // yy
#line 189 "location.hh" // location.cc:333
#endif // !YY_YY_LOCATION_HH_INCLUDED

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,646 @@
// A Bison parser, made by GNU Bison 3.0.5.
// Skeleton interface for Bison LALR(1) parsers in C++
// Copyright (C) 2002-2015, 2018 Free Software Foundation, Inc.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// As a special exception, you may create a larger work that contains
// part or all of the Bison parser skeleton and distribute that work
// under terms of your choice, so long as that work isn't itself a
// parser generator using the skeleton or a modified version thereof
// as a parser skeleton. Alternatively, if you modify or redistribute
// the parser skeleton itself, you may (at your option) remove this
// special exception, which will cause the skeleton and the resulting
// Bison output files to be licensed under the GNU General Public
// License without this special exception.
// This special exception was added by the Free Software Foundation in
// version 2.2 of Bison.
/**
** \file parser.tab.hpp
** Define the yy::parser class.
*/
// C++ LALR(1) parser skeleton written by Akim Demaille.
#ifndef YY_YY_PARSER_TAB_HPP_INCLUDED
# define YY_YY_PARSER_TAB_HPP_INCLUDED
// // "%code requires" blocks.
#line 20 "parser.ypp" // lalr1.cc:394
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <sstream>
#include <string>
#include "Ast.h"
using facebook::graphql::ast::Node;
using facebook::graphql::ast::Name;
using facebook::graphql::ast::Definition;
using facebook::graphql::ast::Document;
using facebook::graphql::ast::OperationDefinition;
using facebook::graphql::ast::VariableDefinition;
using facebook::graphql::ast::Variable;
using facebook::graphql::ast::SelectionSet;
using facebook::graphql::ast::Selection;
using facebook::graphql::ast::Field;
using facebook::graphql::ast::Argument;
using facebook::graphql::ast::FragmentSpread;
using facebook::graphql::ast::InlineFragment;
using facebook::graphql::ast::FragmentDefinition;
using facebook::graphql::ast::Value;
using facebook::graphql::ast::IntValue;
using facebook::graphql::ast::FloatValue;
using facebook::graphql::ast::StringValue;
using facebook::graphql::ast::BooleanValue;
using facebook::graphql::ast::NullValue;
using facebook::graphql::ast::EnumValue;
using facebook::graphql::ast::ListValue;
using facebook::graphql::ast::ObjectValue;
using facebook::graphql::ast::ObjectField;
using facebook::graphql::ast::Directive;
using facebook::graphql::ast::Type;
using facebook::graphql::ast::NamedType;
using facebook::graphql::ast::ListType;
using facebook::graphql::ast::NonNullType;
// Experimental schema support.
using facebook::graphql::ast::SchemaDefinition;
using facebook::graphql::ast::ScalarTypeDefinition;
using facebook::graphql::ast::ObjectTypeDefinition;
using facebook::graphql::ast::InterfaceTypeDefinition;
using facebook::graphql::ast::UnionTypeDefinition;
using facebook::graphql::ast::EnumTypeDefinition;
using facebook::graphql::ast::InputObjectTypeDefinition;
using facebook::graphql::ast::TypeExtensionDefinition;
using facebook::graphql::ast::DirectiveDefinition;
using facebook::graphql::ast::SchemaDefinition;
using facebook::graphql::ast::OperationTypeDefinition;
using facebook::graphql::ast::ScalarTypeDefinition;
using facebook::graphql::ast::ObjectTypeDefinition;
using facebook::graphql::ast::FieldDefinition;
using facebook::graphql::ast::InputValueDefinition;
using facebook::graphql::ast::InterfaceTypeDefinition;
using facebook::graphql::ast::UnionTypeDefinition;
using facebook::graphql::ast::EnumTypeDefinition;
using facebook::graphql::ast::EnumValueDefinition;
using facebook::graphql::ast::InputObjectTypeDefinition;
using facebook::graphql::ast::TypeExtensionDefinition;
using facebook::graphql::ast::DirectiveDefinition;
union yystype { \
const char *str; \
const char *heapStr; \
Name *name; \
Definition *definition; \
Document *document; \
OperationDefinition *operationDefinition; \
VariableDefinition *variableDefinition; \
Variable *variable; \
SelectionSet *selectionSet; \
Selection *selection; \
Field *field; \
Argument *argument; \
FragmentSpread *fragmentSpread; \
InlineFragment *inlineFragment; \
FragmentDefinition *fragmentDefinition; \
Value *value; \
IntValue *intValue; \
FloatValue *floatValue; \
StringValue *stringValue; \
BooleanValue *booleanValue; \
NullValue *nullValue; \
EnumValue *enumValue; \
ListValue *arrayValue; \
ObjectValue *objectValue; \
ObjectField *objectField; \
Directive *directive; \
Type *type; \
NamedType *namedType; \
ListType *listType; \
NonNullType *nonNullType; \
\
std::vector<std::unique_ptr<Definition>> *definitionList; \
std::vector<std::unique_ptr<VariableDefinition>> *variableDefinitionList; \
std::vector<std::unique_ptr<Selection>> *selectionList; \
std::vector<std::unique_ptr<Field>> *fieldList; \
std::vector<std::unique_ptr<Argument>> *argumentList; \
std::vector<std::unique_ptr<Value>> *valueList; \
std::vector<std::unique_ptr<ObjectField>> *objectFieldList; \
std::vector<std::unique_ptr<Directive>> *directiveList; \
\
SchemaDefinition *schemaDefinition; \
ScalarTypeDefinition *scalarTypeDefinition; \
ObjectTypeDefinition *objectTypeDefinition; \
InterfaceTypeDefinition *interfaceTypeDefinition; \
UnionTypeDefinition *unionTypeDefinition; \
EnumTypeDefinition *enumTypeDefinition; \
InputObjectTypeDefinition *inputObjectTypeDefinition; \
TypeExtensionDefinition *typeExtensionDefinition; \
DirectiveDefinition *directiveDefinition; \
OperationTypeDefinition *operationTypeDefinition; \
InputValueDefinition *inputValueDefinition; \
FieldDefinition *fieldDefinition; \
EnumValueDefinition *enumValueDefinition; \
\
std::vector<std::unique_ptr<OperationTypeDefinition>> *operationTypeDefinitionList; \
std::vector<std::unique_ptr<NamedType>> *typeNameList; \
std::vector<std::unique_ptr<InputValueDefinition>> *inputValueDefinitionList; \
std::vector<std::unique_ptr<FieldDefinition>> *fieldDefinitionList; \
std::vector<std::unique_ptr<Name>> *nameList; \
std::vector<std::unique_ptr<EnumValueDefinition>> *enumValueDefinitionList; \
};
#define YYSTYPE union yystype
#define YYLTYPE yy::location
#line 175 "parser.tab.hpp" // lalr1.cc:394
# include <cstdlib> // std::abort
# include <iostream>
# include <stdexcept>
# include <string>
# include <vector>
# include "stack.hh"
# include "location.hh"
#ifndef YY_ATTRIBUTE
# if (defined __GNUC__ \
&& (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \
|| defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
# define YY_ATTRIBUTE(Spec) __attribute__(Spec)
# else
# define YY_ATTRIBUTE(Spec) /* empty */
# endif
#endif
#ifndef YY_ATTRIBUTE_PURE
# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__))
#endif
#ifndef YY_ATTRIBUTE_UNUSED
# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
#endif
#if !defined _Noreturn \
&& (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
# if defined _MSC_VER && 1200 <= _MSC_VER
# define _Noreturn __declspec (noreturn)
# else
# define _Noreturn YY_ATTRIBUTE ((__noreturn__))
# endif
#endif
/* Suppress unused-variable warnings by "using" E. */
#if ! defined lint || defined __GNUC__
# define YYUSE(E) ((void) (E))
#else
# define YYUSE(E) /* empty */
#endif
#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
/* Suppress an incorrect diagnostic about yylval being uninitialized. */
# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
_Pragma ("GCC diagnostic push") \
_Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
_Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
_Pragma ("GCC diagnostic pop")
#else
# define YY_INITIAL_VALUE(Value) Value
#endif
#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
# define YY_IGNORE_MAYBE_UNINITIALIZED_END
#endif
#ifndef YY_INITIAL_VALUE
# define YY_INITIAL_VALUE(Value) /* Nothing. */
#endif
/* Debug traces. */
#ifndef YYDEBUG
# define YYDEBUG 0
#endif
namespace yy {
#line 247 "parser.tab.hpp" // lalr1.cc:394
/// A Bison parser.
class GraphQLParserImpl
{
public:
#ifndef YYSTYPE
/// Symbol semantic values.
#else
typedef YYSTYPE semantic_type;
#endif
/// Symbol locations.
typedef location location_type;
/// Syntax errors thrown from user actions.
struct syntax_error : std::runtime_error
{
syntax_error (const location_type& l, const std::string& m);
location_type location;
};
/// Tokens.
struct token
{
enum yytokentype
{
TOK_EOF = 0,
TOK_DIRECTIVE = 258,
TOK_ENUM = 259,
TOK_EXTEND = 260,
TOK_FALSE = 261,
TOK_FRAGMENT = 262,
TOK_IMPLEMENTS = 263,
TOK_INPUT = 264,
TOK_INTERFACE = 265,
TOK_MUTATION = 266,
TOK_NULL = 267,
TOK_QUERY = 268,
TOK_ON = 269,
TOK_SCALAR = 270,
TOK_SCHEMA = 271,
TOK_SUBSCRIPTION = 272,
TOK_TRUE = 273,
TOK_TYPE = 274,
TOK_UNION = 275,
TOK_BANG = 276,
TOK_LPAREN = 277,
TOK_RPAREN = 278,
TOK_ELLIPSIS = 279,
TOK_COLON = 280,
TOK_EQUAL = 281,
TOK_AT = 282,
TOK_LBRACKET = 283,
TOK_RBRACKET = 284,
TOK_LBRACE = 285,
TOK_PIPE = 286,
TOK_RBRACE = 287,
TOK_VARIABLE = 288,
TOK_INTEGER = 289,
TOK_FLOAT = 290,
TOK_STRING = 291,
TOK_IDENTIFIER = 292
};
};
/// (External) token type, as returned by yylex.
typedef token::yytokentype token_type;
/// Symbol type: an internal symbol number.
typedef int symbol_number_type;
/// The symbol type number to denote an empty symbol.
enum { empty_symbol = -2 };
/// Internal symbol number for tokens (subsumed by symbol_number_type).
typedef unsigned char token_number_type;
/// A complete symbol.
///
/// Expects its Base type to provide access to the symbol type
/// via type_get().
///
/// Provide access to semantic value and location.
template <typename Base>
struct basic_symbol : Base
{
/// Alias to Base.
typedef Base super_type;
/// Default constructor.
basic_symbol ();
/// Copy constructor.
basic_symbol (const basic_symbol& other);
/// Constructor for valueless symbols.
basic_symbol (typename Base::kind_type t,
const location_type& l);
/// Constructor for symbols with semantic value.
basic_symbol (typename Base::kind_type t,
const semantic_type& v,
const location_type& l);
/// Destroy the symbol.
~basic_symbol ();
/// Destroy contents, and record that is empty.
void clear ();
/// Whether empty.
bool empty () const;
/// Destructive move, \a s is emptied into this.
void move (basic_symbol& s);
/// The semantic value.
semantic_type value;
/// The location.
location_type location;
private:
/// Assignment operator.
basic_symbol& operator= (const basic_symbol& other);
};
/// Type access provider for token (enum) based symbols.
struct by_type
{
/// Default constructor.
by_type ();
/// Copy constructor.
by_type (const by_type& other);
/// The symbol type as needed by the constructor.
typedef token_type kind_type;
/// Constructor from (external) token numbers.
by_type (kind_type t);
/// Record that this symbol is empty.
void clear ();
/// Steal the symbol type from \a that.
void move (by_type& that);
/// The (internal) type number (corresponding to \a type).
/// \a empty when empty.
symbol_number_type type_get () const;
/// The token.
token_type token () const;
/// The symbol type.
/// \a empty_symbol when empty.
/// An int, not token_number_type, to be able to store empty_symbol.
int type;
};
/// "External" symbols: returned by the scanner.
typedef basic_symbol<by_type> symbol_type;
/// Build a parser object.
GraphQLParserImpl (bool enableSchema_yyarg, Node **outAST_yyarg, const char **outError_yyarg, void *scanner_yyarg);
virtual ~GraphQLParserImpl ();
/// Parse.
/// \returns 0 iff parsing succeeded.
virtual int parse ();
#if YYDEBUG
/// The current debugging stream.
std::ostream& debug_stream () const YY_ATTRIBUTE_PURE;
/// Set the current debugging stream.
void set_debug_stream (std::ostream &);
/// Type for debugging levels.
typedef int debug_level_type;
/// The current debugging level.
debug_level_type debug_level () const YY_ATTRIBUTE_PURE;
/// Set the current debugging level.
void set_debug_level (debug_level_type l);
#endif
/// Report a syntax error.
/// \param loc where the syntax error is found.
/// \param msg a description of the syntax error.
virtual void error (const location_type& loc, const std::string& msg);
/// Report a syntax error.
void error (const syntax_error& err);
private:
/// This class is not copyable.
GraphQLParserImpl (const GraphQLParserImpl&);
GraphQLParserImpl& operator= (const GraphQLParserImpl&);
/// State numbers.
typedef int state_type;
/// Generate an error message.
/// \param yystate the state where the error occurred.
/// \param yyla the lookahead token.
virtual std::string yysyntax_error_ (state_type yystate,
const symbol_type& yyla) const;
/// Compute post-reduction state.
/// \param yystate the current state
/// \param yysym the nonterminal to push on the stack
state_type yy_lr_goto_state_ (state_type yystate, int yysym);
/// Whether the given \c yypact_ value indicates a defaulted state.
/// \param yyvalue the value to check
static bool yy_pact_value_is_default_ (int yyvalue);
/// Whether the given \c yytable_ value indicates a syntax error.
/// \param yyvalue the value to check
static bool yy_table_value_is_error_ (int yyvalue);
static const short int yypact_ninf_;
static const signed char yytable_ninf_;
/// Convert a scanner token number \a t to a symbol number.
static token_number_type yytranslate_ (int t);
// Tables.
// YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
// STATE-NUM.
static const short int yypact_[];
// YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
// Performed when YYTABLE does not specify something else to do. Zero
// means the default is an error.
static const unsigned char yydefact_[];
// YYPGOTO[NTERM-NUM].
static const short int yypgoto_[];
// YYDEFGOTO[NTERM-NUM].
static const short int yydefgoto_[];
// YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
// positive, shift that token. If negative, reduce the rule whose
// number is the opposite. If YYTABLE_NINF, syntax error.
static const unsigned short int yytable_[];
static const short int yycheck_[];
// YYSTOS[STATE-NUM] -- The (internal number of the) accessing
// symbol of state STATE-NUM.
static const unsigned char yystos_[];
// YYR1[YYN] -- Symbol number of symbol that rule YYN derives.
static const unsigned char yyr1_[];
// YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.
static const unsigned char yyr2_[];
/// Convert the symbol name \a n to a form suitable for a diagnostic.
static std::string yytnamerr_ (const char *n);
/// For a symbol, its name in clear.
static const char* const yytname_[];
#if YYDEBUG
// YYRLINE[YYN] -- Source line where rule number YYN was defined.
static const unsigned short int yyrline_[];
/// Report on the debug stream that the rule \a r is going to be reduced.
virtual void yy_reduce_print_ (int r);
/// Print the state stack on the debug stream.
virtual void yystack_print_ ();
// Debugging.
int yydebug_;
std::ostream* yycdebug_;
/// \brief Display a symbol type, value and location.
/// \param yyo The output stream.
/// \param yysym The symbol.
template <typename Base>
void yy_print_ (std::ostream& yyo, const basic_symbol<Base>& yysym) const;
#endif
/// \brief Reclaim the memory associated to a symbol.
/// \param yymsg Why this token is reclaimed.
/// If null, print nothing.
/// \param yysym The symbol.
template <typename Base>
void yy_destroy_ (const char* yymsg, basic_symbol<Base>& yysym) const;
private:
/// Type access provider for state based symbols.
struct by_state
{
/// Default constructor.
by_state ();
/// The symbol type as needed by the constructor.
typedef state_type kind_type;
/// Constructor.
by_state (kind_type s);
/// Copy constructor.
by_state (const by_state& other);
/// Record that this symbol is empty.
void clear ();
/// Steal the symbol type from \a that.
void move (by_state& that);
/// The (internal) type number (corresponding to \a state).
/// \a empty_symbol when empty.
symbol_number_type type_get () const;
/// The state number used to denote an empty symbol.
enum { empty_state = -1 };
/// The state.
/// \a empty when empty.
state_type state;
};
/// "Internal" symbol: element of the stack.
struct stack_symbol_type : basic_symbol<by_state>
{
/// Superclass.
typedef basic_symbol<by_state> super_type;
/// Construct an empty symbol.
stack_symbol_type ();
/// Copy construct.
stack_symbol_type (const stack_symbol_type& that);
/// Steal the contents from \a sym to build this.
stack_symbol_type (state_type s, symbol_type& sym);
/// Assignment, needed by push_back.
stack_symbol_type& operator= (const stack_symbol_type& that);
};
/// Stack type.
typedef stack<stack_symbol_type> stack_type;
/// The stack.
stack_type yystack_;
/// Push a new state on the stack.
/// \param m a debug message to display
/// if null, no trace is output.
/// \param s the symbol
/// \warning the contents of \a s.value is stolen.
void yypush_ (const char* m, stack_symbol_type& s);
/// Push a new look ahead token on the state on the stack.
/// \param m a debug message to display
/// if null, no trace is output.
/// \param s the state
/// \param sym the symbol (for its value and location).
/// \warning the contents of \a s.value is stolen.
void yypush_ (const char* m, state_type s, symbol_type& sym);
/// Pop \a n symbols the three stacks.
void yypop_ (unsigned n = 1);
/// Constants.
enum
{
yyeof_ = 0,
yylast_ = 955, ///< Last index in yytable_.
yynnts_ = 79, ///< Number of nonterminal symbols.
yyfinal_ = 74, ///< Termination state number.
yyterror_ = 1,
yyerrcode_ = 256,
yyntokens_ = 38 ///< Number of tokens.
};
// User arguments.
bool enableSchema;
Node **outAST;
const char **outError;
void *scanner;
};
} // yy
#line 642 "parser.tab.hpp" // lalr1.cc:394
#endif // !YY_YY_PARSER_TAB_HPP_INCLUDED

View File

@@ -0,0 +1,179 @@
// A Bison parser, made by GNU Bison 3.0.5.
// Positions for Bison parsers in C++
// Copyright (C) 2002-2015, 2018 Free Software Foundation, Inc.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// As a special exception, you may create a larger work that contains
// part or all of the Bison parser skeleton and distribute that work
// under terms of your choice, so long as that work isn't itself a
// parser generator using the skeleton or a modified version thereof
// as a parser skeleton. Alternatively, if you modify or redistribute
// the parser skeleton itself, you may (at your option) remove this
// special exception, which will cause the skeleton and the resulting
// Bison output files to be licensed under the GNU General Public
// License without this special exception.
// This special exception was added by the Free Software Foundation in
// version 2.2 of Bison.
/**
** \file position.hh
** Define the yy::position class.
*/
#ifndef YY_YY_POSITION_HH_INCLUDED
# define YY_YY_POSITION_HH_INCLUDED
# include <algorithm> // std::max
# include <iostream>
# include <string>
# ifndef YY_NULLPTR
# if defined __cplusplus && 201103L <= __cplusplus
# define YY_NULLPTR nullptr
# else
# define YY_NULLPTR 0
# endif
# endif
namespace yy {
#line 56 "position.hh" // location.cc:333
/// Abstract a position.
class position
{
public:
/// Construct a position.
explicit position (std::string* f = YY_NULLPTR,
unsigned l = 1u,
unsigned c = 1u)
: filename (f)
, line (l)
, column (c)
{}
/// Initialization.
void initialize (std::string* fn = YY_NULLPTR,
unsigned l = 1u,
unsigned c = 1u)
{
filename = fn;
line = l;
column = c;
}
/** \name Line and Column related manipulators
** \{ */
/// (line related) Advance to the COUNT next lines.
void lines (int count = 1)
{
if (count)
{
column = 1u;
line = add_ (line, count, 1);
}
}
/// (column related) Advance to the COUNT next columns.
void columns (int count = 1)
{
column = add_ (column, count, 1);
}
/** \} */
/// File name to which this position refers.
std::string* filename;
/// Current line number.
unsigned line;
/// Current column number.
unsigned column;
private:
/// Compute max(min, lhs+rhs) (provided min <= lhs).
static unsigned add_ (unsigned lhs, int rhs, unsigned min)
{
return (0 < rhs || -static_cast<unsigned>(rhs) < lhs
? rhs + lhs
: min);
}
};
/// Add \a width columns, in place.
inline position&
operator+= (position& res, int width)
{
res.columns (width);
return res;
}
/// Add \a width columns.
inline position
operator+ (position res, int width)
{
return res += width;
}
/// Subtract \a width columns, in place.
inline position&
operator-= (position& res, int width)
{
return res += -width;
}
/// Subtract \a width columns.
inline position
operator- (position res, int width)
{
return res -= width;
}
/// Compare two position objects.
inline bool
operator== (const position& pos1, const position& pos2)
{
return (pos1.line == pos2.line
&& pos1.column == pos2.column
&& (pos1.filename == pos2.filename
|| (pos1.filename && pos2.filename
&& *pos1.filename == *pos2.filename)));
}
/// Compare two position objects.
inline bool
operator!= (const position& pos1, const position& pos2)
{
return !(pos1 == pos2);
}
/** \brief Intercept output stream redirection.
** \param ostr the destination output stream
** \param pos a reference to the position to redirect
*/
template <typename YYChar>
inline std::basic_ostream<YYChar>&
operator<< (std::basic_ostream<YYChar>& ostr, const position& pos)
{
if (pos.filename)
ostr << *pos.filename << ':';
return ostr << pos.line << '.' << pos.column;
}
} // yy
#line 179 "position.hh" // location.cc:333
#endif // !YY_YY_POSITION_HH_INCLUDED

View File

@@ -0,0 +1,156 @@
// A Bison parser, made by GNU Bison 3.0.5.
// Stack handling for Bison parsers in C++
// Copyright (C) 2002-2015, 2018 Free Software Foundation, Inc.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// As a special exception, you may create a larger work that contains
// part or all of the Bison parser skeleton and distribute that work
// under terms of your choice, so long as that work isn't itself a
// parser generator using the skeleton or a modified version thereof
// as a parser skeleton. Alternatively, if you modify or redistribute
// the parser skeleton itself, you may (at your option) remove this
// special exception, which will cause the skeleton and the resulting
// Bison output files to be licensed under the GNU General Public
// License without this special exception.
// This special exception was added by the Free Software Foundation in
// version 2.2 of Bison.
/**
** \file stack.hh
** Define the yy::stack class.
*/
#ifndef YY_YY_STACK_HH_INCLUDED
# define YY_YY_STACK_HH_INCLUDED
# include <vector>
namespace yy {
#line 46 "stack.hh" // stack.hh:150
/// A stack with random access from its top.
template <class T, class S = std::vector<T> >
class stack
{
public:
// Hide our reversed order.
typedef typename S::reverse_iterator iterator;
typedef typename S::const_reverse_iterator const_iterator;
stack ()
: seq_ ()
{
seq_.reserve (200);
}
stack (unsigned n)
: seq_ (n)
{}
/// Random access.
///
/// Index 0 returns the topmost element.
T&
operator[] (unsigned i)
{
return seq_[seq_.size () - 1 - i];
}
/// Random access.
///
/// Index 0 returns the topmost element.
const T&
operator[] (unsigned i) const
{
return seq_[seq_.size () - 1 - i];
}
/// Steal the contents of \a t.
///
/// Close to move-semantics.
void
push (T& t)
{
seq_.push_back (T());
operator[](0).move (t);
}
void
pop (unsigned n = 1)
{
for (; n; --n)
seq_.pop_back ();
}
void
clear ()
{
seq_.clear ();
}
typename S::size_type
size () const
{
return seq_.size ();
}
const_iterator
begin () const
{
return seq_.rbegin ();
}
const_iterator
end () const
{
return seq_.rend ();
}
private:
stack (const stack&);
stack& operator= (const stack&);
/// The wrapped container.
S seq_;
};
/// Present a slice of the top of a stack.
template <class T, class S = stack<T> >
class slice
{
public:
slice (const S& stack, unsigned range)
: stack_ (stack)
, range_ (range)
{}
const T&
operator [] (unsigned i) const
{
return stack_[range_ - i];
}
private:
const S& stack_;
unsigned range_;
};
} // yy
#line 155 "stack.hh" // stack.hh:150
#endif // !YY_YY_STACK_HH_INCLUDED

View File

@@ -0,0 +1 @@
*.pyc

View File

@@ -0,0 +1,14 @@
IF (CTYPESGEN_FOUND)
ADD_CUSTOM_COMMAND(
OUTPUT GraphQLParser.py
COMMAND ctypesgen.py ${CMAKE_CURRENT_SOURCE_DIR}/../c/*.h ${CMAKE_CURRENT_BINARY_DIR}/../c/*.h -o ${CMAKE_CURRENT_SOURCE_DIR}/GraphQLParser.py -I ${CMAKE_CURRENT_SOURCE_DIR}/.. -I ${CMAKE_CURRENT_BINARY_DIR}/.. -l graphqlparser -L ${CMAKE_CURRENT_BINARY_DIR}/.. 2>&1 > /dev/null
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/../c/GraphQLAstForEachConcreteType.h ${CMAKE_CURRENT_BINARY_DIR}/../c/GraphQLAst.h ${CMAKE_CURRENT_SOURCE_DIR}/../c/GraphQLAstNode.h ${CMAKE_CURRENT_SOURCE_DIR}/../c/GraphQLAstVisitor.h ${CMAKE_CURRENT_SOURCE_DIR}/../c/GraphQLParser.h
)
ADD_CUSTOM_TARGET(
graphql-parser-python
ALL
DEPENDS GraphQLParser.py)
ELSE()
MESSAGE(WARNING "ctypesgen.py not found; install with pip or easy_install if you want to run pythontest.py.")
ENDIF()

View File

@@ -0,0 +1,5 @@
This directory contains an example Python binding to the GraphQL
parser and AST library. It uses
[ctypesgen.py](https://github.com/davidjamesca/ctypesgen) to generate
the binding code automatically from the pure C API in
`../c`. `example.py` is a short program that uses this binding.

31
external/graphqlparser/python/example.py vendored Executable file
View File

@@ -0,0 +1,31 @@
#!/usr/bin/env python
# Copyright 2019-present, GraphQL Foundation
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
from ctypes import *
from GraphQLParser import *
def print_field(field, unused):
field_name = GraphQLAstField_get_name(field)
field_name_value = GraphQLAstName_get_value(field_name)
print 'field : ' + field_name_value
return 0
def main():
error = POINTER(c_char)()
ast = graphql_parse_string('query myquery { myfield }', byref(error))
field_visitor_callbacks = GraphQLAstVisitorCallbacks(visit_field = visit_field_func(print_field))
graphql_node_visit(ast, pointer(field_visitor_callbacks), None)
graphql_node_free(ast)
ast = graphql_parse_string('query errorQuery on oops { myfield }', byref(error))
print 'Example error:', string_at(error)
graphql_error_free(error)
if ast:
print 'BUG: we should have got a null AST back, but we got:', ast
if __name__ == '__main__':
main()

19
external/graphqlparser/syntaxdefs.h vendored Normal file
View File

@@ -0,0 +1,19 @@
/**
* Copyright 2019-present, GraphQL Foundation
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
/***
* This file contains definitions that need to be shared by the parser
* and the lexer.
*/
yy::GraphQLParserImpl::syntax_error make_error(const yy::location &loc, const std::string &str);
struct LexerExtra {
std::string str;
yy::location loc;
};

View File

@@ -0,0 +1,5 @@
CTestTestfile.cmake
gtest*/*
googletest*
release-1.8.0*
runTests*

View File

@@ -0,0 +1,5 @@
// Copyright GraphQL Foundation
#include <c/GraphQLAst.h>
#include <c/GraphQLAstVisitor.h>
/* This file is just here to make sure our C API builds OK. */

View File

@@ -0,0 +1,25 @@
ADD_SUBDIRECTORY(googletest-release-1.8.0/googletest)
ENABLE_TESTING()
INCLUDE_DIRECTORIES(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR} /usr/local/include/graphqlparser)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11 -g")
FILE(COPY valgrind.supp DESTINATION .)
FILE(COPY kitchen-sink.graphql DESTINATION .)
FILE(COPY kitchen-sink.json DESTINATION .)
FILE(COPY schema-kitchen-sink.graphql DESTINATION .)
FILE(COPY schema-kitchen-sink.json DESTINATION .)
ADD_EXECUTABLE(runTests ParserTests.cpp JsonVisitorTests.cpp BuildCAPI.c)
find_library(LIBGRAPHQLPARSER_LIBRARY libgraphqlparser.dylib HINTS /usr/local/lib)
TARGET_LINK_LIBRARIES(runTests gtest gtest_main ${LIBGRAPHQLPARSER_LIBRARY})
ADD_TEST(gtest_tests runTests)

View File

@@ -0,0 +1,28 @@
/**
* Copyright 2019-present, GraphQL Foundation
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <gtest/gtest.h>
#include "Ast.h"
#include "GraphQLParser.h"
#include "c/GraphQLAstToJSON.h"
using facebook::graphql::parseString;
TEST(JsonVisitorTests, NullValueEmitsValidJSONWithoutTrailingComma) {
const char *error = nullptr;
auto AST = parseString("{field(arg: null)}", &error);
ASSERT_STREQ(nullptr, error) << "GraphQL parser error: " << error;
const char *json = graphql_ast_to_json(reinterpret_cast<const struct GraphQLAstNode *>(AST.get()));
EXPECT_STREQ(
json,
"{\"kind\":\"Document\",\"loc\":{\"start\": {\"line\": 1,\"column\":1}, \"end\": {\"line\":1,\"column\":19}},\"definitions\":[{\"kind\":\"OperationDefinition\",\"loc\":{\"start\": {\"line\": 1,\"column\":1}, \"end\": {\"line\":1,\"column\":19}},\"operation\":\"query\",\"name\":null,\"variableDefinitions\":null,\"directives\":null,\"selectionSet\":{\"kind\":\"SelectionSet\",\"loc\":{\"start\": {\"line\": 1,\"column\":1}, \"end\": {\"line\":1,\"column\":19}},\"selections\":[{\"kind\":\"Field\",\"loc\":{\"start\": {\"line\": 1,\"column\":2}, \"end\": {\"line\":1,\"column\":18}},\"alias\":null,\"name\":{\"kind\":\"Name\",\"loc\":{\"start\": {\"line\": 1,\"column\":2}, \"end\": {\"line\":1,\"column\":7}},\"value\":\"field\"},\"arguments\":[{\"kind\":\"Argument\",\"loc\":{\"start\": {\"line\": 1,\"column\":8}, \"end\": {\"line\":1,\"column\":17}},\"name\":{\"kind\":\"Name\",\"loc\":{\"start\": {\"line\": 1,\"column\":8}, \"end\": {\"line\":1,\"column\":11}},\"value\":\"arg\"},\"value\":{\"kind\":\"NullValue\",\"loc\":{\"start\": {\"line\": 1,\"column\":13}, \"end\": {\"line\":1,\"column\":17}}}}],\"directives\":null,\"selectionSet\":null}]}}]}"
);
free((void *)json);
}

View File

@@ -0,0 +1,352 @@
/**
* Copyright 2019-present, GraphQL Foundation
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <gtest/gtest.h>
#include <cstdlib>
#include <fstream>
#include <sstream>
#include "Ast.h"
#include "GraphQLParser.h"
#include "c/GraphQLAstToJSON.h"
using namespace facebook::graphql;
using namespace facebook::graphql::ast;
static void expectError(const char *queryStr, const char *expectedError) {
const char *actualError = nullptr;
auto ast = parseString(queryStr, &actualError);
EXPECT_FALSE(ast);
EXPECT_STREQ(actualError, expectedError);
std::free((void *)actualError);
}
static void expectSuccessImpl(const char *queryStr, bool enableSchema) {
const char *actualError = nullptr;
auto ast = enableSchema
? parseStringWithExperimentalSchemaSupport(queryStr, &actualError)
: parseString(queryStr, &actualError);
EXPECT_TRUE(ast != nullptr);
EXPECT_STREQ(nullptr, actualError);
std::free((void *)actualError); // NOLINT
}
static void expectSuccess(const char *queryStr) {
expectSuccessImpl(queryStr, false);
}
static void expectSchemaSuccess(const char *queryStr) {
expectSuccessImpl(queryStr, true);
}
static void checkSimpleError() {
expectError("query myquery on type { field }",
"1.15-16: syntax error, unexpected on, expecting ( or @ or {");
}
TEST(ParserTests, RejectsUnrecognizedCharacter) {
expectError("query myquery { field };",
"1.24: unrecognized character ;");
}
TEST(ParserTests, RejectsControlCharacter) {
expectError("query myQuery { \a }",
R"(1.17: unrecognized character \a)");
}
TEST(ParserTests, AcceptsUnicodeBOM) {
expectSuccess("\xef\xbb\xbfquery myquery { field }");
expectSuccess("query myquery\xef\xbb\xbf{ field }");
}
TEST(ParserTests, ReportsErrorLocationAfterIgnoredBOM) {
expectError("\xef\xbb\xbfquery myquery { field };",
"1.27: unrecognized character ;");
}
TEST(ParserTests, RejectsPartialBOM) {
expectError("\xefquery myquery { field };",
R"(1.1: unrecognized character \xef)");
}
TEST(ParserTests, RejectsVerticalTab) {
expectError("\v", R"(1.1: unrecognized character \v)");
}
TEST(ParserTests, RejectsFormFeed) {
expectError("\f", R"(1.1: unrecognized character \f)");
}
TEST(ParserTests, RejectsNoBreakSpace) {
expectError("\xa0", R"(1.1: unrecognized character \xa0)");
}
TEST(ParserTests, LocationTracking) {
SCOPED_TRACE("LocationTracking");
checkSimpleError();
}
TEST(ParserTests, LocationTrackingResetsAcrossInputs) {
{
SCOPED_TRACE("LocationTrackingResetsAcrossInputsFirstTime");
checkSimpleError();
}
{
SCOPED_TRACE("LocationTrackingResetsAcrossInputsSecondTime");
checkSimpleError();
}
}
TEST(ParserTests, LocationTrackingCollapsesCRLF) {
expectError("\r\n;", "2.1: unrecognized character ;");
}
TEST(ParserTests, AcceptsEmptyString) {
expectSuccess(R"({ field(arg:"") })");
}
TEST(ParserTests, AcceptsEmptyBlockString) {
expectSuccess(R"({ field(arg:"""""") })");
}
TEST(ParserTests, UnterminatedString) {
expectError("\"", "1.1: Unterminated string at EOF");
expectError("\"\n\"", "1.1-2: Unterminated string");
}
TEST(ParserTests, RejectControlCharacterInString) {
expectError("{ field(arg:\"\b\") }", R"(1.13-14: unrecognized character \b)");
}
TEST(ParserTests, RejectsBadXEscapeSequence) {
expectError(R"({ field(arg:"\x") })", R"(1.13-15: bad escape sequence \x)");
}
TEST(ParserTests, RejectsIncompleteUnicodeEscape) {
expectError(R"({ field(arg:"\u1") })", "1.13-15: bad Unicode escape sequence");
}
TEST(ParserTests, RejectsUnicodeEscapeWithBadChars) {
expectError(R"({ field(arg:"\u0XX1") })", "1.13-15: bad Unicode escape sequence");
expectError(R"({ field(arg:"\uXXXX") })", "1.13-15: bad Unicode escape sequence");
expectError(R"({ field(arg:"\uFXXX") })", "1.13-15: bad Unicode escape sequence");
expectError(R"({ field(arg:"\uXXXF") })", "1.13-15: bad Unicode escape sequence");
}
TEST(ParserTests, AcceptsValidUnicodeEscape) {
const char *actualError = nullptr;
auto ast = parseString(R"({ field(arg:"\u0009Hello") })", &actualError);
EXPECT_TRUE(ast != nullptr);
EXPECT_STREQ(nullptr, actualError);
std::free((void *)actualError);
auto doc = dynamic_cast<Document *>(ast.get());
ASSERT_TRUE(doc != nullptr);
const auto& defs = doc->getDefinitions();
ASSERT_EQ(1, defs.size());
auto opDef = dynamic_cast<OperationDefinition *>(defs[0].get());
ASSERT_TRUE(opDef != nullptr);
ASSERT_EQ(1, opDef->getSelectionSet().getSelections().size());
auto field = dynamic_cast<Field *>(opDef->getSelectionSet().getSelections()[0].get());
ASSERT_TRUE(field != nullptr);
auto *args = field->getArguments();
ASSERT_NE(nullptr, args);
ASSERT_EQ(1, args->size());
auto *val = dynamic_cast<const StringValue *>(&(*args)[0]->getValue());
ASSERT_NE(nullptr, val);
EXPECT_STREQ("\tHello", val->getValue());
}
TEST(ParserTests, TracksLocationAcrossStrings) {
expectError(R"({ field(arg:"\uFEFF\n") };)",
"1.26: unrecognized character ;");
}
TEST(ParserTests, UsefulErrors) {
expectError("{ ...MissingOn }\nfragment MissingOn Type",
"2.20-23: syntax error, unexpected IDENTIFIER, expecting on");
expectError("{ field: {} }",
"1.10: syntax error, unexpected {");
expectError(
"notanoperation Foo { field }",
"1.1-14: syntax error, unexpected IDENTIFIER");
expectError("...",
"1.1-3: syntax error, unexpected ...");
}
TEST(ParserTests, AcceptsVariableInlineValues) {
expectSuccess("{ field(complex: { a: { b: [ $var ] } }) }");
}
TEST(ParserTests, RejectsVariablesInConstantValues) {
expectError("query Foo($x: Complex = { a: { b: [ $var ] } }) { field }",
"1.37-40: syntax error, unexpected VARIABLE");
}
TEST(ParserTests, RejectsFragmentsNamedOn) {
expectError("fragment on on on { on }",
"1.10-11: syntax error, unexpected on");
}
TEST(ParserTests, RejectsFragmentSpreadOfOn) {
expectError("{ ...on }",
"1.9: syntax error, unexpected }");
};
TEST(ParserTests, AcceptsNullValue) {
expectSuccess("{ fieldWithNullableStringInput(input: null) }");
}
TEST(ParserTests, AcceptsSimpleQuery) {
expectSuccess("query MyQuery { myfield }");
}
TEST(ParserTests, AcceptsSimpleMutation) {
expectSuccess("mutation MyMut { myfield }");
}
TEST(ParserTests, AcceptsSimpleSubscription) {
expectSuccess("subscription MySub { myfield }");
}
TEST(ParserTests, AcceptsQueryShorthand) {
expectSuccess("{ myfield }");
}
TEST(ParserTests, AcceptsLonghandUnnamedQuery) {
expectSuccess("query { myfield }");
}
TEST(ParserTests, AcceptsLonghandUnnamedMutation) {
expectSuccess("mutation { myfield }");
}
TEST(ParserTests, AcceptsLonghandUnnamedSubscription) {
expectSuccess("subscription { myfield }");
}
TEST(ParserTests, AllowsNonKeywordsForNames) {
const char *nonKeywords[] = {
"on",
"fragment",
"query",
"mutation",
"subscription",
"true",
"false"
};
for (auto keyword : nonKeywords) {
const char *fragmentName = !strcmp(keyword, "on") ? "a" : keyword;
std::ostringstream str;
str << "query " << keyword << "{\n"
<< " ... " << fragmentName << '\n'
<< " ... on " << keyword << " { field }\n"
<< "}\n"
<< "fragment " << fragmentName << " on Type {"
<< " " << keyword << '(' << keyword << ": $" << keyword << ") @" << keyword << '(' << keyword << ": " << keyword << ")\n"
<< "}\n";
expectSuccess(str.str().c_str());
}
}
static void testCorrectOutputForStockFile(
const char *inputFileName,
const char *outputFileName,
bool withSchemaParsing) {
FILE *fp = fopen(inputFileName, "r");
ASSERT_NE(nullptr, fp);
const char *error = nullptr;
std::unique_ptr<Node> ast;
if (withSchemaParsing) {
ast = parseFileWithExperimentalSchemaSupport(fp, &error);
} else {
ast = parseFile(fp, &error);
}
ASSERT_TRUE(ast);
ASSERT_FALSE(error);
fclose(fp);
const char *json = graphql_ast_to_json((const struct GraphQLAstNode *)ast.get());
std::ifstream ifs(outputFileName);
std::stringstream ss;
ss << ifs.rdbuf();
EXPECT_STREQ(
json,
ss.str().c_str()
);
free((void *)json);
}
TEST(ParserTests, ProducesCorrectOutputForKitchenSink) {
SCOPED_TRACE("KitchenSink");
testCorrectOutputForStockFile(
"test/kitchen-sink.graphql",
"test/kitchen-sink.json",
false);
}
TEST(ParserTests, ProducesCorrectOutputForSchemaKitchenSink) {
SCOPED_TRACE("SchemaKitchenSink");
testCorrectOutputForStockFile(
"test/schema-kitchen-sink.graphql",
"test/schema-kitchen-sink.json",
true);
}
static void expectSchemaParsing(const char *queryStr) {
char buf[strlen("1.1-XXX: schema support disabled") + 1];
ASSERT_LT(strlen(queryStr), 999);
snprintf(
buf,
sizeof(buf),
"1.1-%lu: schema support disabled",
strlen(queryStr));
expectError(queryStr, buf);
expectSchemaSuccess(queryStr);
}
#define DIRECTIVES "@d1(a: 1) @d2(a: 2)"
TEST(SchemaParserTests, SimpleSchema) {
expectSchemaParsing(
"schema " DIRECTIVES " { query: QueryType, mutation: MutType }");
expectSchemaParsing("scalar SomeScalar " DIRECTIVES);
expectSchemaParsing("type SomeObject implements SomeInterface " DIRECTIVES
" { someField : SomeType }");
expectSchemaParsing("interface SomeInterface " DIRECTIVES
" { someField : SomeType }");
expectSchemaParsing("union SomeUnion " DIRECTIVES
" = SomeType | SomeOtherType");
expectSchemaParsing("enum SomeEnum " DIRECTIVES " { VALUE, OTHER_VALUE }");
expectSchemaParsing("input SomeInput " DIRECTIVES "{ someField: SomeType, "
"otherField: otherType }");
expectSchemaParsing("extend type SomeType " DIRECTIVES
"{ anotherField : AnotherType }");
expectSchemaParsing("directive @somedirective(a1 : t1 = 1 " DIRECTIVES
", a2 : t2) on foo | bar");
}

View File

@@ -0,0 +1,59 @@
# Copyright 2019-present, GraphQL Foundation
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
query queryName($foo: ComplexType, $site: Site = MOBILE) {
whoever123is: node(id: [123, 456]) {
id ,
... on User @defer {
field2 {
id ,
alias: field1(first:10, after:$foo,) @include(if: $foo) {
id,
...frag
}
}
}
... @skip(unless: $foo) {
id
}
... {
id
}
}
}
mutation likeStory {
like(story: 123) @defer {
story {
id
}
}
}
subscription StoryLikeSubscription($input: StoryLikeSubscribeInput) {
storyLikeSubscribe(input: $input) {
story {
likers {
count
}
likeSentence {
text
}
}
}
}
fragment frag on Friend {
foo(size: $size, bar: $b, obj: {key: "value", block: """
block string uses \"""
"""})
}
{
unnamed(truthy: true, falsey: false, nullish: null),
query
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,78 @@
# Copyright 2019-present, GraphQL Foundation
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
# (this line is padding to maintain test line numbers)
schema {
query: QueryType
mutation: MutationType
}
type Foo implements Bar {
one: Type
two(argument: InputType!): Type
three(argument: InputType, other: String): Int
four(argument: String = "string"): String
five(argument: [String] = ["string", "string"]): String
six(argument: InputType = {key: "value"}): Type
seven(argument: Int = null): Type
}
type AnnotatedObject @onObject(arg: "value") {
annotatedField(arg: Type = "default" @onArg): Type @onField
}
interface Bar {
one: Type
four(argument: String = "string"): String
}
interface AnnotatedInterface @onInterface {
annotatedField(arg: Type @onArg): Type @onField
}
union Feed = Story | Article | Advert
union AnnotatedUnion @onUnion = A | B
scalar CustomScalar
scalar AnnotatedScalar @onScalar
enum Site {
DESKTOP
MOBILE
}
enum AnnotatedEnum @onEnum {
ANNOTATED_VALUE @onEnumValue
OTHER_VALUE
}
input InputType {
key: String!
answer: Int = 42
}
input AnnotatedInput @onInputObjectType {
annotatedField: Type @onField
}
extend type Foo {
seven(argument: [String]): Type
}
# NOTE: out-of-spec test cases commented out until the spec is clarified; see
# https://github.com/graphql/graphql-js/issues/650 .
# extend type Foo @onType {}
#type NoFields {}
directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
directive @include(if: Boolean!)
on FIELD
| FRAGMENT_SPREAD
| INLINE_FRAGMENT

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,33 @@
{
<osx_strdup_query_string>
Memcheck:Cond
fun:strlen
fun:strdup
fun:_ZN2yy17GraphQLParserImpl5parseEv
fun:_ZN8facebook7graphqlL7doParseEPPKcPv
fun:_ZN8facebook7graphql11parseStringEPKcPS2_
fun:_ZL11expectErrorPKcS0_
fun:_ZN44ParserTests_TracksLocationAcrossStrings_Test8TestBodyEv
fun:_ZN7testing8internal38HandleSehExceptionsInMethodIfSupportedINS_4TestEvEET0_PT_MS4_FS3_vEPKc
fun:_ZN7testing8internal35HandleExceptionsInMethodIfSupportedINS_4TestEvEET0_PT_MS4_FS3_vEPKc
fun:_ZN7testing4Test3RunEv
fun:_ZN7testing8TestInfo3RunEv
fun:_ZN7testing8TestCase3RunEv
}
{
<unix_strdup_query_string>
Memcheck:Cond
fun:__GI_strlen
fun:strdup
fun:_ZN2yy17GraphQLParserImpl5parseEv
fun:_ZN8facebook7graphqlL7doParseEPPKcPv
fun:_ZN8facebook7graphql11parseStringEPKcPS2_
fun:_ZL11expectErrorPKcS0_
fun:_ZN44ParserTests_TracksLocationAcrossStrings_Test8TestBodyEv
fun:_ZN7testing8internal38HandleSehExceptionsInMethodIfSupportedINS_4TestEvEET0_PT_MS4_FS3_vEPKc
fun:_ZN7testing8internal35HandleExceptionsInMethodIfSupportedINS_4TestEvEET0_PT_MS4_FS3_vEPKc
fun:_ZN7testing4Test3RunEv
fun:_ZN7testing8TestInfo3RunEv
fun:_ZN7testing8TestCase3RunEv
}