├── Ast.cpp ├── lexer.cpp ├── internal ├── ast │ ├── .gitignore │ ├── license.py │ ├── casing.py │ ├── c_visitor_impl.py │ ├── cxx_visitor.py │ ├── cxx_impl.py │ ├── c_impl.py │ ├── js.py │ ├── ast.py │ ├── ast.ast │ ├── c.py │ └── cxx.py ├── go │ ├── .gitignore │ ├── README.md │ ├── callbacks.go │ └── gotest.go ├── python │ ├── .gitignore │ ├── README.md │ ├── CMakeLists.txt │ └── example.py ├── test │ ├── .gitignore │ ├── CMakeLists.txt │ └── ParserTests.cpp ├── .gitignore ├── syntaxdefs.h ├── c │ ├── GraphQLAstToJSON.h │ ├── GraphQLAstToJSON.cpp │ ├── GraphQLParser.cpp │ ├── GraphQLAstNode.cpp │ ├── GraphQLAstNode.h │ ├── GraphQLAstForEachConcreteType.h │ ├── GraphQLParser.h │ ├── GraphQLAstVisitor.h │ ├── GraphQLAstVisitor.cpp │ ├── GraphQLAst.h │ └── GraphQLAst.cpp ├── .travis.yml ├── AstNode.h ├── dump_json_ast.cpp ├── CONTRIBUTING.md ├── GraphQLParser.h ├── LICENSE ├── GraphQLParser.cpp ├── install_manifest.txt ├── PATENTS ├── README.md ├── CMakeLists.txt ├── stack.hh ├── AstVisitor.h ├── JsonVisitor.h ├── position.hh ├── location.hh ├── Ast.cpp ├── lexer.lpp ├── lexer.h ├── JsonVisitor.cpp ├── parser.ypp ├── Ast.h └── parser.tab.hpp ├── parser.tab.cpp ├── GraphQLParser.cpp ├── JsonVisitor.cpp ├── c_GraphQLAst.cpp ├── c_GraphQLParser.cpp ├── c_GraphQLAstNode.cpp ├── c_GraphQLAstToJSON.cpp ├── c_GraphQLAstVisitor.cpp ├── docker ├── Dockerfile └── build.sh ├── cgo_flags.go ├── gitignore.patch ├── README.md ├── import.sh └── includes.patch /Ast.cpp: -------------------------------------------------------------------------------- 1 | internal/Ast.cpp -------------------------------------------------------------------------------- /lexer.cpp: -------------------------------------------------------------------------------- 1 | internal/lexer.cpp -------------------------------------------------------------------------------- /internal/ast/.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /internal/go/.gitignore: -------------------------------------------------------------------------------- 1 | go 2 | -------------------------------------------------------------------------------- /internal/python/.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /parser.tab.cpp: -------------------------------------------------------------------------------- 1 | internal/parser.tab.cpp -------------------------------------------------------------------------------- /GraphQLParser.cpp: -------------------------------------------------------------------------------- 1 | internal/GraphQLParser.cpp -------------------------------------------------------------------------------- /JsonVisitor.cpp: -------------------------------------------------------------------------------- 1 | internal/JsonVisitor.cpp -------------------------------------------------------------------------------- /c_GraphQLAst.cpp: -------------------------------------------------------------------------------- 1 | internal/c/GraphQLAst.cpp -------------------------------------------------------------------------------- /c_GraphQLParser.cpp: -------------------------------------------------------------------------------- 1 | internal/c/GraphQLParser.cpp -------------------------------------------------------------------------------- /c_GraphQLAstNode.cpp: -------------------------------------------------------------------------------- 1 | internal/c/GraphQLAstNode.cpp -------------------------------------------------------------------------------- /c_GraphQLAstToJSON.cpp: -------------------------------------------------------------------------------- 1 | internal/c/GraphQLAstToJSON.cpp -------------------------------------------------------------------------------- /c_GraphQLAstVisitor.cpp: -------------------------------------------------------------------------------- 1 | internal/c/GraphQLAstVisitor.cpp -------------------------------------------------------------------------------- /internal/test/.gitignore: -------------------------------------------------------------------------------- 1 | CTestTestfile.cmake 2 | gtest*/* 3 | runTests* 4 | -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:latest 2 | 3 | # Install base requirements 4 | RUN apk add --update alpine-sdk flex bison cmake python 5 | 6 | COPY build.sh /data/build.sh 7 | 8 | CMD ["/data/build.sh"] 9 | -------------------------------------------------------------------------------- /internal/.gitignore: -------------------------------------------------------------------------------- 1 | bison.tab.cpp 2 | bison.tab.hpp 3 | *.o 4 | parser.output 5 | dump_json_ast 6 | *.dSYM 7 | CMakeCache.txt 8 | CMakeFiles 9 | CMakeScripts 10 | Makefile 11 | cmake_install.cmake 12 | *.a 13 | *.dylib 14 | *.so 15 | GraphQLParser.py 16 | -------------------------------------------------------------------------------- /internal/python/README.md: -------------------------------------------------------------------------------- 1 | This directory contains an example Python binding to the GraphQL 2 | parser and AST library. It uses 3 | [ctypesgen.py](https://github.com/davidjamesca/ctypesgen) to generate 4 | the binding code automatically from the pure C API in 5 | `../c`. `example.py` is a short program that uses this binding. 6 | -------------------------------------------------------------------------------- /internal/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ADD_SUBDIRECTORY(gtest-1.7.0) 2 | 3 | ENABLE_TESTING() 4 | 5 | INCLUDE_DIRECTORIES(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR}) 6 | 7 | ADD_EXECUTABLE(runTests ParserTests.cpp) 8 | 9 | TARGET_LINK_LIBRARIES(runTests gtest gtest_main) 10 | 11 | TARGET_LINK_LIBRARIES(runTests graphqlparser) 12 | 13 | ADD_TEST(gtest_tests runTests) 14 | -------------------------------------------------------------------------------- /cgo_flags.go: -------------------------------------------------------------------------------- 1 | // Package graphqlparser uses the cgo compilation facilities to build the 2 | // GraphQL C++ parser. 3 | package graphqlparser 4 | 5 | // #cgo CPPFLAGS: -Iinternal 6 | // #cgo CXXFLAGS: -std=c++11 -fPIC -fno-omit-frame-pointer -momit-leaf-frame-pointer 7 | // #cgo CXXFLAGS: -W -Wextra -Wno-deprecated-register -Wno-unused-parameter -Wno-sign-compare -Wno-backslash-newline-escape 8 | import "C" 9 | -------------------------------------------------------------------------------- /docker/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eu 4 | 5 | URL=${LIBGRAPHQLPARSER_URL:-"https://github.com/graphql/libgraphqlparser/archive/master.tar.gz"} 6 | 7 | # Build libgraphqlparser 8 | mkdir -p /data/libgraphqlparser 9 | curl -sSL ${URL} \ 10 | | tar -v -C /data/libgraphqlparser -xz --strip-components=1 \ 11 | && cd /data/libgraphqlparser \ 12 | && cmake . \ 13 | && make \ 14 | && make install 15 | -------------------------------------------------------------------------------- /internal/go/README.md: -------------------------------------------------------------------------------- 1 | This directory contains an example usage of the GraphQL parser and AST 2 | library from Go. See [cgo's 3 | documentation](https://github.com/golang/go/wiki/cgo), particularly 4 | the "Function pointer callbacks" section, for explanation of the 5 | mechanisms in use. 6 | 7 | To build, first build the main GraphQLParser library in the parent 8 | directory, and then set this directory to be your `GOPATH` and run `go 9 | build`. 10 | -------------------------------------------------------------------------------- /internal/go/callbacks.go: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | package main 10 | 11 | /* 12 | struct GraphQLAstField; 13 | int printField_cgo(struct GraphQLAstField *field, void *unused) { 14 | return printField(field, unused); 15 | } 16 | */ 17 | import "C" 18 | -------------------------------------------------------------------------------- /gitignore.patch: -------------------------------------------------------------------------------- 1 | diff --git 1/internal/.gitignore 2/internal/.gitignore 2 | index 0173588..7036933 100644 3 | --- 1/internal/.gitignore 4 | +++ 2/internal/.gitignore 5 | @@ -3,9 +3,6 @@ bison.tab.hpp 6 | *.o 7 | parser.output 8 | dump_json_ast 9 | -Ast.h 10 | -Ast.cpp 11 | -AstVisitor.h 12 | *.dSYM 13 | CMakeCache.txt 14 | CMakeFiles 15 | 16 | diff --git 1/internal/c/.gitignore 2/internal/c/.gitignore 17 | deleted file mode 100644 18 | index 02f06d2..e69de29 100644 19 | --- 1/internal/c/.gitignore 20 | +++ /dev/null 21 | @@ -1,3 +0,0 @@ 22 | -GraphQLAst.h 23 | -GraphQLAst.cpp 24 | -GraphQLAstForEachConcreteType.h 25 | -------------------------------------------------------------------------------- /internal/syntaxdefs.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | #pragma once 10 | 11 | /*** 12 | * This file contains definitions that need to be shared by the parser 13 | * and the lexer. 14 | */ 15 | 16 | yy::GraphQLParserImpl::syntax_error make_error(const yy::location &loc, const std::string &str); 17 | 18 | struct LexerExtra { 19 | std::string str; 20 | yy::location loc; 21 | }; 22 | -------------------------------------------------------------------------------- /internal/ast/license.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015, Facebook, Inc. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. An additional grant 6 | # of patent rights can be found in the PATENTS file in the same directory. 7 | 8 | C_LICENSE_COMMENT = '''/** 9 | * Copyright (c) 2015, Facebook, Inc. 10 | * All rights reserved. 11 | * 12 | * This source code is licensed under the BSD-style license found in the 13 | * LICENSE file in the root directory of this source tree. An additional grant 14 | * of patent rights can be found in the PATENTS file in the same directory. 15 | */ 16 | ''' 17 | -------------------------------------------------------------------------------- /internal/c/GraphQLAstToJSON.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #pragma once 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | struct GraphQLAstNode; 17 | 18 | /** 19 | * Serialize the given AST to JSON. The returned C string must be 20 | * freed with free(). 21 | */ 22 | const char *graphql_ast_to_json(const struct GraphQLAstNode *node); 23 | 24 | #ifdef __cplusplus 25 | } 26 | #endif 27 | -------------------------------------------------------------------------------- /internal/c/GraphQLAstToJSON.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #include "c/GraphQLAstToJSON.h" 11 | 12 | #include 13 | 14 | #include "JsonVisitor.h" 15 | #include "AstNode.h" 16 | 17 | 18 | const char *graphql_ast_to_json(const struct GraphQLAstNode *node) 19 | { 20 | facebook::graphql::ast::visitor::JsonVisitor visitor; 21 | ((facebook::graphql::ast::Node *)node)->accept(&visitor); 22 | return strdup(visitor.getResult().c_str()); 23 | } 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # c-graphqlparser 2 | 3 | This is a go-gettable version of the [libgraphqlparser](https://github.com/graphql/libgraphqlparser) C library for use in Go code that needs to link against the libgraphqlparser C library but wants to integrate with `go get` and `go build`. 4 | 5 | To use in your project you need to import the package and set appropriate cgo flag directives: 6 | 7 | ``` 8 | import _ "github.com/tecbot/c-graphqlparser" 9 | 10 | // #cgo CXXFLAGS: -std=c++11 11 | // #cgo CPPFLAGS: -I /c-graphqlparser/internal 12 | // #cgo darwin LDFLAGS: -Wl,-undefined -Wl,dynamic_lookup 13 | // #cgo !darwin LDFLAGS: -Wl,-unresolved-symbols=ignore-all 14 | import "C" 15 | ``` 16 | 17 | To update the upstream version of libgraphqlparser you'll want to run `./import.sh`. 18 | -------------------------------------------------------------------------------- /internal/.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | 3 | compiler: 4 | - clang 5 | - gcc 6 | 7 | before_install: 8 | - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test 9 | - sudo apt-get update -qq 10 | # bison and flex are not installed in CI because 11 | # 1) the versions in Travis are too old, and 12 | # 2) up-to-date bison and flex output should be checked in. 13 | # Versions of g++ prior to 4.8 don't have very good C++11 support. 14 | - sudo apt-get install -y g++-4.8 15 | && sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 90 16 | - wget https://googletest.googlecode.com/files/gtest-1.7.0.zip 17 | && cd test 18 | && unzip ../gtest-1.7.0.zip 19 | && cd .. 20 | && rm gtest-1.7.0.zip 21 | 22 | script: mkdir build && cd build && cmake .. -Dtest=ON && make && test/runTests 23 | -------------------------------------------------------------------------------- /internal/ast/casing.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015, Facebook, Inc. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. An additional grant 6 | # of patent rights can be found in the PATENTS file in the same directory. 7 | 8 | def title(s): 9 | '''Capitalize the first character of s.''' 10 | return s[0].capitalize() + s[1:] 11 | 12 | 13 | def camel(s): 14 | '''Lowercase the first character of s.''' 15 | return s[0].lower() + s[1:] 16 | 17 | 18 | def snake(s): 19 | '''Convert from title or camelCase to snake_case.''' 20 | if len(s) < 2: 21 | return s.lower() 22 | out = s[0].lower() 23 | for c in s[1:]: 24 | if c.isupper(): 25 | out += '_' 26 | c = c.lower() 27 | out += c 28 | return out 29 | -------------------------------------------------------------------------------- /internal/AstNode.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #pragma once 11 | 12 | #include "location.hh" 13 | 14 | namespace facebook { 15 | namespace graphql { 16 | namespace ast { 17 | 18 | namespace visitor { 19 | class AstVisitor; 20 | } 21 | 22 | class Node { 23 | yy::location location_; 24 | public: 25 | explicit Node(const yy::location &location) 26 | : location_(location) {} 27 | 28 | virtual ~Node() {} 29 | 30 | const yy::location &getLocation() const 31 | { return location_; } 32 | 33 | virtual void accept(visitor::AstVisitor *visitor) = 0; 34 | }; 35 | 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /internal/python/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | IF (CTYPESGEN_FOUND) 3 | ADD_CUSTOM_COMMAND( 4 | OUTPUT GraphQLParser.py 5 | 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 6 | 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 7 | ) 8 | ADD_CUSTOM_TARGET( 9 | graphql-parser-python 10 | ALL 11 | DEPENDS GraphQLParser.py) 12 | ELSE() 13 | MESSAGE(WARNING "ctypesgen.py not found; install with pip or easy_install if you want to run pythontest.py.") 14 | ENDIF() 15 | -------------------------------------------------------------------------------- /import.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | set -eu 4 | 5 | URL="https://github.com/graphql/libgraphqlparser/archive/master.tar.gz" 6 | 7 | rm -rf *.cpp internal/* 8 | docker run --rm \ 9 | -v $PWD/internal:/data/libgraphqlparser \ 10 | -e LIBGRAPHQLPARSER_URL=$URL \ 11 | tecbot/libgraphqlparser 12 | 13 | # apply patches 14 | patch -p1 < includes.patch 15 | patch -p1 < gitignore.patch 16 | 17 | # stuff we need to compile. 18 | SOURCES=' 19 | Ast.cpp 20 | GraphQLParser.cpp 21 | JsonVisitor.cpp 22 | lexer.cpp 23 | parser.tab.cpp 24 | ' 25 | 26 | # symlink so cgo compiles them 27 | for file in $SOURCES; do 28 | ln -sf internal/$file . 29 | done 30 | 31 | # stuff we need to compile. 32 | SOURCES=' 33 | GraphQLAst.cpp 34 | GraphQLAstNode.cpp 35 | GraphQLAstToJSON.cpp 36 | GraphQLAstVisitor.cpp 37 | GraphQLParser.cpp 38 | ' 39 | 40 | # symlink so cgo compiles them 41 | for file in $SOURCES; do 42 | ln -sf internal/c/$file ./c_$file 43 | done 44 | -------------------------------------------------------------------------------- /internal/c/GraphQLParser.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #include "c/GraphQLParser.h" 11 | #include "GraphQLParser.h" 12 | #include "AstNode.h" 13 | 14 | #include 15 | 16 | struct GraphQLAstNode *graphql_parse_string(const char *text, const char **error) { 17 | return (struct GraphQLAstNode *)facebook::graphql::parseString(text, error).release(); 18 | } 19 | 20 | struct GraphQLAstNode *graphql_parse_file(FILE *file, const char **error) { 21 | return (struct GraphQLAstNode *)facebook::graphql::parseFile(file, error).release(); 22 | } 23 | 24 | void graphql_error_free(const char *error) { 25 | std::free((void *)error); 26 | } 27 | -------------------------------------------------------------------------------- /internal/c/GraphQLAstNode.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #include "c/GraphQLAstNode.h" 11 | #include "AstNode.h" 12 | 13 | using facebook::graphql::ast::Node; 14 | 15 | void graphql_node_get_location(const struct GraphQLAstNode *node, 16 | struct GraphQLAstLocation *location) { 17 | const Node *realNode = (Node *)node; 18 | const auto &loc = realNode->getLocation(); 19 | location->beginLine = loc.begin.line; 20 | location->beginColumn = loc.begin.column; 21 | location->endLine = loc.end.line; 22 | location->endColumn = loc.end.column; 23 | } 24 | 25 | void graphql_node_free(struct GraphQLAstNode *node) { 26 | delete (Node *)node; 27 | } 28 | -------------------------------------------------------------------------------- /internal/c/GraphQLAstNode.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #pragma once 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | /* Opaque type representing a generic AST node. */ 17 | struct GraphQLAstNode; 18 | 19 | /* A location in the AST. */ 20 | struct GraphQLAstLocation { 21 | unsigned int beginLine; 22 | unsigned int beginColumn; 23 | unsigned int endLine; 24 | unsigned int endColumn; 25 | }; 26 | 27 | /* Fills location with location information for the given node. */ 28 | void graphql_node_get_location(const struct GraphQLAstNode *node, 29 | struct GraphQLAstLocation *location); 30 | 31 | void graphql_node_free(struct GraphQLAstNode *node); 32 | 33 | #ifdef __cplusplus 34 | } 35 | #endif 36 | -------------------------------------------------------------------------------- /internal/ast/c_visitor_impl.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015, Facebook, Inc. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. An additional grant 6 | # of patent rights can be found in the PATENTS file in the same directory. 7 | 8 | from casing import snake 9 | from license import C_LICENSE_COMMENT 10 | 11 | class Printer(object): 12 | '''Printer for a simple list of types to be visited by the C visitor. 13 | ''' 14 | 15 | def __init__(self): 16 | self._types = [] 17 | 18 | def start_file(self): 19 | print C_LICENSE_COMMENT + '/** @generated */' 20 | print '#define FOR_EACH_CONCRETE_TYPE(MACRO) \\' 21 | 22 | def start_type(self, name): 23 | self._types.append(name) 24 | 25 | def field(self, type, name, nullable, plural): 26 | pass 27 | 28 | def end_type(self, name): 29 | pass 30 | 31 | def end_file(self): 32 | print ' \\\n'.join('MACRO(%s, %s)' % (name, snake(name)) for name in self._types) 33 | 34 | def start_union(self, name): 35 | pass 36 | 37 | def union_option(self, option): 38 | pass 39 | 40 | def end_union(self, name): 41 | pass 42 | -------------------------------------------------------------------------------- /internal/dump_json_ast.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #include "AstNode.h" 11 | #include "GraphQLParser.h" 12 | #include "c/GraphQLAstToJSON.h" 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | 19 | using std::cout; 20 | using std::cerr; 21 | using std::endl; 22 | using std::fopen; 23 | using std::fclose; 24 | using std::free; 25 | 26 | 27 | int main(int argc, char **argv) { 28 | const char *error; 29 | FILE * in; 30 | if (argc > 1) { 31 | in = fopen(argv[1], "r"); 32 | } else { 33 | in = stdin; 34 | } 35 | auto AST = facebook::graphql::parseFile(in, &error); 36 | if (argc > 1) { 37 | fclose(in); 38 | } 39 | if (!AST) { 40 | cerr << "Parser failed with error: " << error << endl; 41 | free((void *)error); 42 | return 1; 43 | } 44 | 45 | const char *json = graphql_ast_to_json((const struct GraphQLAstNode *)AST.get()); 46 | puts(json); 47 | free((void *)json); 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /internal/python/example.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) 2015, Facebook, Inc. 3 | # All rights reserved. 4 | # 5 | # This source code is licensed under the BSD-style license found in the 6 | # LICENSE file in the root directory of this source tree. An additional grant 7 | # of patent rights can be found in the PATENTS file in the same directory. 8 | 9 | from ctypes import * 10 | from GraphQLParser import * 11 | 12 | def print_field(field, unused): 13 | field_name = GraphQLAstField_get_name(field) 14 | field_name_value = GraphQLAstName_get_value(field_name) 15 | print 'field : ' + field_name_value 16 | return 0 17 | 18 | def main(): 19 | error = POINTER(c_char)() 20 | ast = graphql_parse_string('query myquery { myfield }', byref(error)) 21 | field_visitor_callbacks = GraphQLAstVisitorCallbacks(visit_field = visit_field_func(print_field)) 22 | graphql_node_visit(ast, pointer(field_visitor_callbacks), None) 23 | 24 | graphql_node_free(ast) 25 | 26 | ast = graphql_parse_string('query errorQuery on oops { myfield }', byref(error)) 27 | print 'Example error:', string_at(error) 28 | graphql_error_free(error) 29 | if ast: 30 | print 'BUG: we should have got a null AST back, but we got:', ast 31 | 32 | if __name__ == '__main__': 33 | main() 34 | -------------------------------------------------------------------------------- /internal/c/GraphQLAstForEachConcreteType.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | /** @generated */ 10 | #define FOR_EACH_CONCRETE_TYPE(MACRO) \ 11 | MACRO(Document, document) \ 12 | MACRO(OperationDefinition, operation_definition) \ 13 | MACRO(VariableDefinition, variable_definition) \ 14 | MACRO(SelectionSet, selection_set) \ 15 | MACRO(Field, field) \ 16 | MACRO(Argument, argument) \ 17 | MACRO(FragmentSpread, fragment_spread) \ 18 | MACRO(InlineFragment, inline_fragment) \ 19 | MACRO(FragmentDefinition, fragment_definition) \ 20 | MACRO(Variable, variable) \ 21 | MACRO(IntValue, int_value) \ 22 | MACRO(FloatValue, float_value) \ 23 | MACRO(StringValue, string_value) \ 24 | MACRO(BooleanValue, boolean_value) \ 25 | MACRO(EnumValue, enum_value) \ 26 | MACRO(ArrayValue, array_value) \ 27 | MACRO(ObjectValue, object_value) \ 28 | MACRO(ObjectField, object_field) \ 29 | MACRO(Directive, directive) \ 30 | MACRO(NamedType, named_type) \ 31 | MACRO(ListType, list_type) \ 32 | MACRO(NonNullType, non_null_type) \ 33 | MACRO(Name, name) 34 | -------------------------------------------------------------------------------- /internal/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to libgraphqlparser 2 | We want to make contributing to this project as easy and transparent as 3 | possible. 4 | 5 | ## Pull Requests 6 | We actively welcome your pull requests. 7 | 8 | 1. Fork the repo and create your branch from `master`. 9 | 2. If you've added code that should be tested, add tests 10 | 3. If you've changed APIs, update the documentation. 11 | 4. Ensure the test suite passes. 12 | 5. Make sure your code lints. 13 | 6. If you haven't already, complete the Contributor License Agreement ("CLA"). 14 | 15 | ## Contributor License Agreement ("CLA") 16 | In order to accept your pull request, we need you to submit a CLA. You only need 17 | to do this once to work on any of Facebook's open source projects. 18 | 19 | Complete your CLA here: 20 | 21 | ## Issues 22 | We use GitHub issues to track public bugs. Please ensure your description is 23 | clear and has sufficient instructions to be able to reproduce the issue. 24 | 25 | Facebook has a [bounty program](https://www.facebook.com/whitehat/) for the safe 26 | disclosure of security bugs. In those cases, please go through the process 27 | outlined on that page and do not file a public issue. 28 | 29 | ## License 30 | By contributing to libgraphqlparser, you agree that your contributions 31 | will be licensed under its BSD license. 32 | -------------------------------------------------------------------------------- /internal/GraphQLParser.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | /** 11 | * The purpose of this file is to provide a nice interface to parsing 12 | * GraphQL, rather than the old-fashioned interface provided by bison 13 | * and flex. 14 | */ 15 | 16 | #pragma once 17 | 18 | #include 19 | #include 20 | 21 | namespace facebook { 22 | namespace graphql { 23 | 24 | namespace ast { 25 | class Node; 26 | } 27 | 28 | /** 29 | * Parse the given GraphQL source string, returning an AST. Returns 30 | * nullptr on error and, if error is not null, places a string 31 | * describing what went wrong in error that must be freed with free(3). 32 | */ 33 | std::unique_ptr parseString(const char *text, const char **error); 34 | 35 | /** 36 | * Read and parse GraphQL source from the given file, returning an 37 | * AST. Returns nullptr on error and, if error is not null, places an 38 | * error string in error that must be freed with free(3). 39 | */ 40 | std::unique_ptr parseFile(FILE *file, const char **error); 41 | 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /internal/c/GraphQLParser.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #pragma once 11 | 12 | #include 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | /** 19 | * This file provides C wrappers for ../GraphQLParser.h. 20 | */ 21 | 22 | struct GraphQLAstNode; 23 | 24 | /** 25 | * Parse the given GraphQL source string, returning an AST. Returns 26 | * NULL on error. Return value must be freed with 27 | * graphql_node_free(). If NULL is returned and error is not NULL, an 28 | * error message is placed in error and must be freed with 29 | * graphql_error_free(). 30 | */ 31 | struct GraphQLAstNode *graphql_parse_string(const char *text, 32 | const char **error); 33 | 34 | /** 35 | * Read and parse GraphQL source from the given file, returning an 36 | * AST. Returns nullptr on error. Return value must be freed with 37 | * graphql_node_free(). If NULL is returned and error is not NULL, an 38 | * error message is placed in error and must be freed with 39 | * graphql_error_free(). 40 | */ 41 | struct GraphQLAstNode *graphql_parse_file(FILE *file, const char **error); 42 | 43 | /** 44 | * Frees an error. 45 | */ 46 | void graphql_error_free(const char *error); 47 | 48 | #ifdef __cplusplus 49 | } 50 | #endif 51 | -------------------------------------------------------------------------------- /internal/ast/cxx_visitor.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015, Facebook, Inc. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. An additional grant 6 | # of patent rights can be found in the PATENTS file in the same directory. 7 | 8 | from casing import camel, title 9 | from license import C_LICENSE_COMMENT 10 | 11 | class Printer(object): 12 | def __init__(self): 13 | pass 14 | 15 | def start_file(self): 16 | print C_LICENSE_COMMENT + '''/** @generated */ 17 | 18 | #pragma once 19 | 20 | #include "Ast.h" 21 | 22 | namespace facebook { 23 | namespace graphql { 24 | namespace ast { 25 | namespace visitor { 26 | 27 | class AstVisitor { 28 | public: 29 | virtual ~AstVisitor() {} 30 | ''' 31 | 32 | def end_file(self): 33 | print '};' # end AstVisitor 34 | print 35 | print '}' 36 | print '}' 37 | print '}' 38 | print '}' 39 | 40 | def start_type(self, name): 41 | titleName = title(name) 42 | camelName = camel(titleName) 43 | print ' virtual bool visit%s(const %s &%s) { return true; }' % ( 44 | titleName, 45 | titleName, 46 | camelName) 47 | print ' virtual void endVisit%s(const %s &%s) { }' % ( 48 | titleName, 49 | titleName, 50 | camelName) 51 | print 52 | 53 | def end_type(self, name): 54 | pass 55 | 56 | def field(self, type, name, nullable, plural): 57 | pass 58 | 59 | def start_union(self, name): 60 | pass 61 | 62 | def union_option(self, option): 63 | pass 64 | 65 | def end_union(self, name): 66 | pass 67 | -------------------------------------------------------------------------------- /internal/LICENSE: -------------------------------------------------------------------------------- 1 | BSD License 2 | 3 | For libgraphqlparser software 4 | 5 | Copyright (c) 2015-present, Facebook, Inc. All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without modification, 8 | are permitted provided that the following conditions are met: 9 | 10 | * Redistributions of source code must retain the above copyright notice, this 11 | list of conditions and the following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the above copyright notice, 14 | this list of conditions and the following disclaimer in the documentation 15 | and/or other materials provided with the distribution. 16 | 17 | * Neither the name Facebook nor the names of its contributors may be used to 18 | endorse or promote products derived from this software without specific 19 | prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 22 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 25 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 28 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | -------------------------------------------------------------------------------- /internal/GraphQLParser.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #include "GraphQLParser.h" 11 | 12 | #include "AstNode.h" 13 | 14 | #include "parser.tab.hpp" 15 | #include "lexer.h" 16 | #include "syntaxdefs.h" 17 | 18 | namespace facebook { 19 | namespace graphql { 20 | 21 | // Given properly-configured yylex, run the parser and return the 22 | // result. 23 | static std::unique_ptr doParse(const char **outError, yyscan_t scanner) { 24 | Node *outAST; 25 | yy::GraphQLParserImpl parser(&outAST, outError, scanner); 26 | int failure = parser.parse(); 27 | return !failure ? std::unique_ptr(outAST) : nullptr; 28 | } 29 | 30 | std::unique_ptr parseString(const char *text, const char **error) { 31 | yyscan_t scanner; 32 | struct LexerExtra extra; 33 | yylex_init_extra(&extra, &scanner); 34 | YY_BUFFER_STATE buffer = yy_scan_string(text, scanner); 35 | yy_switch_to_buffer(buffer, scanner); 36 | 37 | auto result = doParse(error, scanner); 38 | yylex_destroy(scanner); 39 | return result; 40 | } 41 | 42 | std::unique_ptr parseFile(FILE *file, const char **error) { 43 | yyscan_t scanner; 44 | struct LexerExtra extra; 45 | yylex_init_extra(&extra, &scanner); 46 | yyset_in(file, scanner); 47 | 48 | auto result = doParse(error, scanner); 49 | yylex_destroy(scanner); 50 | 51 | return result; 52 | } 53 | 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /internal/ast/cxx_impl.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015, Facebook, Inc. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. An additional grant 6 | # of patent rights can be found in the PATENTS file in the same directory. 7 | 8 | from license import C_LICENSE_COMMENT 9 | 10 | class Printer(object): 11 | def __init__(self): 12 | pass 13 | 14 | def start_file(self): 15 | print C_LICENSE_COMMENT + '''/** @generated */ 16 | 17 | #include "Ast.h" 18 | #include "AstVisitor.h" 19 | 20 | namespace facebook { 21 | namespace graphql { 22 | namespace ast { 23 | ''' 24 | 25 | def end_file(self): 26 | print '}' 27 | print '}' 28 | print '}' 29 | 30 | def start_type(self, name): 31 | print '''void %s::accept(visitor::AstVisitor *visitor) { 32 | if (visitor->visit%s(*this)) { 33 | ''' % (name, name) 34 | 35 | def field(self, type, name, nullable, plural): 36 | if type in ['OperationKind', 'string', 'double', 'boolean']: 37 | return 38 | 39 | if plural: 40 | accept = '{ for (const auto &x : *%s_) { x->accept(visitor); } }' % name 41 | if nullable: 42 | accept = 'if (%s_) %s' % (name, accept) 43 | print ' ' + accept 44 | else: 45 | accept = '%s_->accept(visitor);' % name 46 | if nullable: 47 | accept = 'if (%s_) { %s }' % (name, accept) 48 | print ' ' + accept 49 | 50 | def end_type(self, name): 51 | print ''' } 52 | visitor->endVisit%s(*this); 53 | } 54 | ''' % name 55 | 56 | def start_union(self, name): 57 | pass 58 | 59 | def union_option(self, option): 60 | pass 61 | 62 | def end_union(self, name): 63 | pass 64 | -------------------------------------------------------------------------------- /internal/ast/c_impl.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015, Facebook, Inc. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. An additional grant 6 | # of patent rights can be found in the PATENTS file in the same directory. 7 | 8 | from c import field_prototype, return_type, struct_name 9 | from casing import title 10 | from license import C_LICENSE_COMMENT 11 | 12 | class Printer(object): 13 | '''Printer for the implementation of the pure C interface to the AST. 14 | ''' 15 | 16 | def __init__(self): 17 | self._current_type = None 18 | 19 | def start_file(self): 20 | print C_LICENSE_COMMENT + '''/** @generated */ 21 | 22 | #include "GraphQLAst.h" 23 | #include "../Ast.h" 24 | 25 | using namespace facebook::graphql::ast; 26 | ''' 27 | 28 | def end_file(self): 29 | pass 30 | 31 | def start_type(self, name): 32 | self._current_type = name 33 | 34 | def field(self, type, name, nullable, plural): 35 | print field_prototype(self._current_type, type, name, nullable, plural) + ' {' 36 | print ' const auto *realNode = (const %s *)node;' % self._current_type 37 | title_name = title(name) 38 | call_get = 'realNode->get%s()' % title_name 39 | if plural: 40 | if nullable: 41 | print ' return %s ? %s->size() : 0;' % (call_get, call_get) 42 | else: 43 | print ' return %s.size();' % call_get 44 | else: 45 | if type in ['string', 'OperationKind', 'boolean']: 46 | print ' return %s;' % call_get 47 | else: 48 | fmt = ' return (const struct %s *)%s%s;' 49 | print fmt % (struct_name(type), '' if nullable else '&', call_get) 50 | 51 | print '}' 52 | 53 | def end_type(self, name): 54 | pass 55 | 56 | def start_union(self, name): 57 | pass 58 | 59 | def union_option(self, option): 60 | pass 61 | 62 | def end_union(self, name): 63 | pass 64 | -------------------------------------------------------------------------------- /includes.patch: -------------------------------------------------------------------------------- 1 | diff --git 1/internal/c/GraphQLAst.cpp 2/internal/c/GraphQLAst.cpp 2 | index 3996c9a..cf39d4b 100644 3 | --- 1/internal/c/GraphQLAst.cpp 4 | +++ 2/internal/c/GraphQLAst.cpp 5 | @@ -8,8 +8,8 @@ 6 | */ 7 | /** @generated */ 8 | 9 | -#include "GraphQLAst.h" 10 | -#include "../Ast.h" 11 | +#include "c/GraphQLAst.h" 12 | +#include "Ast.h" 13 | 14 | using namespace facebook::graphql::ast; 15 | 16 | diff --git a/internal/c/GraphQLAstNode.cpp b/internal/c/GraphQLAstNode.cpp 17 | index a7947b3..9eb2f17 100644 18 | --- a/internal/c/GraphQLAstNode.cpp 19 | +++ b/internal/c/GraphQLAstNode.cpp 20 | @@ -7,8 +7,8 @@ 21 | * of patent rights can be found in the PATENTS file in the same directory. 22 | */ 23 | 24 | -#include "GraphQLAstNode.h" 25 | -#include "../AstNode.h" 26 | +#include "c/GraphQLAstNode.h" 27 | +#include "AstNode.h" 28 | 29 | using facebook::graphql::ast::Node; 30 | 31 | diff --git a/internal/c/GraphQLParser.cpp b/internal/c/GraphQLParser.cpp 32 | index 871a5f9..5f8aa5a 100644 33 | --- a/internal/c/GraphQLParser.cpp 34 | +++ b/internal/c/GraphQLParser.cpp 35 | @@ -7,9 +7,9 @@ 36 | * of patent rights can be found in the PATENTS file in the same directory. 37 | */ 38 | 39 | +#include "c/GraphQLParser.h" 40 | #include "GraphQLParser.h" 41 | -#include "../GraphQLParser.h" 42 | -#include "../AstNode.h" 43 | +#include "AstNode.h" 44 | 45 | #include 46 | 47 | diff --git 1/internal/c/GraphQLAstToJSON.cpp 2/internal/c/GraphQLAstToJSON.cpp 48 | index ec42ae5..fe1984e 100644 49 | --- 1/internal/c/GraphQLAstToJSON.cpp 50 | +++ 2/internal/c/GraphQLAstToJSON.cpp 51 | @@ -7,12 +7,12 @@ 52 | * of patent rights can be found in the PATENTS file in the same directory. 53 | */ 54 | 55 | -#include "GraphQLAstToJSON.h" 56 | +#include "c/GraphQLAstToJSON.h" 57 | 58 | #include 59 | 60 | -#include "../JsonVisitor.h" 61 | -#include "../AstNode.h" 62 | +#include "JsonVisitor.h" 63 | +#include "AstNode.h" 64 | 65 | 66 | const char *graphql_ast_to_json(const struct GraphQLAstNode *node) 67 | -------------------------------------------------------------------------------- /internal/go/gotest.go: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | package main 10 | 11 | /* 12 | #cgo CFLAGS: -I ../c -I .. 13 | #cgo LDFLAGS: -L .. -lgraphqlparser 14 | #include "GraphQLAst.h" 15 | #include "GraphQLAstNode.h" 16 | #include "GraphQLAstVisitor.h" 17 | #include "GraphQLParser.h" 18 | #include 19 | 20 | int printField_cgo(struct GraphQLAstField *field, void *unused); 21 | */ 22 | import "C" 23 | 24 | import "errors" 25 | import "fmt" 26 | import "unsafe" 27 | 28 | //export printField 29 | func printField(field *C.struct_GraphQLAstField, unused unsafe.Pointer) int { 30 | fmt.Printf("field : %s\n", C.GoString(C.GraphQLAstName_get_value(C.GraphQLAstField_get_name(field)))) 31 | return 0 32 | } 33 | 34 | func parse(query string) (*C.struct_GraphQLAstNode, error) { 35 | graphql := C.CString(query) 36 | cError := (*C.char)(nil) 37 | ast := C.graphql_parse_string(graphql, &cError) 38 | C.free(unsafe.Pointer(graphql)) 39 | 40 | if ast == nil { 41 | err := errors.New(C.GoString(cError)) 42 | C.graphql_error_free(cError) 43 | return nil, err 44 | } 45 | return ast, nil 46 | } 47 | 48 | func main() { 49 | ast, err := parse("query myquery { myfield }") 50 | if err != nil { 51 | fmt.Printf("BUG: unexpected parse error: %s", err) 52 | return 53 | } 54 | visitor_callbacks := C.struct_GraphQLAstVisitorCallbacks{visit_field: (C.visit_field_func)(C.printField_cgo)} 55 | C.graphql_node_visit(ast, &visitor_callbacks, nil) 56 | 57 | C.graphql_node_free(ast) 58 | 59 | ast2, err2 := parse("query errorQuery on oops { myfield }") 60 | if err2 != nil { 61 | fmt.Printf("Example error: %s\n", err2) 62 | } 63 | if ast2 != nil { 64 | fmt.Printf("BUG: we should have got a null AST back, but we got %s\n", ast2) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /internal/ast/js.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015, Facebook, Inc. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. An additional grant 6 | # of patent rights can be found in the PATENTS file in the same directory. 7 | 8 | 9 | class Printer(object): 10 | def __init__(self): 11 | pass 12 | 13 | def start_file(self): 14 | print '''/* @flow */ 15 | /* @generated */ 16 | /* jshint ignore:start */ 17 | 18 | /** 19 | * Copyright (c) 2015, Facebook, Inc. 20 | * All rights reserved. 21 | * 22 | * This source code is licensed under the BSD-style license found in the 23 | * LICENSE file in the root directory of this source tree. An additional grant 24 | * of patent rights can be found in the PATENTS file in the same directory. 25 | */ 26 | 27 | type Node = { 28 | kind: string; 29 | start?: ?number; 30 | end?: ?number; 31 | }; 32 | 33 | type OperationKind = 'query' | 'mutation' | 'subscription';''' 34 | 35 | def end_file(self): 36 | pass 37 | 38 | def start_type(self, name): 39 | print 40 | print 'type %s = Node & {' % name 41 | kind = name 42 | if kind == 'GenericType': 43 | kind = 'Type' 44 | print ' kind: \'%s\';' % kind 45 | 46 | def end_type(self, name): 47 | print '}' 48 | 49 | def _js_type(self, type, plural): 50 | if plural: 51 | type = 'Array<%s>' % type 52 | return type 53 | 54 | def field(self, type, name, nullable, plural): 55 | nullable_char = '?' if nullable else '' 56 | js_type = self._js_type(type, plural) 57 | print ' %(name)s%(nullable_char)s: %(nullable_char)s%(js_type)s;' % locals() 58 | 59 | def start_union(self, name): 60 | print ('type %s = ' % name), 61 | self._current_options = [] 62 | 63 | def union_option(self, type): 64 | self._current_options.append(type) 65 | 66 | def end_union(self, name): 67 | print '\n | '.join(self._current_options) 68 | print 69 | self._current_options = None 70 | -------------------------------------------------------------------------------- /internal/install_manifest.txt: -------------------------------------------------------------------------------- 1 | /usr/local/include/graphqlparser/c/GraphQLAst.h 2 | /usr/local/include/graphqlparser/c/GraphQLAstForEachConcreteType.h 3 | /usr/local/include/graphqlparser/c/GraphQLAstNode.h 4 | /usr/local/include/graphqlparser/c/GraphQLAstToJSON.h 5 | /usr/local/include/graphqlparser/c/GraphQLAstVisitor.h 6 | /usr/local/include/graphqlparser/c/GraphQLParser.h 7 | /usr/local/include/graphqlparser/libgraphqlparser/Ast.h 8 | /usr/local/include/graphqlparser/libgraphqlparser/AstNode.h 9 | /usr/local/include/graphqlparser/libgraphqlparser/AstVisitor.h 10 | /usr/local/include/graphqlparser/libgraphqlparser/c/GraphQLAst.h 11 | /usr/local/include/graphqlparser/libgraphqlparser/c/GraphQLAstForEachConcreteType.h 12 | /usr/local/include/graphqlparser/libgraphqlparser/c/GraphQLAstNode.h 13 | /usr/local/include/graphqlparser/libgraphqlparser/c/GraphQLAstToJSON.h 14 | /usr/local/include/graphqlparser/libgraphqlparser/c/GraphQLAstVisitor.h 15 | /usr/local/include/graphqlparser/libgraphqlparser/c/GraphQLParser.h 16 | /usr/local/include/graphqlparser/libgraphqlparser/GraphQLParser.h 17 | /usr/local/include/graphqlparser/libgraphqlparser/JsonVisitor.h 18 | /usr/local/include/graphqlparser/libgraphqlparser/lexer.h 19 | /usr/local/include/graphqlparser/libgraphqlparser/syntaxdefs.h 20 | /usr/local/include/graphqlparser/c/GraphQLAst.h 21 | /usr/local/include/graphqlparser/c/GraphQLAstForEachConcreteType.h 22 | /usr/local/include/graphqlparser/c/GraphQLAstNode.h 23 | /usr/local/include/graphqlparser/c/GraphQLAstToJSON.h 24 | /usr/local/include/graphqlparser/c/GraphQLAstVisitor.h 25 | /usr/local/include/graphqlparser/c/GraphQLParser.h 26 | /usr/local/include/graphqlparser/AstNode.h 27 | /usr/local/include/graphqlparser/GraphQLParser.h 28 | /usr/local/include/graphqlparser/JsonVisitor.h 29 | /usr/local/include/graphqlparser/lexer.h 30 | /usr/local/include/graphqlparser/location.hh 31 | /usr/local/include/graphqlparser/parser.tab.hpp 32 | /usr/local/include/graphqlparser/position.hh 33 | /usr/local/include/graphqlparser/stack.hh 34 | /usr/local/include/graphqlparser/syntaxdefs.h 35 | /usr/local/lib/libgraphqlparser.so -------------------------------------------------------------------------------- /internal/PATENTS: -------------------------------------------------------------------------------- 1 | Additional Grant of Patent Rights Version 2 2 | 3 | "Software" means libgraphqlparser distributed by Facebook, Inc. 4 | 5 | Facebook, Inc. ("Facebook") hereby grants to each recipient of the Software 6 | ("you") a perpetual, worldwide, royalty-free, non-exclusive, irrevocable 7 | (subject to the termination provision below) license under any Necessary 8 | Claims, to make, have made, use, sell, offer to sell, import, and otherwise 9 | transfer the Software. For avoidance of doubt, no license is granted under 10 | Facebook’s rights in any patent claims that are infringed by (i) modifications 11 | to the Software made by you or any third party or (ii) the Software in 12 | combination with any software or other technology. 13 | 14 | The license granted hereunder will terminate, automatically and without notice, 15 | if you (or any of your subsidiaries, corporate affiliates or agents) initiate 16 | directly or indirectly, or take a direct financial interest in, any Patent 17 | Assertion: (i) against Facebook or any of its subsidiaries or corporate 18 | affiliates, (ii) against any party if such Patent Assertion arises in whole or 19 | in part from any software, technology, product or service of Facebook or any of 20 | its subsidiaries or corporate affiliates, or (iii) against any party relating 21 | to the Software. Notwithstanding the foregoing, if Facebook or any of its 22 | subsidiaries or corporate affiliates files a lawsuit alleging patent 23 | infringement against you in the first instance, and you respond by filing a 24 | patent infringement counterclaim in that lawsuit against that party that is 25 | unrelated to the Software, the license granted hereunder will not terminate 26 | under section (i) of this paragraph due to such counterclaim. 27 | 28 | A "Necessary Claim" is a claim of a patent owned by Facebook that is 29 | necessarily infringed by the Software standing alone. 30 | 31 | A "Patent Assertion" is any lawsuit or other action alleging direct, indirect, 32 | or contributory infringement or inducement to infringe any patent, including a 33 | cross-claim or counterclaim. 34 | -------------------------------------------------------------------------------- /internal/c/GraphQLAstVisitor.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #pragma once 11 | 12 | #include "c/GraphQLAst.h" 13 | #include "c/GraphQLAstForEachConcreteType.h" 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | #define TYPEDEFS(type, snake_type) \ 20 | typedef int (*visit_##snake_type##_func)(const struct GraphQLAst##type *snake_type, void *user_data); \ 21 | typedef void (*end_visit_##snake_type##_func)(const struct GraphQLAst##type *snake_type, void *user_data); 22 | 23 | FOR_EACH_CONCRETE_TYPE(TYPEDEFS) 24 | 25 | #define FUNC_MEMBER(type, snake_type) \ 26 | visit_##snake_type##_func visit_##snake_type; \ 27 | end_visit_##snake_type##_func end_visit_##snake_type; 28 | /** 29 | * Functions to be called when particular AST nodes are encountered. 30 | * visit_* functions are called in pre-order, and may return non-zero to 31 | * continue recursing into children (if any), or zero to skip them. end_visit_* 32 | * functions are called in post-order. Any particular function may be set to 33 | * NULL to indicate that the caller is not interested in the corresponding type 34 | * of AST node. (NULL visit_* functions act as though they simply returned 35 | * non-zero.) 36 | */ 37 | struct GraphQLAstVisitorCallbacks { 38 | FOR_EACH_CONCRETE_TYPE(FUNC_MEMBER) 39 | }; 40 | 41 | struct GraphQLAstNode; 42 | 43 | /** 44 | * Walk the AST rooted at the given node, issuing callbacks from the given 45 | * callbacks struct as appropriate. userData will be passed as the userData 46 | * argument to each callback. 47 | */ 48 | void graphql_node_visit(struct GraphQLAstNode *node, 49 | const struct GraphQLAstVisitorCallbacks *callbacks, 50 | void *userData); 51 | 52 | #ifdef __cplusplus 53 | } 54 | #endif 55 | 56 | -------------------------------------------------------------------------------- /internal/ast/ast.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) 2015, Facebook, Inc. 3 | # All rights reserved. 4 | # 5 | # This source code is licensed under the BSD-style license found in the 6 | # LICENSE file in the root directory of this source tree. An additional grant 7 | # of patent rights can be found in the PATENTS file in the same directory. 8 | 9 | from importlib import import_module 10 | 11 | def load_lang(lang): 12 | return import_module(lang).Printer() 13 | 14 | 15 | def print_ast(lang_module, input_file): 16 | lang_module.start_file() 17 | line = input_file.readline() 18 | while line: 19 | line = line.strip() 20 | if line.startswith('#') or not line: 21 | line = input_file.readline() 22 | continue 23 | 24 | code, rest = line.split(None, 1) 25 | if code[0] == 'T': 26 | lang_module.start_type(rest) 27 | field_line = input_file.readline().strip() 28 | while field_line: 29 | if field_line.startswith('#'): 30 | field_line = input_file.readline().strip() 31 | continue 32 | field_kind, field_type, field_name = field_line.split() 33 | nullable = len(field_kind) > 1 and field_kind[1] == '?' 34 | if field_kind[0] == 'S': 35 | plural = False 36 | elif field_kind[0] == 'P': 37 | plural = True 38 | else: 39 | raise Error('Unknown field kind: ' + field_kind) 40 | lang_module.field(field_type, field_name, nullable, plural) 41 | field_line = input_file.readline().strip() 42 | lang_module.end_type(rest) 43 | elif code[0] == 'U': 44 | lang_module.start_union(rest) 45 | field_line = input_file.readline().strip() 46 | while field_line: 47 | option_code, option_type = field_line.split() 48 | if option_code != 'O': 49 | raise Error('Unknown code in union: ' + option_code) 50 | lang_module.union_option(option_type) 51 | field_line = input_file.readline().strip() 52 | lang_module.end_union(rest) 53 | line = input_file.readline() 54 | 55 | lang_module.end_file() 56 | if __name__ == '__main__': 57 | import sys 58 | lang = sys.argv[1] 59 | filename = sys.argv[2] 60 | 61 | lang_module = load_lang(lang) 62 | 63 | print_ast(lang_module, open(filename, 'r')) 64 | -------------------------------------------------------------------------------- /internal/c/GraphQLAstVisitor.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #include "c/GraphQLAstVisitor.h" 11 | #include "AstVisitor.h" 12 | 13 | using namespace facebook::graphql::ast; 14 | 15 | #include "c/GraphQLAstForEachConcreteType.h" 16 | 17 | #define DECLARE_VISIT(type, snake_type) \ 18 | bool visit##type(const type &node) override; \ 19 | void endVisit##type(const type &node) override; 20 | 21 | class CVisitorBridge : public visitor::AstVisitor { 22 | const struct GraphQLAstVisitorCallbacks *callbacks_; 23 | void *userData_; 24 | public: 25 | explicit CVisitorBridge(const struct GraphQLAstVisitorCallbacks *callbacks, 26 | void *userData) 27 | : callbacks_(callbacks), userData_(userData) {} 28 | 29 | ~CVisitorBridge() {} 30 | 31 | FOR_EACH_CONCRETE_TYPE(DECLARE_VISIT) 32 | }; 33 | 34 | #define IMPLEMENT_VISIT(type, snake_type) \ 35 | bool CVisitorBridge::visit##type(const type &node) { \ 36 | if (callbacks_->visit_##snake_type) { \ 37 | return callbacks_->visit_##snake_type( \ 38 | (const struct GraphQLAst##type *)&node, userData_); \ 39 | } \ 40 | return true; \ 41 | } \ 42 | void CVisitorBridge::endVisit##type(const type &node) { \ 43 | if (callbacks_->end_visit_##snake_type) { \ 44 | callbacks_->end_visit_##snake_type( \ 45 | (const struct GraphQLAst##type *)&node, userData_); \ 46 | } \ 47 | } 48 | 49 | FOR_EACH_CONCRETE_TYPE(IMPLEMENT_VISIT) 50 | 51 | void graphql_node_visit(struct GraphQLAstNode *node, 52 | const struct GraphQLAstVisitorCallbacks *callbacks, 53 | void *userData) 54 | { 55 | CVisitorBridge visitor(callbacks, userData); 56 | if (node) { 57 | ((facebook::graphql::ast::Node *)node)->accept(&visitor); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /internal/ast/ast.ast: -------------------------------------------------------------------------------- 1 | # Mini-language for AST definition. 2 | # All AST nodes extend AstNode. 3 | # All AST nodes are visitible. 4 | # All AST fields have a getter and a setter and are a constructor argument. 5 | # We have concrete types (code T) and unions (code U). 6 | # S for singular field, P for plural, ? for nullable. 7 | # O for option in a union. 8 | # Scalar type ontology: string, boolean 9 | 10 | # Location tracking for Identifier is probably useful for error messages. 11 | U Definition 12 | O OperationDefinition 13 | O FragmentDefinition 14 | 15 | T Document 16 | P Definition definitions 17 | 18 | T OperationDefinition 19 | S OperationKind operation 20 | S? Name name 21 | P? VariableDefinition variableDefinitions 22 | P? Directive directives 23 | S SelectionSet selectionSet 24 | 25 | T VariableDefinition 26 | S Variable variable 27 | S Type type 28 | S? Value defaultValue 29 | 30 | T SelectionSet 31 | P Selection selections 32 | 33 | U Selection 34 | O Field 35 | O FragmentSpread 36 | O InlineFragment 37 | 38 | T Field 39 | S? Name alias 40 | S Name name 41 | P? Argument arguments 42 | P? Directive directives 43 | S? SelectionSet selectionSet 44 | 45 | T Argument 46 | S Name name 47 | S Value value 48 | 49 | T FragmentSpread 50 | S Name name 51 | P? Directive directives 52 | 53 | T InlineFragment 54 | S NamedType typeCondition 55 | P? Directive directives 56 | S SelectionSet selectionSet 57 | 58 | T FragmentDefinition 59 | S Name name 60 | S NamedType typeCondition 61 | P? Directive directives 62 | S SelectionSet selectionSet 63 | 64 | U Value 65 | O Variable 66 | O IntValue 67 | O FloatValue 68 | O StringValue 69 | O BooleanValue 70 | O EnumValue 71 | O ArrayValue 72 | O ObjectValue 73 | 74 | T Variable 75 | S Name name 76 | 77 | T IntValue 78 | S string value 79 | 80 | T FloatValue 81 | S string value 82 | 83 | T StringValue 84 | S string value 85 | 86 | T BooleanValue 87 | S boolean value 88 | 89 | T EnumValue 90 | S string value 91 | 92 | T ArrayValue 93 | P Value values 94 | 95 | T ObjectValue 96 | P ObjectField fields 97 | 98 | T ObjectField 99 | S Name name 100 | S Value value 101 | 102 | T Directive 103 | S Name name 104 | P? Argument arguments 105 | 106 | U Type 107 | O NamedType 108 | O ListType 109 | O NonNullType 110 | 111 | T NamedType 112 | S Name name 113 | 114 | T ListType 115 | S Type type 116 | 117 | T NonNullType 118 | # JS version prohibits nesting nonnull in nonnull, we can't because we 119 | # can't support multiple unions. Fix? 120 | S Type type 121 | 122 | T Name 123 | S string value 124 | -------------------------------------------------------------------------------- /internal/README.md: -------------------------------------------------------------------------------- 1 | # libgraphqlparser 2 | 3 | libgraphqlparser is a parser for 4 | [GraphQL](http://facebook.github.io/graphql/), a query language 5 | created by Facebook for describing data requirements on complex 6 | application data models, implemented in C++11. It can be used on its 7 | own in C++ code (or in C code via the pure C API defined in the `c` 8 | subdirectory), or you can use it as the basis for an extension module 9 | for your favorite programming language instead of writing your own 10 | parser from scratch. 11 | 12 | ## Example 13 | 14 | The provided `dump_json_ast` is a simple program that reads GraphQL 15 | text on stdin and prints a JSON representation of the AST to stdout. 16 | 17 | The `python` subdirectory contains an example Python binding for the 18 | pure C API. 19 | 20 | ## Requirements 21 | 22 | libgraphqlparser requires a C++ compiler that supports C++11. It 23 | also requires Mac OS X or Linux. 24 | 25 | To run tests, please download googletest from 26 | https://googletest.googlecode.com/files/gtest-1.7.0.zip and unzip it 27 | in the `test` subdirectory. 28 | 29 | ## Building libgraphqlparser 30 | 31 | libgraphqlparser is built with [CMake](http://www.cmake.org/). If a 32 | sufficiently-recent version of [Flex](http://flex.sourceforge.net/) and [Bison](http://www.gnu.org/software/bison/) are installed on your 33 | system, it will use them; otherwise, it will rely on the checked-in 34 | `parser.tab.{c,h}pp` and `lexer.{h,cpp}`. 35 | 36 | ## How libgraphqlparser works 37 | 38 | libgraphqlparser uses flex and bison to generate a C++ parser for 39 | GraphQL. These tools work well but have idiosyncratic interfaces by 40 | modern standards, so GraphQLParser.h provides a simple interface to 41 | parse GraphQL. 42 | 43 | In order to make it simpler to write code based around the GraphQL 44 | AST, libgraphqlparser includes an extremely simple code generation 45 | framework in the `ast/` subdirectory. This framework is used to build 46 | the AST classes themselves, as well as a visitor over the AST. It may 47 | be easier to understand the output of the generation steps directly 48 | (i.e., Ast.h, Ast.cpp, and AstVisitor.h) rather than trying to read 49 | the generation scripts. Simply building libgraphqlparser will cause 50 | these files to be generated. 51 | 52 | libgraphqlparser also uses the AST generation framework to build a 53 | pure C API in the `c` subdirectory. This API can be used from C code, 54 | and it should also simplify the task of creating bindings to other 55 | programming languages. 56 | 57 | ## License 58 | libgraphqlparser is BSD-licensed. We also provide an additional patent grant. 59 | 60 | ## Related Projects 61 | 62 | - [graphql-parser (Ruby interface)](https://github.com/Shopify/graphql-parser) 63 | - [py-graphqlparser (Python interface)](https://github.com/elastic-coders/py-graphqlparser) 64 | -------------------------------------------------------------------------------- /internal/ast/c.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015, Facebook, Inc. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. An additional grant 6 | # of patent rights can be found in the PATENTS file in the same directory. 7 | 8 | from casing import snake 9 | 10 | from license import C_LICENSE_COMMENT 11 | 12 | def struct_name(type): 13 | return 'GraphQLAst' + type 14 | 15 | 16 | def return_type(type): 17 | if type == 'OperationKind' or type == 'string': 18 | return 'const char *' 19 | 20 | if type == 'boolean': 21 | return 'int' 22 | 23 | return 'const struct %s *' % struct_name(type) 24 | 25 | 26 | def field_prototype(owning_type, type, name, nullable, plural): 27 | st_name = struct_name(owning_type) 28 | if plural: 29 | return 'int %s_get_%s_size(const struct %s *node)' % ( 30 | st_name, snake(name), st_name) 31 | else: 32 | ret_type = return_type(type) 33 | return '%s %s_get_%s(const struct %s *node)' % ( 34 | ret_type, st_name, snake(name), st_name) 35 | 36 | 37 | class Printer(object): 38 | '''Printer for the pure C interface to the AST. 39 | 40 | Merely a set of wrappers around the C++ interface; makes it possible 41 | to use the AST from C code and simplifies the task of writing 42 | bindings for other langugages. 43 | 44 | The mapping is as follows: 45 | 46 | - For each concrete type, you get an opaque C struct type, 47 | accessible only by pointer. 48 | 49 | - For each singular field of a concrete type, you get an accessor 50 | function, returning said field in the obvious way. 51 | 52 | - For each plural field of a concrete type, you get an accessor 53 | function telling you its size. For access to elements of a plural 54 | field, you can use the visitor API. 55 | 56 | - For each union type, you get nothing specific (REVIEW), but you 57 | can use the visitor API to work around this entirely. 58 | 59 | ''' 60 | 61 | def __init__(self): 62 | self._current_type = None 63 | 64 | def start_file(self): 65 | print C_LICENSE_COMMENT + '''/** @generated */ 66 | 67 | #pragma once 68 | 69 | #ifdef __cplusplus 70 | extern "C" { 71 | #endif 72 | 73 | ''' 74 | 75 | def end_file(self): 76 | print ''' 77 | 78 | #ifdef __cplusplus 79 | } 80 | #endif 81 | ''' 82 | 83 | def start_type(self, name): 84 | # Forward declarations for AST nodes. 85 | st_name = struct_name(name) 86 | print 'struct ' + st_name + ';' 87 | self._current_type = name 88 | 89 | def field(self, type, name, nullable, plural): 90 | print field_prototype(self._current_type, type, name, nullable, plural) + ';' 91 | 92 | def end_type(self, name): 93 | print 94 | 95 | def start_union(self, name): 96 | print 'struct ' + struct_name(name) + ';' 97 | 98 | def union_option(self, option): 99 | pass 100 | 101 | def end_union(self, name): 102 | print 103 | -------------------------------------------------------------------------------- /internal/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8) 2 | PROJECT(libgraphqlparser C CXX) 3 | 4 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11") 5 | 6 | FIND_PACKAGE(PythonInterp) 7 | IF (NOT PYTHON_VERSION_MAJOR EQUAL 2) 8 | MESSAGE(FATAL_ERROR "Python 2 is required.") 9 | ENDIF() 10 | 11 | FIND_PROGRAM(CTYPESGEN_FOUND ctypesgen.py) 12 | 13 | FIND_PACKAGE(BISON 3) 14 | FIND_PACKAGE(FLEX) 15 | IF (BISON_FOUND) 16 | BISON_TARGET(graphqlparser parser.ypp ${CMAKE_CURRENT_SOURCE_DIR}/parser.tab.cpp) 17 | ENDIF() 18 | 19 | IF(FLEX_FOUND) 20 | FLEX_TARGET(GraphQLScanner lexer.lpp ${CMAKE_CURRENT_SOURCE_DIR}/lexer.cpp COMPILE_FLAGS "--header-file=lexer.h") 21 | IF (BISON_FOUND) 22 | ADD_FLEX_BISON_DEPENDENCY(GraphQLScanner graphqlparser) 23 | ENDIF() 24 | ENDIF() 25 | 26 | FILE(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/c) 27 | INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) 28 | INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) 29 | 30 | ADD_LIBRARY(graphqlparser SHARED 31 | JsonVisitor.cpp 32 | ${CMAKE_CURRENT_BINARY_DIR}/Ast.h 33 | ${CMAKE_CURRENT_BINARY_DIR}/Ast.cpp 34 | ${CMAKE_CURRENT_BINARY_DIR}/AstVisitor.h 35 | ${CMAKE_CURRENT_BINARY_DIR}/c/GraphQLAst.h 36 | ${CMAKE_CURRENT_BINARY_DIR}/c/GraphQLAst.cpp 37 | ${CMAKE_CURRENT_BINARY_DIR}/c/GraphQLAstForEachConcreteType.h 38 | c/GraphQLAstNode.cpp 39 | c/GraphQLAstToJSON.cpp 40 | c/GraphQLAstVisitor.h 41 | c/GraphQLAstVisitor.cpp 42 | c/GraphQLParser.cpp 43 | parser.tab.hpp 44 | parser.tab.cpp 45 | lexer.cpp 46 | lexer.h 47 | GraphQLParser.cpp) 48 | 49 | # Enable this and remove CMAKE_CXX_FLAGS fiddle above when we are able 50 | # to upgrade to CMake 2.8.12. Blocker seems to be Travis CI being on 51 | # Ubuntu Precise; Trusty has 2.8.12. 52 | # TARGET_COMPILE_OPTIONS(graphqlparser PUBLIC -std=gnu++11) 53 | 54 | ADD_EXECUTABLE(dump_json_ast dump_json_ast.cpp) 55 | TARGET_LINK_LIBRARIES(dump_json_ast graphqlparser) 56 | 57 | FUNCTION(GENERATE_AST_FILE FILE_TYPE FILE_RELATIVE_PATH) 58 | ADD_CUSTOM_COMMAND( 59 | OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${FILE_RELATIVE_PATH} 60 | COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/ast/ast.py ${FILE_TYPE} ${CMAKE_CURRENT_SOURCE_DIR}/ast/ast.ast > ${CMAKE_CURRENT_BINARY_DIR}/${FILE_RELATIVE_PATH} 61 | DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/ast/ast.ast ${CMAKE_CURRENT_SOURCE_DIR}/ast/ast.py) 62 | ENDFUNCTION(GENERATE_AST_FILE) 63 | 64 | GENERATE_AST_FILE(cxx Ast.h) 65 | 66 | GENERATE_AST_FILE(cxx_visitor AstVisitor.h) 67 | 68 | GENERATE_AST_FILE(cxx_impl Ast.cpp) 69 | 70 | GENERATE_AST_FILE(c c/GraphQLAst.h) 71 | 72 | GENERATE_AST_FILE(c_impl c/GraphQLAst.cpp) 73 | 74 | GENERATE_AST_FILE(c_visitor_impl c/GraphQLAstForEachConcreteType.h) 75 | 76 | ADD_SUBDIRECTORY(python) 77 | 78 | OPTION(test "Build tests." OFF) 79 | 80 | INSTALL(DIRECTORY c ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/c DESTINATION include/graphqlparser 81 | FILES_MATCHING PATTERN "*.h" 82 | PATTERN "build" EXCLUDE) 83 | 84 | INSTALL(FILES 85 | AstNode.h 86 | GraphQLParser.h 87 | JsonVisitor.h 88 | lexer.h 89 | location.hh 90 | parser.tab.hpp 91 | position.hh 92 | stack.hh 93 | syntaxdefs.h 94 | DESTINATION include/graphqlparser) 95 | INSTALL(TARGETS graphqlparser 96 | LIBRARY DESTINATION lib) 97 | 98 | IF (test) 99 | ADD_SUBDIRECTORY(test) 100 | ENDIF() 101 | -------------------------------------------------------------------------------- /internal/stack.hh: -------------------------------------------------------------------------------- 1 | // A Bison parser, made by GNU Bison 3.0.4. 2 | 3 | // Stack handling for Bison parsers in C++ 4 | 5 | // Copyright (C) 2002-2015 Free Software Foundation, Inc. 6 | 7 | // This program is free software: you can redistribute it and/or modify 8 | // it under the terms of the GNU General Public License as published by 9 | // the Free Software Foundation, either version 3 of the License, or 10 | // (at your option) any later version. 11 | 12 | // This program is distributed in the hope that it will be useful, 13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | // GNU General Public License for more details. 16 | 17 | // You should have received a copy of the GNU General Public License 18 | // along with this program. If not, see . 19 | 20 | // As a special exception, you may create a larger work that contains 21 | // part or all of the Bison parser skeleton and distribute that work 22 | // under terms of your choice, so long as that work isn't itself a 23 | // parser generator using the skeleton or a modified version thereof 24 | // as a parser skeleton. Alternatively, if you modify or redistribute 25 | // the parser skeleton itself, you may (at your option) remove this 26 | // special exception, which will cause the skeleton and the resulting 27 | // Bison output files to be licensed under the GNU General Public 28 | // License without this special exception. 29 | 30 | // This special exception was added by the Free Software Foundation in 31 | // version 2.2 of Bison. 32 | 33 | /** 34 | ** \file stack.hh 35 | ** Define the yy::stack class. 36 | */ 37 | 38 | #ifndef YY_YY_STACK_HH_INCLUDED 39 | # define YY_YY_STACK_HH_INCLUDED 40 | 41 | # include 42 | 43 | 44 | namespace yy { 45 | #line 46 "stack.hh" // stack.hh:151 46 | template > 47 | class stack 48 | { 49 | public: 50 | // Hide our reversed order. 51 | typedef typename S::reverse_iterator iterator; 52 | typedef typename S::const_reverse_iterator const_iterator; 53 | 54 | stack () 55 | : seq_ () 56 | { 57 | seq_.reserve (200); 58 | } 59 | 60 | stack (unsigned int n) 61 | : seq_ (n) 62 | {} 63 | 64 | inline 65 | T& 66 | operator[] (unsigned int i) 67 | { 68 | return seq_[seq_.size () - 1 - i]; 69 | } 70 | 71 | inline 72 | const T& 73 | operator[] (unsigned int i) const 74 | { 75 | return seq_[seq_.size () - 1 - i]; 76 | } 77 | 78 | /// Steal the contents of \a t. 79 | /// 80 | /// Close to move-semantics. 81 | inline 82 | void 83 | push (T& t) 84 | { 85 | seq_.push_back (T()); 86 | operator[](0).move (t); 87 | } 88 | 89 | inline 90 | void 91 | pop (unsigned int n = 1) 92 | { 93 | for (; n; --n) 94 | seq_.pop_back (); 95 | } 96 | 97 | void 98 | clear () 99 | { 100 | seq_.clear (); 101 | } 102 | 103 | inline 104 | typename S::size_type 105 | size () const 106 | { 107 | return seq_.size (); 108 | } 109 | 110 | inline 111 | const_iterator 112 | begin () const 113 | { 114 | return seq_.rbegin (); 115 | } 116 | 117 | inline 118 | const_iterator 119 | end () const 120 | { 121 | return seq_.rend (); 122 | } 123 | 124 | private: 125 | stack (const stack&); 126 | stack& operator= (const stack&); 127 | /// The wrapped container. 128 | S seq_; 129 | }; 130 | 131 | /// Present a slice of the top of a stack. 132 | template > 133 | class slice 134 | { 135 | public: 136 | slice (const S& stack, unsigned int range) 137 | : stack_ (stack) 138 | , range_ (range) 139 | {} 140 | 141 | inline 142 | const T& 143 | operator [] (unsigned int i) const 144 | { 145 | return stack_[range_ - i]; 146 | } 147 | 148 | private: 149 | const S& stack_; 150 | unsigned int range_; 151 | }; 152 | 153 | 154 | } // yy 155 | #line 156 "stack.hh" // stack.hh:151 156 | 157 | #endif // !YY_YY_STACK_HH_INCLUDED 158 | -------------------------------------------------------------------------------- /internal/AstVisitor.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | /** @generated */ 10 | 11 | #pragma once 12 | 13 | #include "Ast.h" 14 | 15 | namespace facebook { 16 | namespace graphql { 17 | namespace ast { 18 | namespace visitor { 19 | 20 | class AstVisitor { 21 | public: 22 | virtual ~AstVisitor() {} 23 | 24 | virtual bool visitDocument(const Document &document) { return true; } 25 | virtual void endVisitDocument(const Document &document) { } 26 | 27 | virtual bool visitOperationDefinition(const OperationDefinition &operationDefinition) { return true; } 28 | virtual void endVisitOperationDefinition(const OperationDefinition &operationDefinition) { } 29 | 30 | virtual bool visitVariableDefinition(const VariableDefinition &variableDefinition) { return true; } 31 | virtual void endVisitVariableDefinition(const VariableDefinition &variableDefinition) { } 32 | 33 | virtual bool visitSelectionSet(const SelectionSet &selectionSet) { return true; } 34 | virtual void endVisitSelectionSet(const SelectionSet &selectionSet) { } 35 | 36 | virtual bool visitField(const Field &field) { return true; } 37 | virtual void endVisitField(const Field &field) { } 38 | 39 | virtual bool visitArgument(const Argument &argument) { return true; } 40 | virtual void endVisitArgument(const Argument &argument) { } 41 | 42 | virtual bool visitFragmentSpread(const FragmentSpread &fragmentSpread) { return true; } 43 | virtual void endVisitFragmentSpread(const FragmentSpread &fragmentSpread) { } 44 | 45 | virtual bool visitInlineFragment(const InlineFragment &inlineFragment) { return true; } 46 | virtual void endVisitInlineFragment(const InlineFragment &inlineFragment) { } 47 | 48 | virtual bool visitFragmentDefinition(const FragmentDefinition &fragmentDefinition) { return true; } 49 | virtual void endVisitFragmentDefinition(const FragmentDefinition &fragmentDefinition) { } 50 | 51 | virtual bool visitVariable(const Variable &variable) { return true; } 52 | virtual void endVisitVariable(const Variable &variable) { } 53 | 54 | virtual bool visitIntValue(const IntValue &intValue) { return true; } 55 | virtual void endVisitIntValue(const IntValue &intValue) { } 56 | 57 | virtual bool visitFloatValue(const FloatValue &floatValue) { return true; } 58 | virtual void endVisitFloatValue(const FloatValue &floatValue) { } 59 | 60 | virtual bool visitStringValue(const StringValue &stringValue) { return true; } 61 | virtual void endVisitStringValue(const StringValue &stringValue) { } 62 | 63 | virtual bool visitBooleanValue(const BooleanValue &booleanValue) { return true; } 64 | virtual void endVisitBooleanValue(const BooleanValue &booleanValue) { } 65 | 66 | virtual bool visitEnumValue(const EnumValue &enumValue) { return true; } 67 | virtual void endVisitEnumValue(const EnumValue &enumValue) { } 68 | 69 | virtual bool visitArrayValue(const ArrayValue &arrayValue) { return true; } 70 | virtual void endVisitArrayValue(const ArrayValue &arrayValue) { } 71 | 72 | virtual bool visitObjectValue(const ObjectValue &objectValue) { return true; } 73 | virtual void endVisitObjectValue(const ObjectValue &objectValue) { } 74 | 75 | virtual bool visitObjectField(const ObjectField &objectField) { return true; } 76 | virtual void endVisitObjectField(const ObjectField &objectField) { } 77 | 78 | virtual bool visitDirective(const Directive &directive) { return true; } 79 | virtual void endVisitDirective(const Directive &directive) { } 80 | 81 | virtual bool visitNamedType(const NamedType &namedType) { return true; } 82 | virtual void endVisitNamedType(const NamedType &namedType) { } 83 | 84 | virtual bool visitListType(const ListType &listType) { return true; } 85 | virtual void endVisitListType(const ListType &listType) { } 86 | 87 | virtual bool visitNonNullType(const NonNullType &nonNullType) { return true; } 88 | virtual void endVisitNonNullType(const NonNullType &nonNullType) { } 89 | 90 | virtual bool visitName(const Name &name) { return true; } 91 | virtual void endVisitName(const Name &name) { } 92 | 93 | }; 94 | 95 | } 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /internal/JsonVisitor.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #pragma once 11 | 12 | #include "AstNode.h" 13 | #include "AstVisitor.h" 14 | 15 | #include 16 | #include 17 | 18 | namespace facebook { 19 | namespace graphql { 20 | namespace ast { 21 | namespace visitor { 22 | 23 | /** 24 | * Produces a JSON string describing the visited AST, in a format that 25 | * would be a valid graphql-js AST when parsed. 26 | */ 27 | class JsonVisitor : public AstVisitor { 28 | // Stack of lists of printed children. 29 | // Postvisit method precondition: printed.back() contains strings 30 | // for this node's children. 31 | // Postvisit method postcondition: *(printed.rbegin() - 1) has had this 32 | std::vector> printed_; 33 | std::ostringstream out_; 34 | 35 | // Print the opening of a new JSON dictionary, the node kind, and 36 | // the node location. 37 | void startPrintingNode(const char *kind, const yy::location &location); 38 | 39 | void printLocation(const yy::location &location); 40 | 41 | // Must be called at the start of all visit methods for node types 42 | // that have children. Maintains printed_. 43 | void visitNode(); 44 | 45 | // Must be called at the end of all visit methods for node types 46 | // that have children. Maintains printed_. 47 | void endVisitNode(); 48 | 49 | // Prints a non-null array of n children from the given 50 | // iterator. Does not update the iterator. 51 | void printChildArray( 52 | const std::vector::const_iterator &childIterator, 53 | size_t numChildren); 54 | 55 | // Prints one of the many FooValue types that is prepresented with a 56 | // single string. 57 | template 58 | void endVisitValueRepresentedAsString(const char *valueKind, const ValueType &value); 59 | 60 | public: 61 | JsonVisitor() {} 62 | ~JsonVisitor() {} 63 | 64 | std::string getResult() const { 65 | return out_.str(); 66 | } 67 | 68 | bool visitDocument(const Document &document) override; 69 | void endVisitDocument(const Document &document) override; 70 | 71 | bool visitOperationDefinition(const OperationDefinition &operationDefinition) override; 72 | void endVisitOperationDefinition(const OperationDefinition &operationDefinition) override; 73 | 74 | bool visitVariableDefinition(const VariableDefinition &variableDefinition) override; 75 | void endVisitVariableDefinition(const VariableDefinition &variableDefinition) override; 76 | 77 | bool visitSelectionSet(const SelectionSet &selectionSet) override; 78 | void endVisitSelectionSet(const SelectionSet &selectionSet) override; 79 | 80 | bool visitField(const Field &field) override; 81 | void endVisitField(const Field &field) override; 82 | 83 | bool visitArgument(const Argument &argument) override; 84 | void endVisitArgument(const Argument &argument) override; 85 | 86 | bool visitFragmentSpread(const FragmentSpread &fragmentSpread) override; 87 | void endVisitFragmentSpread(const FragmentSpread &fragmentSpread) override; 88 | 89 | bool visitInlineFragment(const InlineFragment &inlineFragment) override; 90 | void endVisitInlineFragment(const InlineFragment &inlineFragment) override; 91 | 92 | bool visitFragmentDefinition(const FragmentDefinition &fragmentDefinition) override; 93 | void endVisitFragmentDefinition(const FragmentDefinition &fragmentDefinition) override; 94 | 95 | bool visitVariable(const Variable &variable) override; 96 | void endVisitVariable(const Variable &variable) override; 97 | 98 | void endVisitIntValue(const IntValue &intValue) override; 99 | 100 | void endVisitFloatValue(const FloatValue &floatValue) override; 101 | 102 | void endVisitStringValue(const StringValue &stringValue) override; 103 | 104 | void endVisitBooleanValue(const BooleanValue &booleanValue) override; 105 | 106 | void endVisitEnumValue(const EnumValue &enumValue) override; 107 | 108 | bool visitArrayValue(const ArrayValue &arrayValue) override; 109 | void endVisitArrayValue(const ArrayValue &arrayValue) override; 110 | 111 | bool visitObjectValue(const ObjectValue &objectValue) override; 112 | void endVisitObjectValue(const ObjectValue &objectValue) override; 113 | 114 | bool visitObjectField(const ObjectField &objectField) override; 115 | void endVisitObjectField(const ObjectField &objectField) override; 116 | 117 | bool visitDirective(const Directive &directive) override; 118 | void endVisitDirective(const Directive &directive) override; 119 | 120 | void endVisitName(const Name &name) override; 121 | 122 | bool visitNamedType(const NamedType &namedType) override; 123 | void endVisitNamedType(const NamedType &namedType) override; 124 | 125 | bool visitListType(const ListType &listType) override; 126 | void endVisitListType(const ListType &listType) override; 127 | 128 | bool visitNonNullType(const NonNullType &nonNullType) override; 129 | void endVisitNonNullType(const NonNullType &nonNullType) override; 130 | 131 | }; 132 | 133 | } 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /internal/position.hh: -------------------------------------------------------------------------------- 1 | // A Bison parser, made by GNU Bison 3.0.4. 2 | 3 | // Positions for Bison parsers in C++ 4 | 5 | // Copyright (C) 2002-2015 Free Software Foundation, Inc. 6 | 7 | // This program is free software: you can redistribute it and/or modify 8 | // it under the terms of the GNU General Public License as published by 9 | // the Free Software Foundation, either version 3 of the License, or 10 | // (at your option) any later version. 11 | 12 | // This program is distributed in the hope that it will be useful, 13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | // GNU General Public License for more details. 16 | 17 | // You should have received a copy of the GNU General Public License 18 | // along with this program. If not, see . 19 | 20 | // As a special exception, you may create a larger work that contains 21 | // part or all of the Bison parser skeleton and distribute that work 22 | // under terms of your choice, so long as that work isn't itself a 23 | // parser generator using the skeleton or a modified version thereof 24 | // as a parser skeleton. Alternatively, if you modify or redistribute 25 | // the parser skeleton itself, you may (at your option) remove this 26 | // special exception, which will cause the skeleton and the resulting 27 | // Bison output files to be licensed under the GNU General Public 28 | // License without this special exception. 29 | 30 | // This special exception was added by the Free Software Foundation in 31 | // version 2.2 of Bison. 32 | 33 | /** 34 | ** \file position.hh 35 | ** Define the yy::position class. 36 | */ 37 | 38 | #ifndef YY_YY_POSITION_HH_INCLUDED 39 | # define YY_YY_POSITION_HH_INCLUDED 40 | 41 | # include // std::max 42 | # include 43 | # include 44 | 45 | # ifndef YY_NULLPTR 46 | # if defined __cplusplus && 201103L <= __cplusplus 47 | # define YY_NULLPTR nullptr 48 | # else 49 | # define YY_NULLPTR 0 50 | # endif 51 | # endif 52 | 53 | 54 | namespace yy { 55 | #line 56 "position.hh" // location.cc:337 56 | /// Abstract a position. 57 | class position 58 | { 59 | public: 60 | /// Construct a position. 61 | explicit position (std::string* f = YY_NULLPTR, 62 | unsigned int l = 1u, 63 | unsigned int c = 1u) 64 | : filename (f) 65 | , line (l) 66 | , column (c) 67 | { 68 | } 69 | 70 | 71 | /// Initialization. 72 | void initialize (std::string* fn = YY_NULLPTR, 73 | unsigned int l = 1u, 74 | unsigned int c = 1u) 75 | { 76 | filename = fn; 77 | line = l; 78 | column = c; 79 | } 80 | 81 | /** \name Line and Column related manipulators 82 | ** \{ */ 83 | /// (line related) Advance to the COUNT next lines. 84 | void lines (int count = 1) 85 | { 86 | if (count) 87 | { 88 | column = 1u; 89 | line = add_ (line, count, 1); 90 | } 91 | } 92 | 93 | /// (column related) Advance to the COUNT next columns. 94 | void columns (int count = 1) 95 | { 96 | column = add_ (column, count, 1); 97 | } 98 | /** \} */ 99 | 100 | /// File name to which this position refers. 101 | std::string* filename; 102 | /// Current line number. 103 | unsigned int line; 104 | /// Current column number. 105 | unsigned int column; 106 | 107 | private: 108 | /// Compute max(min, lhs+rhs) (provided min <= lhs). 109 | static unsigned int add_ (unsigned int lhs, int rhs, unsigned int min) 110 | { 111 | return (0 < rhs || -static_cast(rhs) < lhs 112 | ? rhs + lhs 113 | : min); 114 | } 115 | }; 116 | 117 | /// Add \a width columns, in place. 118 | inline position& 119 | operator+= (position& res, int width) 120 | { 121 | res.columns (width); 122 | return res; 123 | } 124 | 125 | /// Add \a width columns. 126 | inline position 127 | operator+ (position res, int width) 128 | { 129 | return res += width; 130 | } 131 | 132 | /// Subtract \a width columns, in place. 133 | inline position& 134 | operator-= (position& res, int width) 135 | { 136 | return res += -width; 137 | } 138 | 139 | /// Subtract \a width columns. 140 | inline position 141 | operator- (position res, int width) 142 | { 143 | return res -= width; 144 | } 145 | 146 | /// Compare two position objects. 147 | inline bool 148 | operator== (const position& pos1, const position& pos2) 149 | { 150 | return (pos1.line == pos2.line 151 | && pos1.column == pos2.column 152 | && (pos1.filename == pos2.filename 153 | || (pos1.filename && pos2.filename 154 | && *pos1.filename == *pos2.filename))); 155 | } 156 | 157 | /// Compare two position objects. 158 | inline bool 159 | operator!= (const position& pos1, const position& pos2) 160 | { 161 | return !(pos1 == pos2); 162 | } 163 | 164 | /** \brief Intercept output stream redirection. 165 | ** \param ostr the destination output stream 166 | ** \param pos a reference to the position to redirect 167 | */ 168 | template 169 | inline std::basic_ostream& 170 | operator<< (std::basic_ostream& ostr, const position& pos) 171 | { 172 | if (pos.filename) 173 | ostr << *pos.filename << ':'; 174 | return ostr << pos.line << '.' << pos.column; 175 | } 176 | 177 | 178 | } // yy 179 | #line 180 "position.hh" // location.cc:337 180 | #endif // !YY_YY_POSITION_HH_INCLUDED 181 | -------------------------------------------------------------------------------- /internal/c/GraphQLAst.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | /** @generated */ 10 | 11 | #pragma once 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | 18 | struct GraphQLAstDefinition; 19 | 20 | struct GraphQLAstDocument; 21 | int GraphQLAstDocument_get_definitions_size(const struct GraphQLAstDocument *node); 22 | 23 | struct GraphQLAstOperationDefinition; 24 | const char * GraphQLAstOperationDefinition_get_operation(const struct GraphQLAstOperationDefinition *node); 25 | const struct GraphQLAstName * GraphQLAstOperationDefinition_get_name(const struct GraphQLAstOperationDefinition *node); 26 | int GraphQLAstOperationDefinition_get_variable_definitions_size(const struct GraphQLAstOperationDefinition *node); 27 | int GraphQLAstOperationDefinition_get_directives_size(const struct GraphQLAstOperationDefinition *node); 28 | const struct GraphQLAstSelectionSet * GraphQLAstOperationDefinition_get_selection_set(const struct GraphQLAstOperationDefinition *node); 29 | 30 | struct GraphQLAstVariableDefinition; 31 | const struct GraphQLAstVariable * GraphQLAstVariableDefinition_get_variable(const struct GraphQLAstVariableDefinition *node); 32 | const struct GraphQLAstType * GraphQLAstVariableDefinition_get_type(const struct GraphQLAstVariableDefinition *node); 33 | const struct GraphQLAstValue * GraphQLAstVariableDefinition_get_default_value(const struct GraphQLAstVariableDefinition *node); 34 | 35 | struct GraphQLAstSelectionSet; 36 | int GraphQLAstSelectionSet_get_selections_size(const struct GraphQLAstSelectionSet *node); 37 | 38 | struct GraphQLAstSelection; 39 | 40 | struct GraphQLAstField; 41 | const struct GraphQLAstName * GraphQLAstField_get_alias(const struct GraphQLAstField *node); 42 | const struct GraphQLAstName * GraphQLAstField_get_name(const struct GraphQLAstField *node); 43 | int GraphQLAstField_get_arguments_size(const struct GraphQLAstField *node); 44 | int GraphQLAstField_get_directives_size(const struct GraphQLAstField *node); 45 | const struct GraphQLAstSelectionSet * GraphQLAstField_get_selection_set(const struct GraphQLAstField *node); 46 | 47 | struct GraphQLAstArgument; 48 | const struct GraphQLAstName * GraphQLAstArgument_get_name(const struct GraphQLAstArgument *node); 49 | const struct GraphQLAstValue * GraphQLAstArgument_get_value(const struct GraphQLAstArgument *node); 50 | 51 | struct GraphQLAstFragmentSpread; 52 | const struct GraphQLAstName * GraphQLAstFragmentSpread_get_name(const struct GraphQLAstFragmentSpread *node); 53 | int GraphQLAstFragmentSpread_get_directives_size(const struct GraphQLAstFragmentSpread *node); 54 | 55 | struct GraphQLAstInlineFragment; 56 | const struct GraphQLAstNamedType * GraphQLAstInlineFragment_get_type_condition(const struct GraphQLAstInlineFragment *node); 57 | int GraphQLAstInlineFragment_get_directives_size(const struct GraphQLAstInlineFragment *node); 58 | const struct GraphQLAstSelectionSet * GraphQLAstInlineFragment_get_selection_set(const struct GraphQLAstInlineFragment *node); 59 | 60 | struct GraphQLAstFragmentDefinition; 61 | const struct GraphQLAstName * GraphQLAstFragmentDefinition_get_name(const struct GraphQLAstFragmentDefinition *node); 62 | const struct GraphQLAstNamedType * GraphQLAstFragmentDefinition_get_type_condition(const struct GraphQLAstFragmentDefinition *node); 63 | int GraphQLAstFragmentDefinition_get_directives_size(const struct GraphQLAstFragmentDefinition *node); 64 | const struct GraphQLAstSelectionSet * GraphQLAstFragmentDefinition_get_selection_set(const struct GraphQLAstFragmentDefinition *node); 65 | 66 | struct GraphQLAstValue; 67 | 68 | struct GraphQLAstVariable; 69 | const struct GraphQLAstName * GraphQLAstVariable_get_name(const struct GraphQLAstVariable *node); 70 | 71 | struct GraphQLAstIntValue; 72 | const char * GraphQLAstIntValue_get_value(const struct GraphQLAstIntValue *node); 73 | 74 | struct GraphQLAstFloatValue; 75 | const char * GraphQLAstFloatValue_get_value(const struct GraphQLAstFloatValue *node); 76 | 77 | struct GraphQLAstStringValue; 78 | const char * GraphQLAstStringValue_get_value(const struct GraphQLAstStringValue *node); 79 | 80 | struct GraphQLAstBooleanValue; 81 | int GraphQLAstBooleanValue_get_value(const struct GraphQLAstBooleanValue *node); 82 | 83 | struct GraphQLAstEnumValue; 84 | const char * GraphQLAstEnumValue_get_value(const struct GraphQLAstEnumValue *node); 85 | 86 | struct GraphQLAstArrayValue; 87 | int GraphQLAstArrayValue_get_values_size(const struct GraphQLAstArrayValue *node); 88 | 89 | struct GraphQLAstObjectValue; 90 | int GraphQLAstObjectValue_get_fields_size(const struct GraphQLAstObjectValue *node); 91 | 92 | struct GraphQLAstObjectField; 93 | const struct GraphQLAstName * GraphQLAstObjectField_get_name(const struct GraphQLAstObjectField *node); 94 | const struct GraphQLAstValue * GraphQLAstObjectField_get_value(const struct GraphQLAstObjectField *node); 95 | 96 | struct GraphQLAstDirective; 97 | const struct GraphQLAstName * GraphQLAstDirective_get_name(const struct GraphQLAstDirective *node); 98 | int GraphQLAstDirective_get_arguments_size(const struct GraphQLAstDirective *node); 99 | 100 | struct GraphQLAstType; 101 | 102 | struct GraphQLAstNamedType; 103 | const struct GraphQLAstName * GraphQLAstNamedType_get_name(const struct GraphQLAstNamedType *node); 104 | 105 | struct GraphQLAstListType; 106 | const struct GraphQLAstType * GraphQLAstListType_get_type(const struct GraphQLAstListType *node); 107 | 108 | struct GraphQLAstNonNullType; 109 | const struct GraphQLAstType * GraphQLAstNonNullType_get_type(const struct GraphQLAstNonNullType *node); 110 | 111 | struct GraphQLAstName; 112 | const char * GraphQLAstName_get_value(const struct GraphQLAstName *node); 113 | 114 | 115 | 116 | #ifdef __cplusplus 117 | } 118 | #endif 119 | 120 | -------------------------------------------------------------------------------- /internal/location.hh: -------------------------------------------------------------------------------- 1 | // A Bison parser, made by GNU Bison 3.0.4. 2 | 3 | // Locations for Bison parsers in C++ 4 | 5 | // Copyright (C) 2002-2015 Free Software Foundation, Inc. 6 | 7 | // This program is free software: you can redistribute it and/or modify 8 | // it under the terms of the GNU General Public License as published by 9 | // the Free Software Foundation, either version 3 of the License, or 10 | // (at your option) any later version. 11 | 12 | // This program is distributed in the hope that it will be useful, 13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | // GNU General Public License for more details. 16 | 17 | // You should have received a copy of the GNU General Public License 18 | // along with this program. If not, see . 19 | 20 | // As a special exception, you may create a larger work that contains 21 | // part or all of the Bison parser skeleton and distribute that work 22 | // under terms of your choice, so long as that work isn't itself a 23 | // parser generator using the skeleton or a modified version thereof 24 | // as a parser skeleton. Alternatively, if you modify or redistribute 25 | // the parser skeleton itself, you may (at your option) remove this 26 | // special exception, which will cause the skeleton and the resulting 27 | // Bison output files to be licensed under the GNU General Public 28 | // License without this special exception. 29 | 30 | // This special exception was added by the Free Software Foundation in 31 | // version 2.2 of Bison. 32 | 33 | /** 34 | ** \file location.hh 35 | ** Define the yy::location class. 36 | */ 37 | 38 | #ifndef YY_YY_LOCATION_HH_INCLUDED 39 | # define YY_YY_LOCATION_HH_INCLUDED 40 | 41 | # include "position.hh" 42 | 43 | 44 | namespace yy { 45 | #line 46 "location.hh" // location.cc:337 46 | /// Abstract a location. 47 | class location 48 | { 49 | public: 50 | 51 | /// Construct a location from \a b to \a e. 52 | location (const position& b, const position& e) 53 | : begin (b) 54 | , end (e) 55 | { 56 | } 57 | 58 | /// Construct a 0-width location in \a p. 59 | explicit location (const position& p = position ()) 60 | : begin (p) 61 | , end (p) 62 | { 63 | } 64 | 65 | /// Construct a 0-width location in \a f, \a l, \a c. 66 | explicit location (std::string* f, 67 | unsigned int l = 1u, 68 | unsigned int c = 1u) 69 | : begin (f, l, c) 70 | , end (f, l, c) 71 | { 72 | } 73 | 74 | 75 | /// Initialization. 76 | void initialize (std::string* f = YY_NULLPTR, 77 | unsigned int l = 1u, 78 | unsigned int c = 1u) 79 | { 80 | begin.initialize (f, l, c); 81 | end = begin; 82 | } 83 | 84 | /** \name Line and Column related manipulators 85 | ** \{ */ 86 | public: 87 | /// Reset initial location to final location. 88 | void step () 89 | { 90 | begin = end; 91 | } 92 | 93 | /// Extend the current location to the COUNT next columns. 94 | void columns (int count = 1) 95 | { 96 | end += count; 97 | } 98 | 99 | /// Extend the current location to the COUNT next lines. 100 | void lines (int count = 1) 101 | { 102 | end.lines (count); 103 | } 104 | /** \} */ 105 | 106 | 107 | public: 108 | /// Beginning of the located region. 109 | position begin; 110 | /// End of the located region. 111 | position end; 112 | }; 113 | 114 | /// Join two locations, in place. 115 | inline location& operator+= (location& res, const location& end) 116 | { 117 | res.end = end.end; 118 | return res; 119 | } 120 | 121 | /// Join two locations. 122 | inline location operator+ (location res, const location& end) 123 | { 124 | return res += end; 125 | } 126 | 127 | /// Add \a width columns to the end position, in place. 128 | inline location& operator+= (location& res, int width) 129 | { 130 | res.columns (width); 131 | return res; 132 | } 133 | 134 | /// Add \a width columns to the end position. 135 | inline location operator+ (location res, int width) 136 | { 137 | return res += width; 138 | } 139 | 140 | /// Subtract \a width columns to the end position, in place. 141 | inline location& operator-= (location& res, int width) 142 | { 143 | return res += -width; 144 | } 145 | 146 | /// Subtract \a width columns to the end position. 147 | inline location operator- (location res, int width) 148 | { 149 | return res -= width; 150 | } 151 | 152 | /// Compare two location objects. 153 | inline bool 154 | operator== (const location& loc1, const location& loc2) 155 | { 156 | return loc1.begin == loc2.begin && loc1.end == loc2.end; 157 | } 158 | 159 | /// Compare two location objects. 160 | inline bool 161 | operator!= (const location& loc1, const location& loc2) 162 | { 163 | return !(loc1 == loc2); 164 | } 165 | 166 | /** \brief Intercept output stream redirection. 167 | ** \param ostr the destination output stream 168 | ** \param loc a reference to the location to redirect 169 | ** 170 | ** Avoid duplicate information. 171 | */ 172 | template 173 | inline std::basic_ostream& 174 | operator<< (std::basic_ostream& ostr, const location& loc) 175 | { 176 | unsigned int end_col = 0 < loc.end.column ? loc.end.column - 1 : 0; 177 | ostr << loc.begin; 178 | if (loc.end.filename 179 | && (!loc.begin.filename 180 | || *loc.begin.filename != *loc.end.filename)) 181 | ostr << '-' << loc.end.filename << ':' << loc.end.line << '.' << end_col; 182 | else if (loc.begin.line < loc.end.line) 183 | ostr << '-' << loc.end.line << '.' << end_col; 184 | else if (loc.begin.column < end_col) 185 | ostr << '-' << end_col; 186 | return ostr; 187 | } 188 | 189 | 190 | } // yy 191 | #line 192 "location.hh" // location.cc:337 192 | #endif // !YY_YY_LOCATION_HH_INCLUDED 193 | -------------------------------------------------------------------------------- /internal/Ast.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | /** @generated */ 10 | 11 | #include "Ast.h" 12 | #include "AstVisitor.h" 13 | 14 | namespace facebook { 15 | namespace graphql { 16 | namespace ast { 17 | 18 | void Document::accept(visitor::AstVisitor *visitor) { 19 | if (visitor->visitDocument(*this)) { 20 | 21 | { for (const auto &x : *definitions_) { x->accept(visitor); } } 22 | } 23 | visitor->endVisitDocument(*this); 24 | } 25 | 26 | void OperationDefinition::accept(visitor::AstVisitor *visitor) { 27 | if (visitor->visitOperationDefinition(*this)) { 28 | 29 | if (name_) { name_->accept(visitor); } 30 | if (variableDefinitions_) { for (const auto &x : *variableDefinitions_) { x->accept(visitor); } } 31 | if (directives_) { for (const auto &x : *directives_) { x->accept(visitor); } } 32 | selectionSet_->accept(visitor); 33 | } 34 | visitor->endVisitOperationDefinition(*this); 35 | } 36 | 37 | void VariableDefinition::accept(visitor::AstVisitor *visitor) { 38 | if (visitor->visitVariableDefinition(*this)) { 39 | 40 | variable_->accept(visitor); 41 | type_->accept(visitor); 42 | if (defaultValue_) { defaultValue_->accept(visitor); } 43 | } 44 | visitor->endVisitVariableDefinition(*this); 45 | } 46 | 47 | void SelectionSet::accept(visitor::AstVisitor *visitor) { 48 | if (visitor->visitSelectionSet(*this)) { 49 | 50 | { for (const auto &x : *selections_) { x->accept(visitor); } } 51 | } 52 | visitor->endVisitSelectionSet(*this); 53 | } 54 | 55 | void Field::accept(visitor::AstVisitor *visitor) { 56 | if (visitor->visitField(*this)) { 57 | 58 | if (alias_) { alias_->accept(visitor); } 59 | name_->accept(visitor); 60 | if (arguments_) { for (const auto &x : *arguments_) { x->accept(visitor); } } 61 | if (directives_) { for (const auto &x : *directives_) { x->accept(visitor); } } 62 | if (selectionSet_) { selectionSet_->accept(visitor); } 63 | } 64 | visitor->endVisitField(*this); 65 | } 66 | 67 | void Argument::accept(visitor::AstVisitor *visitor) { 68 | if (visitor->visitArgument(*this)) { 69 | 70 | name_->accept(visitor); 71 | value_->accept(visitor); 72 | } 73 | visitor->endVisitArgument(*this); 74 | } 75 | 76 | void FragmentSpread::accept(visitor::AstVisitor *visitor) { 77 | if (visitor->visitFragmentSpread(*this)) { 78 | 79 | name_->accept(visitor); 80 | if (directives_) { for (const auto &x : *directives_) { x->accept(visitor); } } 81 | } 82 | visitor->endVisitFragmentSpread(*this); 83 | } 84 | 85 | void InlineFragment::accept(visitor::AstVisitor *visitor) { 86 | if (visitor->visitInlineFragment(*this)) { 87 | 88 | typeCondition_->accept(visitor); 89 | if (directives_) { for (const auto &x : *directives_) { x->accept(visitor); } } 90 | selectionSet_->accept(visitor); 91 | } 92 | visitor->endVisitInlineFragment(*this); 93 | } 94 | 95 | void FragmentDefinition::accept(visitor::AstVisitor *visitor) { 96 | if (visitor->visitFragmentDefinition(*this)) { 97 | 98 | name_->accept(visitor); 99 | typeCondition_->accept(visitor); 100 | if (directives_) { for (const auto &x : *directives_) { x->accept(visitor); } } 101 | selectionSet_->accept(visitor); 102 | } 103 | visitor->endVisitFragmentDefinition(*this); 104 | } 105 | 106 | void Variable::accept(visitor::AstVisitor *visitor) { 107 | if (visitor->visitVariable(*this)) { 108 | 109 | name_->accept(visitor); 110 | } 111 | visitor->endVisitVariable(*this); 112 | } 113 | 114 | void IntValue::accept(visitor::AstVisitor *visitor) { 115 | if (visitor->visitIntValue(*this)) { 116 | 117 | } 118 | visitor->endVisitIntValue(*this); 119 | } 120 | 121 | void FloatValue::accept(visitor::AstVisitor *visitor) { 122 | if (visitor->visitFloatValue(*this)) { 123 | 124 | } 125 | visitor->endVisitFloatValue(*this); 126 | } 127 | 128 | void StringValue::accept(visitor::AstVisitor *visitor) { 129 | if (visitor->visitStringValue(*this)) { 130 | 131 | } 132 | visitor->endVisitStringValue(*this); 133 | } 134 | 135 | void BooleanValue::accept(visitor::AstVisitor *visitor) { 136 | if (visitor->visitBooleanValue(*this)) { 137 | 138 | } 139 | visitor->endVisitBooleanValue(*this); 140 | } 141 | 142 | void EnumValue::accept(visitor::AstVisitor *visitor) { 143 | if (visitor->visitEnumValue(*this)) { 144 | 145 | } 146 | visitor->endVisitEnumValue(*this); 147 | } 148 | 149 | void ArrayValue::accept(visitor::AstVisitor *visitor) { 150 | if (visitor->visitArrayValue(*this)) { 151 | 152 | { for (const auto &x : *values_) { x->accept(visitor); } } 153 | } 154 | visitor->endVisitArrayValue(*this); 155 | } 156 | 157 | void ObjectValue::accept(visitor::AstVisitor *visitor) { 158 | if (visitor->visitObjectValue(*this)) { 159 | 160 | { for (const auto &x : *fields_) { x->accept(visitor); } } 161 | } 162 | visitor->endVisitObjectValue(*this); 163 | } 164 | 165 | void ObjectField::accept(visitor::AstVisitor *visitor) { 166 | if (visitor->visitObjectField(*this)) { 167 | 168 | name_->accept(visitor); 169 | value_->accept(visitor); 170 | } 171 | visitor->endVisitObjectField(*this); 172 | } 173 | 174 | void Directive::accept(visitor::AstVisitor *visitor) { 175 | if (visitor->visitDirective(*this)) { 176 | 177 | name_->accept(visitor); 178 | if (arguments_) { for (const auto &x : *arguments_) { x->accept(visitor); } } 179 | } 180 | visitor->endVisitDirective(*this); 181 | } 182 | 183 | void NamedType::accept(visitor::AstVisitor *visitor) { 184 | if (visitor->visitNamedType(*this)) { 185 | 186 | name_->accept(visitor); 187 | } 188 | visitor->endVisitNamedType(*this); 189 | } 190 | 191 | void ListType::accept(visitor::AstVisitor *visitor) { 192 | if (visitor->visitListType(*this)) { 193 | 194 | type_->accept(visitor); 195 | } 196 | visitor->endVisitListType(*this); 197 | } 198 | 199 | void NonNullType::accept(visitor::AstVisitor *visitor) { 200 | if (visitor->visitNonNullType(*this)) { 201 | 202 | type_->accept(visitor); 203 | } 204 | visitor->endVisitNonNullType(*this); 205 | } 206 | 207 | void Name::accept(visitor::AstVisitor *visitor) { 208 | if (visitor->visitName(*this)) { 209 | 210 | } 211 | visitor->endVisitName(*this); 212 | } 213 | 214 | } 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /internal/lexer.lpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | %{ 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include "location.hh" 16 | #include "position.hh" 17 | #include "parser.tab.hpp" 18 | #include "syntaxdefs.h" 19 | 20 | // Keep track of token lengths. 21 | #define YY_USER_ACTION yyextra->loc.columns(yyleng); 22 | 23 | static void escape(char c, char *buf); 24 | 25 | %} 26 | 27 | %option bison-bridge bison-locations 28 | %option noyywrap batch noinput nounput 29 | %option reentrant 30 | %option extra-type="struct LexerExtra *" 31 | 32 | %x STRING_STATE 33 | %x C_COMMENT_STATE 34 | %x LINE_COMMENT_STATE 35 | 36 | FLOAT -?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)? 37 | INTEGER -?(0|[1-9][0-9]*) 38 | IDENTIFIER [_A-Za-z][_0-9A-Za-z]* 39 | VARIABLE $[_0-9A-Za-z]+ 40 | BOM \xef\xbb\xbf 41 | CRLF \r\n 42 | BADCHAR [\x00-\x08\x0b\x0c\x0e-\x1f] 43 | STRINGCHAR [^\x00-\x1f\\\x22] 44 | 45 | blank [ \t,] 46 | newline [\n\r] 47 | notnewline [^\n\r] 48 | 49 | %% 50 | 51 | %{ 52 | yyextra->loc.step(); 53 | %} 54 | 55 | { 56 | \" { 57 | BEGIN(INITIAL); 58 | yylval->str = yyextra->str.c_str(); 59 | return yy::GraphQLParserImpl::token::TOK_STRING; 60 | } 61 | 62 | {newline} { 63 | throw make_error(yyextra->loc, "Unterminated string"); 64 | } 65 | 66 | <> { 67 | throw make_error(yyextra->loc, "Unterminated string at EOF"); 68 | } 69 | 70 | {STRINGCHAR}+ { 71 | char *p = yytext; 72 | while (*p) { 73 | yyextra->loc.columns(); 74 | yyextra->str.push_back(*p++); 75 | } 76 | } 77 | 78 | \\\" { yyextra->str.push_back('"'); } 79 | \\\\ { yyextra->str.push_back('\\'); } 80 | \\\/ { yyextra->str.push_back('/'); } 81 | \\n { yyextra->str.push_back('\n'); } 82 | \\t { yyextra->str.push_back('\t'); } 83 | \\r { yyextra->str.push_back('\r'); } 84 | \\b { yyextra->str.push_back('\b'); } 85 | \\f { yyextra->str.push_back('\f'); } 86 | 87 | \\u[0-9A-Fa-f]{4} { 88 | int ch; 89 | sscanf(yytext + 1, "%x", &ch); 90 | yyextra->str.push_back(ch); 91 | } 92 | 93 | \\u { throw make_error(yyextra->loc, "bad Unicode escape sequence"); } 94 | \\. { throw make_error(yyextra->loc, std::string("bad escape sequence \\") + yytext[1]); } 95 | 96 | } 97 | 98 | { 99 | {CRLF} { yyextra->loc.step(); BEGIN(INITIAL); } 100 | {newline} { yyextra->loc.step(); BEGIN(INITIAL); } 101 | {notnewline}+ /* eat comment character */ 102 | } 103 | 104 | { 105 | {blank}+ { yyextra->loc.step(); } 106 | {BOM}+ { yyextra->loc.step(); yyextra->loc.step(); yyextra->loc.step(); } 107 | {CRLF}+ { yyextra->loc.lines(yyleng / 2); yyextra->loc.step(); } 108 | {newline}+ { yyextra->loc.lines(yyleng); yyextra->loc.step(); } 109 | 110 | # {yyextra->loc.step(); BEGIN(LINE_COMMENT_STATE); } 111 | 112 | false { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_FALSE; } 113 | fragment { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_FRAGMENT; } 114 | mutation { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_MUTATION; } 115 | null { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_NULL; } 116 | on { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_ON; } 117 | query { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_QUERY; } 118 | true { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_TRUE; } 119 | 120 | {INTEGER} { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_INTEGER; } 121 | {FLOAT} { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_FLOAT; } 122 | {IDENTIFIER} { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_IDENTIFIER; } 123 | {VARIABLE} { yylval->str = yytext + 1; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_VARIABLE; } 124 | 125 | "!" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_BANG; } 126 | "(" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_LPAREN; } 127 | ")" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_RPAREN; } 128 | "..." { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_ELLIPSIS; } 129 | ":" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_COLON; } 130 | "=" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_EQUAL; } 131 | "@" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_AT; } 132 | "[" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_LBRACKET; } 133 | "]" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_RBRACKET; } 134 | "{" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_LBRACE; } 135 | "|" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_PIPE; } 136 | "}" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_RBRACE; } 137 | 138 | 139 | <> { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_EOF; } 140 | 141 | \" { 142 | BEGIN(STRING_STATE); 143 | yyextra->str.clear(); 144 | } 145 | } 146 | 147 | . { 148 | char buf[6]; 149 | escape(yytext[0], buf); 150 | throw make_error( 151 | yyextra->loc, 152 | std::string("unrecognized character ") + buf); 153 | } 154 | 155 | %% 156 | 157 | static void escape(char c, char *buf) { 158 | if (std::isgraph(c)) { 159 | *buf = c; 160 | buf[1] = '\0'; 161 | } else { 162 | buf[0] = '\\'; 163 | buf[2] = '\0'; 164 | switch (c) { 165 | case '\a': 166 | buf[1] = 'a'; 167 | break; 168 | case '\b': 169 | buf[1] = 'b'; 170 | break; 171 | case '\f': 172 | buf[1] = 'f'; 173 | break; 174 | case '\n': 175 | buf[1] = 'n'; 176 | break; 177 | case '\r': 178 | buf[1] = 'r'; 179 | break; 180 | case '\t': 181 | buf[1] = 't'; 182 | break; 183 | case '\v': 184 | buf[1] = 'v'; 185 | break; 186 | default: 187 | buf[1] = 'x'; 188 | std::snprintf(buf + 2, 3, "%x", ((int)c & 0xFF)); 189 | break; 190 | } 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /internal/test/ParserTests.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #include 11 | #include 12 | 13 | #include "Ast.h" 14 | #include "GraphQLParser.h" 15 | 16 | using namespace facebook::graphql; 17 | using namespace facebook::graphql::ast; 18 | 19 | 20 | static void expectError(const char *queryStr, const char *expectedError) { 21 | const char *actualError = nullptr; 22 | auto ast = parseString(queryStr, &actualError); 23 | 24 | EXPECT_FALSE(ast); 25 | EXPECT_STREQ(expectedError, actualError); 26 | 27 | std::free((void *)actualError); 28 | } 29 | 30 | static void expectSuccess(const char *queryStr) { 31 | const char *actualError = nullptr; 32 | auto ast = parseString(queryStr, &actualError); 33 | 34 | EXPECT_TRUE(ast != nullptr); 35 | EXPECT_STREQ(nullptr, actualError); 36 | 37 | std::free((void *)actualError); 38 | } 39 | 40 | static void checkSimpleError() { 41 | expectError("query myquery on type { field }", 42 | "1.15-16: syntax error, unexpected on, expecting ( or @ or {"); 43 | } 44 | 45 | TEST(ParserTests, RejectsUnrecognizedCharacter) { 46 | expectError("query myquery { field };", 47 | "1.24: unrecognized character ;"); 48 | } 49 | 50 | TEST(ParserTests, RejectsControlCharacter) { 51 | expectError("query myQuery { \a }", 52 | "1.17: unrecognized character \\a"); 53 | } 54 | 55 | TEST(ParserTests, AcceptsUnicodeBOM) { 56 | expectSuccess("\xef\xbb\xbfquery myquery { field }"); 57 | expectSuccess("query myquery\xef\xbb\xbf{ field }"); 58 | } 59 | 60 | TEST(ParserTests, ReportsErrorLocationAfterIgnoredBOM) { 61 | expectError("\xef\xbb\xbfquery myquery { field };", 62 | "1.27: unrecognized character ;"); 63 | 64 | } 65 | 66 | TEST(ParserTests, RejectsPartialBOM) { 67 | expectError("\xefquery myquery { field };", 68 | "1.1: unrecognized character \\xef"); 69 | } 70 | 71 | TEST(ParserTests, RejectsVerticalTab) { 72 | expectError("\v", "1.1: unrecognized character \\v"); 73 | } 74 | 75 | TEST(ParserTests, RejectsFormFeed) { 76 | expectError("\f", "1.1: unrecognized character \\f"); 77 | } 78 | 79 | TEST(ParserTests, RejectsNoBreakSpace) { 80 | expectError("\xa0", "1.1: unrecognized character \\xa0"); 81 | } 82 | 83 | 84 | TEST(ParserTests, LocationTracking) { 85 | SCOPED_TRACE("LocationTracking"); 86 | checkSimpleError(); 87 | } 88 | 89 | TEST(ParserTests, LocationTrackingResetsAcrossInputs) { 90 | { 91 | SCOPED_TRACE("LocationTrackingResetsAcrossInputsFirstTime"); 92 | checkSimpleError(); 93 | } 94 | 95 | { 96 | SCOPED_TRACE("LocationTrackingResetsAcrossInputsSecondTime"); 97 | checkSimpleError(); 98 | } 99 | 100 | } 101 | 102 | TEST(ParserTests, LocationTrackingCollapsesCRLF) { 103 | expectError("\r\n;", "2.1: unrecognized character ;"); 104 | } 105 | 106 | TEST(ParserTests, AcceptsEmptyString) { 107 | expectSuccess("{ field(arg:\"\") }"); 108 | } 109 | 110 | TEST(ParserTests, UnterminatedString) { 111 | expectError("\"", "1.1: Unterminated string at EOF"); 112 | expectError("\"\n\"", "1.1-2: Unterminated string"); 113 | } 114 | 115 | TEST(ParserTests, RejectControlCharacterInString) { 116 | expectError("{ field(arg:\"\b\") }", "1.13-14: unrecognized character \\b"); 117 | } 118 | 119 | TEST(ParserTests, RejectsBadXEscapeSequence) { 120 | expectError("{ field(arg:\"\\x\") }", "1.13-15: bad escape sequence \\x"); 121 | } 122 | 123 | TEST(ParserTests, RejectsIncompleteUnicodeEscape) { 124 | expectError("{ field(arg:\"\\u1\") }", "1.13-15: bad Unicode escape sequence"); 125 | } 126 | 127 | TEST(ParserTests, RejectsUnicodeEscapeWithBadChars) { 128 | expectError("{ field(arg:\"\\u0XX1\") }", "1.13-15: bad Unicode escape sequence"); 129 | expectError("{ field(arg:\"\\uXXXX\") }", "1.13-15: bad Unicode escape sequence"); 130 | expectError("{ field(arg:\"\\uFXXX\") }", "1.13-15: bad Unicode escape sequence"); 131 | expectError("{ field(arg:\"\\uXXXF\") }", "1.13-15: bad Unicode escape sequence"); 132 | } 133 | 134 | TEST(ParserTests, TracksLocationAcrossStrings) { 135 | expectError("{ field(arg:\"\\uFEFF\\n\") };", 136 | "1.26: unrecognized character ;"); 137 | } 138 | 139 | TEST(ParserTests, UsefulErrors) { 140 | expectError("{ ...MissingOn }\nfragment MissingOn Type", 141 | "2.20-23: syntax error, unexpected IDENTIFIER, expecting on"); 142 | 143 | expectError("{ field: {} }", 144 | "1.10: syntax error, unexpected {"); 145 | 146 | expectError( 147 | "notanoperation Foo { field }", 148 | "1.1-14: syntax error, unexpected IDENTIFIER, expecting fragment or " 149 | "mutation or query or {"); 150 | 151 | expectError("...", 152 | "1.1-3: syntax error, unexpected ..., expecting fragment or " 153 | "mutation or query or {"); 154 | } 155 | 156 | TEST(ParserTests, AcceptsVariableInlineValues) { 157 | expectSuccess("{ field(complex: { a: { b: [ $var ] } }) }"); 158 | } 159 | 160 | TEST(ParserTests, RejectsVariablesInConstantValues) { 161 | expectError("query Foo($x: Complex = { a: { b: [ $var ] } }) { field }", 162 | "1.37-40: syntax error, unexpected VARIABLE"); 163 | } 164 | 165 | TEST(ParserTests, RejectsFragmentsNamedOn) { 166 | expectError("fragment on on on { on }", 167 | "1.10-11: syntax error, unexpected on"); 168 | } 169 | 170 | TEST(ParserTests, RejectsFragmentSpreadOfOn) { 171 | expectError("{ ...on }", 172 | "1.9: syntax error, unexpected }"); 173 | }; 174 | 175 | TEST(ParserTests, RejectsNullValue) { 176 | expectError("{ fieldWithNullableStringInput(input: null) }", 177 | "1.39-42: syntax error, unexpected null"); 178 | } 179 | 180 | TEST(ParserTests, AcceptsSimpleQuery) { 181 | expectSuccess("query MyQuery { myfield }"); 182 | } 183 | 184 | TEST(ParserTests, AcceptsQueryShorthand) { 185 | expectSuccess("{ myfield }"); 186 | } 187 | 188 | TEST(ParserTests, AcceptsLonghandUnnamedQuery) { 189 | expectSuccess("query { myfield }"); 190 | } 191 | 192 | TEST(ParserTests, AcceptsLonghandUnnamedMutation) { 193 | expectSuccess("mutation { myfield }"); 194 | } 195 | 196 | TEST(ParserTests, AllowsNonKeywordsForNames) { 197 | const char *nonKeywords[] = { 198 | "on", 199 | "fragment", 200 | "query", 201 | "mutation", 202 | "true", 203 | "false" 204 | }; 205 | 206 | for (int ii = 0; ii < sizeof(nonKeywords) / sizeof(nonKeywords[0]); ++ii) { 207 | const char *keyword = nonKeywords[ii]; 208 | const char *fragmentName = !strcmp(keyword, "on") ? "a" : keyword; 209 | 210 | std::ostringstream str; 211 | 212 | str << "query " << keyword << "{\n" 213 | << " ... " << fragmentName << '\n' 214 | << " ... on " << keyword << " { field }\n" 215 | << "}\n" 216 | << "fragment " << fragmentName << " on Type {" 217 | << " " << keyword << '(' << keyword << ": $" << keyword << ") @" << keyword << '(' << keyword << ": " << keyword << ")\n" 218 | << "}\n"; 219 | expectSuccess(str.str().c_str()); 220 | } 221 | } 222 | -------------------------------------------------------------------------------- /internal/ast/cxx.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015, Facebook, Inc. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. An additional grant 6 | # of patent rights can be found in the PATENTS file in the same directory. 7 | 8 | import cStringIO as StringIO 9 | 10 | from casing import title 11 | from license import C_LICENSE_COMMENT 12 | 13 | class Printer(object): 14 | def __init__(self): 15 | self._type_name = None 16 | # Map concrete type to base class 17 | self._bases = {} 18 | # HACK: Defer everything we print so that forward declarations for 19 | # all classes come first. Avoids having to do 2 passes over the 20 | # input file. 21 | self._deferredOutput = StringIO.StringIO() 22 | 23 | self._fields = [] 24 | 25 | def start_file(self): 26 | print C_LICENSE_COMMENT + '''/** @generated */ 27 | #pragma once 28 | 29 | #include "AstNode.h" 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | namespace facebook { 37 | namespace graphql { 38 | namespace ast { 39 | 40 | // The parser uses strdup to move from yytext to the heap, so we need 41 | // to use free instead of delete. 42 | struct CDeleter { 43 | void operator()(const char *p) const { free((void *)p); } 44 | }; 45 | ''' 46 | 47 | def end_file(self): 48 | print 49 | print self._deferredOutput.getvalue() 50 | print '}' 51 | print '}' 52 | print '}' 53 | 54 | def _base_class(self, type): 55 | return self._bases.get(type, 'Node') 56 | 57 | def start_type(self, name): 58 | self._type_name = name 59 | base = self._base_class(name) 60 | # non-deferred! 61 | print 'class %s;' % name 62 | print >> self._deferredOutput, 'class %s : public %s {' % (name, base) 63 | self._fields = [] 64 | 65 | def field(self, type, name, nullable, plural): 66 | if type == 'OperationKind': 67 | type = 'string' 68 | self._fields.append((type, name, nullable, plural)) 69 | 70 | def end_type(self, name): 71 | self._print_fields() 72 | print >> self._deferredOutput, ' public:' 73 | self._print_constructor() 74 | print >> self._deferredOutput 75 | self._print_destructor_prototype() 76 | print >> self._deferredOutput 77 | self._print_noncopyable() 78 | print >> self._deferredOutput 79 | self._print_getters() 80 | print >> self._deferredOutput, ' void accept(visitor::AstVisitor *visitor) override;' 81 | print >> self._deferredOutput, '};' 82 | print >> self._deferredOutput 83 | print >> self._deferredOutput 84 | self._type_name = None 85 | self._fields = [] 86 | 87 | def _storage_type(self, type): 88 | if type == 'string': 89 | return 'std::unique_ptr' 90 | elif type == 'boolean': 91 | return 'bool' 92 | else: 93 | return 'std::unique_ptr<%s>' % type 94 | 95 | def _print_fields(self): 96 | for (type, name, nullable, plural) in self._fields: 97 | storage_type = self._storage_type(type) 98 | if plural: 99 | storage_type = 'std::unique_ptr>' % storage_type 100 | print >> self._deferredOutput, ' %s %s_;' % (storage_type, name) 101 | 102 | def _ctor_singular_type(self, type): 103 | if type == 'string': 104 | return 'const char *' 105 | elif type == 'boolean': 106 | return 'bool' 107 | else: 108 | return '%s *' % type 109 | 110 | def _ctor_plural_type(self, type): 111 | return 'std::vector<%s> *' % self._storage_type(type) 112 | 113 | def _print_constructor(self): 114 | print >> self._deferredOutput, ' explicit %s(' % self._type_name 115 | print >> self._deferredOutput, ' const yy::location &location%s' % (',' if self._fields else '') 116 | def ctor_arg(type, name, plural): 117 | if plural: 118 | ctor_type = self._ctor_plural_type(type) 119 | else: 120 | ctor_type = self._ctor_singular_type(type) 121 | return ' %s %s' % (ctor_type, name) 122 | print >> self._deferredOutput, ',\n'.join(ctor_arg(type, name, plural) 123 | for (type, name, nullable, plural) in self._fields) 124 | print >> self._deferredOutput, ' )' 125 | def ctor_init(type, name, plural): 126 | # Strings are const char *, just pass. 127 | # Vectors are passed by pointer and we take ownership. 128 | # Node types are passed in by pointer and we take ownership. 129 | value = name 130 | return ' %s_(%s)' % (name, value) 131 | print >> self._deferredOutput, ' : %s(location)%s' % (self._base_class(self._type_name), ',' if self._fields else '') 132 | print >> self._deferredOutput, ',\n'.join(ctor_init(type, name, plural) 133 | for (type, name, nullable, plural) 134 | in self._fields) 135 | print >> self._deferredOutput, ' {}' 136 | 137 | def _getter_type(self, type, nullable, plural): 138 | if plural and nullable: 139 | return 'const std::vector<%s>*' % self._storage_type(type) 140 | elif plural: 141 | return 'const std::vector<%s>&' % self._storage_type(type) 142 | 143 | if type == 'string': 144 | assert not nullable 145 | return 'const char *' 146 | elif type == 'boolean': 147 | assert not nullable 148 | return 'bool' 149 | elif nullable: 150 | return 'const %s*' % type 151 | else: 152 | return 'const %s&' % type 153 | 154 | def _getter_value_to_return(self, raw_value, type, nullable, plural): 155 | if plural and nullable: 156 | return raw_value + '.get()' 157 | elif plural: 158 | return '*%s' % raw_value 159 | elif type == 'boolean': 160 | return raw_value 161 | elif nullable or type == 'string': 162 | return '%s.get()' % raw_value 163 | else: 164 | return '*%s' % raw_value 165 | 166 | def _print_getters(self): 167 | for (type, name, nullable, plural) in self._fields: 168 | print >> self._deferredOutput, ' %s get%s() const' % ( 169 | self._getter_type(type, nullable, plural), 170 | title(name)) 171 | print >> self._deferredOutput, ' { return %s; }' % ( 172 | self._getter_value_to_return(name + '_', type, nullable, plural)) 173 | print >> self._deferredOutput 174 | 175 | def _print_destructor_prototype(self): 176 | print >> self._deferredOutput, ' ~%s() {}' % self._type_name 177 | 178 | def _print_noncopyable(self): 179 | print >> self._deferredOutput, ' %s(const %s&) = delete;' % ( 180 | self._type_name, self._type_name) 181 | print >> self._deferredOutput, ' %s& operator=(const %s&) = delete;' % ( 182 | self._type_name, self._type_name) 183 | 184 | def start_union(self, name): 185 | self._type_name = name 186 | # non-deferred! 187 | print 'class %s;' % name 188 | print >> self._deferredOutput, 'class %s : public Node {' % name 189 | print >> self._deferredOutput, ' public:' 190 | self._print_constructor() 191 | print >> self._deferredOutput, '};' 192 | print >> self._deferredOutput 193 | 194 | def union_option(self, type): 195 | assert type not in self._bases, '%s cannot appear in more than one union!' % type 196 | self._bases[type] = self._type_name 197 | 198 | def end_union(self, name): 199 | pass 200 | -------------------------------------------------------------------------------- /internal/lexer.h: -------------------------------------------------------------------------------- 1 | #ifndef yyHEADER_H 2 | #define yyHEADER_H 1 3 | #define yyIN_HEADER 1 4 | 5 | #line 6 "lexer.h" 6 | 7 | #line 8 "lexer.h" 8 | 9 | #define YY_INT_ALIGNED short int 10 | 11 | /* A lexical scanner generated by flex */ 12 | 13 | #define FLEX_SCANNER 14 | #define YY_FLEX_MAJOR_VERSION 2 15 | #define YY_FLEX_MINOR_VERSION 5 16 | #define YY_FLEX_SUBMINOR_VERSION 35 17 | #if YY_FLEX_SUBMINOR_VERSION > 0 18 | #define FLEX_BETA 19 | #endif 20 | 21 | /* First, we deal with platform-specific or compiler-specific issues. */ 22 | 23 | /* begin standard C headers. */ 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | /* end standard C headers. */ 30 | 31 | /* flex integer type definitions */ 32 | 33 | #ifndef FLEXINT_H 34 | #define FLEXINT_H 35 | 36 | /* C99 systems have . Non-C99 systems may or may not. */ 37 | 38 | #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L 39 | 40 | /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, 41 | * if you want the limit (max/min) macros for int types. 42 | */ 43 | #ifndef __STDC_LIMIT_MACROS 44 | #define __STDC_LIMIT_MACROS 1 45 | #endif 46 | 47 | #include 48 | typedef int8_t flex_int8_t; 49 | typedef uint8_t flex_uint8_t; 50 | typedef int16_t flex_int16_t; 51 | typedef uint16_t flex_uint16_t; 52 | typedef int32_t flex_int32_t; 53 | typedef uint32_t flex_uint32_t; 54 | typedef uint64_t flex_uint64_t; 55 | #else 56 | typedef signed char flex_int8_t; 57 | typedef short int flex_int16_t; 58 | typedef int flex_int32_t; 59 | typedef unsigned char flex_uint8_t; 60 | typedef unsigned short int flex_uint16_t; 61 | typedef unsigned int flex_uint32_t; 62 | #endif /* ! C99 */ 63 | 64 | /* Limits of integral types. */ 65 | #ifndef INT8_MIN 66 | #define INT8_MIN (-128) 67 | #endif 68 | #ifndef INT16_MIN 69 | #define INT16_MIN (-32767-1) 70 | #endif 71 | #ifndef INT32_MIN 72 | #define INT32_MIN (-2147483647-1) 73 | #endif 74 | #ifndef INT8_MAX 75 | #define INT8_MAX (127) 76 | #endif 77 | #ifndef INT16_MAX 78 | #define INT16_MAX (32767) 79 | #endif 80 | #ifndef INT32_MAX 81 | #define INT32_MAX (2147483647) 82 | #endif 83 | #ifndef UINT8_MAX 84 | #define UINT8_MAX (255U) 85 | #endif 86 | #ifndef UINT16_MAX 87 | #define UINT16_MAX (65535U) 88 | #endif 89 | #ifndef UINT32_MAX 90 | #define UINT32_MAX (4294967295U) 91 | #endif 92 | 93 | #endif /* ! FLEXINT_H */ 94 | 95 | #ifdef __cplusplus 96 | 97 | /* The "const" storage-class-modifier is valid. */ 98 | #define YY_USE_CONST 99 | 100 | #else /* ! __cplusplus */ 101 | 102 | /* C99 requires __STDC__ to be defined as 1. */ 103 | #if defined (__STDC__) 104 | 105 | #define YY_USE_CONST 106 | 107 | #endif /* defined (__STDC__) */ 108 | #endif /* ! __cplusplus */ 109 | 110 | #ifdef YY_USE_CONST 111 | #define yyconst const 112 | #else 113 | #define yyconst 114 | #endif 115 | 116 | /* An opaque pointer. */ 117 | #ifndef YY_TYPEDEF_YY_SCANNER_T 118 | #define YY_TYPEDEF_YY_SCANNER_T 119 | typedef void* yyscan_t; 120 | #endif 121 | 122 | /* For convenience, these vars (plus the bison vars far below) 123 | are macros in the reentrant scanner. */ 124 | #define yyin yyg->yyin_r 125 | #define yyout yyg->yyout_r 126 | #define yyextra yyg->yyextra_r 127 | #define yyleng yyg->yyleng_r 128 | #define yytext yyg->yytext_r 129 | #define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) 130 | #define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) 131 | #define yy_flex_debug yyg->yy_flex_debug_r 132 | 133 | /* Size of default input buffer. */ 134 | #ifndef YY_BUF_SIZE 135 | #define YY_BUF_SIZE 16384 136 | #endif 137 | 138 | #ifndef YY_TYPEDEF_YY_BUFFER_STATE 139 | #define YY_TYPEDEF_YY_BUFFER_STATE 140 | typedef struct yy_buffer_state *YY_BUFFER_STATE; 141 | #endif 142 | 143 | #ifndef YY_TYPEDEF_YY_SIZE_T 144 | #define YY_TYPEDEF_YY_SIZE_T 145 | typedef size_t yy_size_t; 146 | #endif 147 | 148 | #ifndef YY_STRUCT_YY_BUFFER_STATE 149 | #define YY_STRUCT_YY_BUFFER_STATE 150 | struct yy_buffer_state 151 | { 152 | FILE *yy_input_file; 153 | 154 | char *yy_ch_buf; /* input buffer */ 155 | char *yy_buf_pos; /* current position in input buffer */ 156 | 157 | /* Size of input buffer in bytes, not including room for EOB 158 | * characters. 159 | */ 160 | yy_size_t yy_buf_size; 161 | 162 | /* Number of characters read into yy_ch_buf, not including EOB 163 | * characters. 164 | */ 165 | yy_size_t yy_n_chars; 166 | 167 | /* Whether we "own" the buffer - i.e., we know we created it, 168 | * and can realloc() it to grow it, and should free() it to 169 | * delete it. 170 | */ 171 | int yy_is_our_buffer; 172 | 173 | /* Whether this is an "interactive" input source; if so, and 174 | * if we're using stdio for input, then we want to use getc() 175 | * instead of fread(), to make sure we stop fetching input after 176 | * each newline. 177 | */ 178 | int yy_is_interactive; 179 | 180 | /* Whether we're considered to be at the beginning of a line. 181 | * If so, '^' rules will be active on the next match, otherwise 182 | * not. 183 | */ 184 | int yy_at_bol; 185 | 186 | int yy_bs_lineno; /**< The line count. */ 187 | int yy_bs_column; /**< The column count. */ 188 | 189 | /* Whether to try to fill the input buffer when we reach the 190 | * end of it. 191 | */ 192 | int yy_fill_buffer; 193 | 194 | int yy_buffer_status; 195 | 196 | }; 197 | #endif /* !YY_STRUCT_YY_BUFFER_STATE */ 198 | 199 | void yyrestart (FILE *input_file ,yyscan_t yyscanner ); 200 | void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); 201 | YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner ); 202 | void yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); 203 | void yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); 204 | void yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); 205 | void yypop_buffer_state (yyscan_t yyscanner ); 206 | 207 | YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner ); 208 | YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner ); 209 | YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len ,yyscan_t yyscanner ); 210 | 211 | void *yyalloc (yy_size_t ,yyscan_t yyscanner ); 212 | void *yyrealloc (void *,yy_size_t ,yyscan_t yyscanner ); 213 | void yyfree (void * ,yyscan_t yyscanner ); 214 | 215 | /* Begin user sect3 */ 216 | 217 | #define yywrap(n) 1 218 | #define YY_SKIP_YYWRAP 219 | 220 | #define yytext_ptr yytext_r 221 | 222 | #ifdef YY_HEADER_EXPORT_START_CONDITIONS 223 | #define INITIAL 0 224 | #define STRING_STATE 1 225 | #define C_COMMENT_STATE 2 226 | #define LINE_COMMENT_STATE 3 227 | 228 | #endif 229 | 230 | #ifndef YY_NO_UNISTD_H 231 | /* Special case for "unistd.h", since it is non-ANSI. We include it way 232 | * down here because we want the user's section 1 to have been scanned first. 233 | * The user has a chance to override it with an option. 234 | */ 235 | #include 236 | #endif 237 | 238 | #define YY_EXTRA_TYPE struct LexerExtra * 239 | 240 | int yylex_init (yyscan_t* scanner); 241 | 242 | int yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner); 243 | 244 | /* Accessor methods to globals. 245 | These are made visible to non-reentrant scanners for convenience. */ 246 | 247 | int yylex_destroy (yyscan_t yyscanner ); 248 | 249 | int yyget_debug (yyscan_t yyscanner ); 250 | 251 | void yyset_debug (int debug_flag ,yyscan_t yyscanner ); 252 | 253 | YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner ); 254 | 255 | void yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner ); 256 | 257 | FILE *yyget_in (yyscan_t yyscanner ); 258 | 259 | void yyset_in (FILE * in_str ,yyscan_t yyscanner ); 260 | 261 | FILE *yyget_out (yyscan_t yyscanner ); 262 | 263 | void yyset_out (FILE * out_str ,yyscan_t yyscanner ); 264 | 265 | yy_size_t yyget_leng (yyscan_t yyscanner ); 266 | 267 | char *yyget_text (yyscan_t yyscanner ); 268 | 269 | int yyget_lineno (yyscan_t yyscanner ); 270 | 271 | void yyset_lineno (int line_number ,yyscan_t yyscanner ); 272 | 273 | YYSTYPE * yyget_lval (yyscan_t yyscanner ); 274 | 275 | void yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner ); 276 | 277 | YYLTYPE *yyget_lloc (yyscan_t yyscanner ); 278 | 279 | void yyset_lloc (YYLTYPE * yylloc_param ,yyscan_t yyscanner ); 280 | 281 | /* Macros after this point can all be overridden by user definitions in 282 | * section 1. 283 | */ 284 | 285 | #ifndef YY_SKIP_YYWRAP 286 | #ifdef __cplusplus 287 | extern "C" int yywrap (yyscan_t yyscanner ); 288 | #else 289 | extern int yywrap (yyscan_t yyscanner ); 290 | #endif 291 | #endif 292 | 293 | #ifndef yytext_ptr 294 | static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner); 295 | #endif 296 | 297 | #ifdef YY_NEED_STRLEN 298 | static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner); 299 | #endif 300 | 301 | #ifndef YY_NO_INPUT 302 | 303 | #endif 304 | 305 | /* Amount of stuff to slurp up with each read. */ 306 | #ifndef YY_READ_BUF_SIZE 307 | #define YY_READ_BUF_SIZE 8192 308 | #endif 309 | 310 | /* Number of entries by which start-condition stack grows. */ 311 | #ifndef YY_START_STACK_INCR 312 | #define YY_START_STACK_INCR 25 313 | #endif 314 | 315 | /* Default declaration of generated scanner - a define so the user can 316 | * easily add parameters. 317 | */ 318 | #ifndef YY_DECL 319 | #define YY_DECL_IS_OURS 1 320 | 321 | extern int yylex \ 322 | (YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,yyscan_t yyscanner); 323 | 324 | #define YY_DECL int yylex \ 325 | (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner) 326 | #endif /* !YY_DECL */ 327 | 328 | /* yy_get_previous_state - get the state just before the EOB char was reached */ 329 | 330 | #undef YY_NEW_FILE 331 | #undef YY_FLUSH_BUFFER 332 | #undef yy_set_bol 333 | #undef yy_new_buffer 334 | #undef yy_set_interactive 335 | #undef YY_DO_BEFORE_ACTION 336 | 337 | #ifdef YY_DECL_IS_OURS 338 | #undef YY_DECL_IS_OURS 339 | #undef YY_DECL 340 | #endif 341 | 342 | #line 155 "lexer.lpp" 343 | 344 | 345 | #line 346 "lexer.h" 346 | #undef yyIN_HEADER 347 | #endif /* yyHEADER_H */ 348 | -------------------------------------------------------------------------------- /internal/c/GraphQLAst.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | /** @generated */ 10 | 11 | #include "c/GraphQLAst.h" 12 | #include "Ast.h" 13 | 14 | using namespace facebook::graphql::ast; 15 | 16 | int GraphQLAstDocument_get_definitions_size(const struct GraphQLAstDocument *node) { 17 | const auto *realNode = (const Document *)node; 18 | return realNode->getDefinitions().size(); 19 | } 20 | const char * GraphQLAstOperationDefinition_get_operation(const struct GraphQLAstOperationDefinition *node) { 21 | const auto *realNode = (const OperationDefinition *)node; 22 | return realNode->getOperation(); 23 | } 24 | const struct GraphQLAstName * GraphQLAstOperationDefinition_get_name(const struct GraphQLAstOperationDefinition *node) { 25 | const auto *realNode = (const OperationDefinition *)node; 26 | return (const struct GraphQLAstName *)realNode->getName(); 27 | } 28 | int GraphQLAstOperationDefinition_get_variable_definitions_size(const struct GraphQLAstOperationDefinition *node) { 29 | const auto *realNode = (const OperationDefinition *)node; 30 | return realNode->getVariableDefinitions() ? realNode->getVariableDefinitions()->size() : 0; 31 | } 32 | int GraphQLAstOperationDefinition_get_directives_size(const struct GraphQLAstOperationDefinition *node) { 33 | const auto *realNode = (const OperationDefinition *)node; 34 | return realNode->getDirectives() ? realNode->getDirectives()->size() : 0; 35 | } 36 | const struct GraphQLAstSelectionSet * GraphQLAstOperationDefinition_get_selection_set(const struct GraphQLAstOperationDefinition *node) { 37 | const auto *realNode = (const OperationDefinition *)node; 38 | return (const struct GraphQLAstSelectionSet *)&realNode->getSelectionSet(); 39 | } 40 | const struct GraphQLAstVariable * GraphQLAstVariableDefinition_get_variable(const struct GraphQLAstVariableDefinition *node) { 41 | const auto *realNode = (const VariableDefinition *)node; 42 | return (const struct GraphQLAstVariable *)&realNode->getVariable(); 43 | } 44 | const struct GraphQLAstType * GraphQLAstVariableDefinition_get_type(const struct GraphQLAstVariableDefinition *node) { 45 | const auto *realNode = (const VariableDefinition *)node; 46 | return (const struct GraphQLAstType *)&realNode->getType(); 47 | } 48 | const struct GraphQLAstValue * GraphQLAstVariableDefinition_get_default_value(const struct GraphQLAstVariableDefinition *node) { 49 | const auto *realNode = (const VariableDefinition *)node; 50 | return (const struct GraphQLAstValue *)realNode->getDefaultValue(); 51 | } 52 | int GraphQLAstSelectionSet_get_selections_size(const struct GraphQLAstSelectionSet *node) { 53 | const auto *realNode = (const SelectionSet *)node; 54 | return realNode->getSelections().size(); 55 | } 56 | const struct GraphQLAstName * GraphQLAstField_get_alias(const struct GraphQLAstField *node) { 57 | const auto *realNode = (const Field *)node; 58 | return (const struct GraphQLAstName *)realNode->getAlias(); 59 | } 60 | const struct GraphQLAstName * GraphQLAstField_get_name(const struct GraphQLAstField *node) { 61 | const auto *realNode = (const Field *)node; 62 | return (const struct GraphQLAstName *)&realNode->getName(); 63 | } 64 | int GraphQLAstField_get_arguments_size(const struct GraphQLAstField *node) { 65 | const auto *realNode = (const Field *)node; 66 | return realNode->getArguments() ? realNode->getArguments()->size() : 0; 67 | } 68 | int GraphQLAstField_get_directives_size(const struct GraphQLAstField *node) { 69 | const auto *realNode = (const Field *)node; 70 | return realNode->getDirectives() ? realNode->getDirectives()->size() : 0; 71 | } 72 | const struct GraphQLAstSelectionSet * GraphQLAstField_get_selection_set(const struct GraphQLAstField *node) { 73 | const auto *realNode = (const Field *)node; 74 | return (const struct GraphQLAstSelectionSet *)realNode->getSelectionSet(); 75 | } 76 | const struct GraphQLAstName * GraphQLAstArgument_get_name(const struct GraphQLAstArgument *node) { 77 | const auto *realNode = (const Argument *)node; 78 | return (const struct GraphQLAstName *)&realNode->getName(); 79 | } 80 | const struct GraphQLAstValue * GraphQLAstArgument_get_value(const struct GraphQLAstArgument *node) { 81 | const auto *realNode = (const Argument *)node; 82 | return (const struct GraphQLAstValue *)&realNode->getValue(); 83 | } 84 | const struct GraphQLAstName * GraphQLAstFragmentSpread_get_name(const struct GraphQLAstFragmentSpread *node) { 85 | const auto *realNode = (const FragmentSpread *)node; 86 | return (const struct GraphQLAstName *)&realNode->getName(); 87 | } 88 | int GraphQLAstFragmentSpread_get_directives_size(const struct GraphQLAstFragmentSpread *node) { 89 | const auto *realNode = (const FragmentSpread *)node; 90 | return realNode->getDirectives() ? realNode->getDirectives()->size() : 0; 91 | } 92 | const struct GraphQLAstNamedType * GraphQLAstInlineFragment_get_type_condition(const struct GraphQLAstInlineFragment *node) { 93 | const auto *realNode = (const InlineFragment *)node; 94 | return (const struct GraphQLAstNamedType *)&realNode->getTypeCondition(); 95 | } 96 | int GraphQLAstInlineFragment_get_directives_size(const struct GraphQLAstInlineFragment *node) { 97 | const auto *realNode = (const InlineFragment *)node; 98 | return realNode->getDirectives() ? realNode->getDirectives()->size() : 0; 99 | } 100 | const struct GraphQLAstSelectionSet * GraphQLAstInlineFragment_get_selection_set(const struct GraphQLAstInlineFragment *node) { 101 | const auto *realNode = (const InlineFragment *)node; 102 | return (const struct GraphQLAstSelectionSet *)&realNode->getSelectionSet(); 103 | } 104 | const struct GraphQLAstName * GraphQLAstFragmentDefinition_get_name(const struct GraphQLAstFragmentDefinition *node) { 105 | const auto *realNode = (const FragmentDefinition *)node; 106 | return (const struct GraphQLAstName *)&realNode->getName(); 107 | } 108 | const struct GraphQLAstNamedType * GraphQLAstFragmentDefinition_get_type_condition(const struct GraphQLAstFragmentDefinition *node) { 109 | const auto *realNode = (const FragmentDefinition *)node; 110 | return (const struct GraphQLAstNamedType *)&realNode->getTypeCondition(); 111 | } 112 | int GraphQLAstFragmentDefinition_get_directives_size(const struct GraphQLAstFragmentDefinition *node) { 113 | const auto *realNode = (const FragmentDefinition *)node; 114 | return realNode->getDirectives() ? realNode->getDirectives()->size() : 0; 115 | } 116 | const struct GraphQLAstSelectionSet * GraphQLAstFragmentDefinition_get_selection_set(const struct GraphQLAstFragmentDefinition *node) { 117 | const auto *realNode = (const FragmentDefinition *)node; 118 | return (const struct GraphQLAstSelectionSet *)&realNode->getSelectionSet(); 119 | } 120 | const struct GraphQLAstName * GraphQLAstVariable_get_name(const struct GraphQLAstVariable *node) { 121 | const auto *realNode = (const Variable *)node; 122 | return (const struct GraphQLAstName *)&realNode->getName(); 123 | } 124 | const char * GraphQLAstIntValue_get_value(const struct GraphQLAstIntValue *node) { 125 | const auto *realNode = (const IntValue *)node; 126 | return realNode->getValue(); 127 | } 128 | const char * GraphQLAstFloatValue_get_value(const struct GraphQLAstFloatValue *node) { 129 | const auto *realNode = (const FloatValue *)node; 130 | return realNode->getValue(); 131 | } 132 | const char * GraphQLAstStringValue_get_value(const struct GraphQLAstStringValue *node) { 133 | const auto *realNode = (const StringValue *)node; 134 | return realNode->getValue(); 135 | } 136 | int GraphQLAstBooleanValue_get_value(const struct GraphQLAstBooleanValue *node) { 137 | const auto *realNode = (const BooleanValue *)node; 138 | return realNode->getValue(); 139 | } 140 | const char * GraphQLAstEnumValue_get_value(const struct GraphQLAstEnumValue *node) { 141 | const auto *realNode = (const EnumValue *)node; 142 | return realNode->getValue(); 143 | } 144 | int GraphQLAstArrayValue_get_values_size(const struct GraphQLAstArrayValue *node) { 145 | const auto *realNode = (const ArrayValue *)node; 146 | return realNode->getValues().size(); 147 | } 148 | int GraphQLAstObjectValue_get_fields_size(const struct GraphQLAstObjectValue *node) { 149 | const auto *realNode = (const ObjectValue *)node; 150 | return realNode->getFields().size(); 151 | } 152 | const struct GraphQLAstName * GraphQLAstObjectField_get_name(const struct GraphQLAstObjectField *node) { 153 | const auto *realNode = (const ObjectField *)node; 154 | return (const struct GraphQLAstName *)&realNode->getName(); 155 | } 156 | const struct GraphQLAstValue * GraphQLAstObjectField_get_value(const struct GraphQLAstObjectField *node) { 157 | const auto *realNode = (const ObjectField *)node; 158 | return (const struct GraphQLAstValue *)&realNode->getValue(); 159 | } 160 | const struct GraphQLAstName * GraphQLAstDirective_get_name(const struct GraphQLAstDirective *node) { 161 | const auto *realNode = (const Directive *)node; 162 | return (const struct GraphQLAstName *)&realNode->getName(); 163 | } 164 | int GraphQLAstDirective_get_arguments_size(const struct GraphQLAstDirective *node) { 165 | const auto *realNode = (const Directive *)node; 166 | return realNode->getArguments() ? realNode->getArguments()->size() : 0; 167 | } 168 | const struct GraphQLAstName * GraphQLAstNamedType_get_name(const struct GraphQLAstNamedType *node) { 169 | const auto *realNode = (const NamedType *)node; 170 | return (const struct GraphQLAstName *)&realNode->getName(); 171 | } 172 | const struct GraphQLAstType * GraphQLAstListType_get_type(const struct GraphQLAstListType *node) { 173 | const auto *realNode = (const ListType *)node; 174 | return (const struct GraphQLAstType *)&realNode->getType(); 175 | } 176 | const struct GraphQLAstType * GraphQLAstNonNullType_get_type(const struct GraphQLAstNonNullType *node) { 177 | const auto *realNode = (const NonNullType *)node; 178 | return (const struct GraphQLAstType *)&realNode->getType(); 179 | } 180 | const char * GraphQLAstName_get_value(const struct GraphQLAstName *node) { 181 | const auto *realNode = (const Name *)node; 182 | return realNode->getValue(); 183 | } 184 | -------------------------------------------------------------------------------- /internal/JsonVisitor.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #include "position.hh" 11 | #include "JsonVisitor.h" 12 | 13 | #include 14 | #include 15 | 16 | namespace facebook { 17 | namespace graphql { 18 | namespace ast { 19 | namespace visitor { 20 | 21 | 22 | // Method invariant: printed_ contains strings for this node's children. 23 | void JsonVisitor::printLocation(const yy::location &location) 24 | { 25 | out_ << "{\"start\":" << location.begin.column 26 | << ",\"end\":" << location.end.column << '}'; 27 | } 28 | 29 | void JsonVisitor::startPrintingNode(const char *kind, const yy::location &location) { 30 | out_.str(""); 31 | out_ << "{\"kind\":\"" << kind << "\",\"loc\":"; 32 | printLocation(location); 33 | out_ << ','; 34 | return; 35 | } 36 | 37 | void JsonVisitor::printChildArray( 38 | const std::vector::const_iterator &childIterator, 39 | size_t numChildren) { 40 | out_ << '['; 41 | for (int ii = 0; ii < numChildren; ++ii) { 42 | if (ii != 0) { 43 | out_ << ','; 44 | } 45 | out_ << *(childIterator + ii); 46 | } 47 | out_ << ']'; 48 | } 49 | 50 | void JsonVisitor::visitNode() { 51 | printed_.emplace_back(); 52 | } 53 | 54 | void JsonVisitor::endVisitNode() { 55 | printed_.pop_back(); 56 | printed_.back().emplace_back(out_.str()); 57 | } 58 | 59 | bool JsonVisitor::visitDocument(const Document &document) { 60 | visitNode(); 61 | return true; 62 | } 63 | 64 | void JsonVisitor::endVisitDocument(const Document &document) { 65 | startPrintingNode("Document", document.getLocation()); 66 | out_ << "\"definitions\":"; 67 | 68 | const auto &children = printed_.back(); 69 | printChildArray(children.begin(), children.size()); 70 | out_ << '}'; 71 | printed_.pop_back(); 72 | assert(printed_.empty()); 73 | } 74 | 75 | bool JsonVisitor::visitOperationDefinition(const OperationDefinition &operationDefinition) { 76 | visitNode(); 77 | return true; 78 | } 79 | 80 | void JsonVisitor::endVisitOperationDefinition(const OperationDefinition &operationDefinition) { 81 | startPrintingNode("OperationDefinition", operationDefinition.getLocation()); 82 | 83 | out_ << "\"operation\":\"" << operationDefinition.getOperation() 84 | << '\"'; 85 | 86 | const auto &children = printed_.back(); 87 | 88 | auto nextChild = children.begin(); 89 | 90 | out_ << ",\"name\": " 91 | << (operationDefinition.getName() ? *nextChild++ : "null"); 92 | 93 | out_ << ",\"variableDefinitions\":"; 94 | const auto *variableDefinitions = operationDefinition.getVariableDefinitions(); 95 | if (variableDefinitions != nullptr) { 96 | printChildArray(nextChild, variableDefinitions->size()); 97 | nextChild += variableDefinitions->size(); 98 | } else { 99 | out_ << "null"; 100 | } 101 | 102 | out_ << ",\"directives\":"; 103 | const auto *directives = operationDefinition.getDirectives(); 104 | if (directives != nullptr) { 105 | printChildArray(nextChild, directives->size()); 106 | nextChild += directives->size(); 107 | } else { 108 | out_ << "null"; 109 | } 110 | 111 | out_ << ",\"selectionSet\":" << *nextChild++; 112 | 113 | assert(nextChild == children.end()); 114 | out_ << "}"; 115 | 116 | endVisitNode(); 117 | } 118 | 119 | bool JsonVisitor::visitVariableDefinition(const VariableDefinition &variableDefinition) { 120 | visitNode(); 121 | return true; 122 | } 123 | 124 | void JsonVisitor::endVisitVariableDefinition(const VariableDefinition &variableDefinition) { 125 | startPrintingNode("VariableDefinition", variableDefinition.getLocation()); 126 | 127 | const auto &children = printed_.back(); 128 | out_ << "\"variable\":" << children[0]; 129 | out_ << ",\"type\":" << children[1]; 130 | out_ << ",\"defaultValue\":"; 131 | if (children.size() > 2) { 132 | assert(children.size() == 3); 133 | out_ << children[2]; 134 | } else { 135 | assert(children.size() == 2); 136 | out_ << "null"; 137 | } 138 | 139 | out_ << '}'; 140 | 141 | endVisitNode(); 142 | } 143 | 144 | bool JsonVisitor::visitSelectionSet(const SelectionSet &selectionSet) { 145 | visitNode(); 146 | return true; 147 | } 148 | 149 | void JsonVisitor::endVisitSelectionSet(const SelectionSet &selectionSet) { 150 | startPrintingNode("SelectionSet", selectionSet.getLocation()); 151 | 152 | out_ << "\"selections\":"; 153 | 154 | const auto &children = printed_.back(); 155 | printChildArray(children.begin(), children.size()); 156 | 157 | out_ << '}'; 158 | 159 | endVisitNode(); 160 | } 161 | 162 | bool JsonVisitor::visitField(const Field &field) { 163 | visitNode(); 164 | return true; 165 | } 166 | 167 | void JsonVisitor::endVisitField(const Field &field) { 168 | startPrintingNode("Field", field.getLocation()); 169 | 170 | const auto &children = printed_.back(); 171 | auto nextChild = children.begin(); 172 | 173 | out_ << "\"alias\":"; 174 | if (field.getAlias() != nullptr) { 175 | out_ << *nextChild++; 176 | } else { 177 | out_ << "null"; 178 | } 179 | 180 | out_ << ",\"name\":" << *nextChild++; 181 | 182 | out_ << ",\"arguments\":"; 183 | const auto *arguments = field.getArguments(); 184 | if (arguments != nullptr) { 185 | printChildArray(nextChild, arguments->size()); 186 | nextChild += arguments->size(); 187 | } else { 188 | out_ << "null"; 189 | } 190 | 191 | out_ << ",\"directives\":"; 192 | const auto *directives = field.getDirectives(); 193 | if (directives != nullptr) { 194 | printChildArray(nextChild, directives->size()); 195 | nextChild += directives->size(); 196 | } else { 197 | out_ << "null"; 198 | } 199 | 200 | out_ << ",\"selectionSet\":"; 201 | if (field.getSelectionSet() != nullptr) { 202 | out_ << *nextChild++; 203 | } else { 204 | out_ << "null"; 205 | } 206 | 207 | out_ << '}'; 208 | 209 | endVisitNode(); 210 | } 211 | 212 | bool JsonVisitor::visitArgument(const Argument &argument) { 213 | visitNode(); 214 | return true; 215 | } 216 | 217 | void JsonVisitor::endVisitArgument(const Argument &argument) { 218 | startPrintingNode("Argument", argument.getLocation()); 219 | 220 | const auto &children = printed_.back(); 221 | out_ << "\"name\":" << children[0] << ",\"value\":" << children[1]; 222 | 223 | out_ << '}'; 224 | 225 | endVisitNode(); 226 | } 227 | 228 | bool JsonVisitor::visitFragmentSpread(const FragmentSpread &fragmentSpread) { 229 | visitNode(); 230 | return true; 231 | } 232 | 233 | void JsonVisitor::endVisitFragmentSpread(const FragmentSpread &fragmentSpread) { 234 | startPrintingNode("FragmentSpread", fragmentSpread.getLocation()); 235 | 236 | const auto &children = printed_.back(); 237 | out_ << "\"name\":" << children[0]; 238 | 239 | out_ << ",\"directives\":"; 240 | const auto *directives = fragmentSpread.getDirectives(); 241 | if (directives != nullptr) { 242 | printChildArray(children.begin() + 1, directives->size()); 243 | } else { 244 | out_ << "null"; 245 | } 246 | 247 | out_ << '}'; 248 | 249 | endVisitNode(); 250 | } 251 | 252 | bool JsonVisitor::visitInlineFragment(const InlineFragment &inlineFragment) { 253 | visitNode(); 254 | return true; 255 | } 256 | 257 | void JsonVisitor::endVisitInlineFragment(const InlineFragment &inlineFragment) { 258 | startPrintingNode("InlineFragment", inlineFragment.getLocation()); 259 | 260 | const auto &children = printed_.back(); 261 | 262 | out_ << "\"typeCondition\":" << children[0]; 263 | 264 | out_ << ",\"directives\":"; 265 | auto nextChild = children.begin() + 1; 266 | const auto *directives = inlineFragment.getDirectives(); 267 | if (directives != nullptr) { 268 | printChildArray(nextChild, directives->size()); 269 | nextChild += directives->size(); 270 | } else { 271 | out_ << "null"; 272 | } 273 | 274 | out_ << ",\"selectionSet\":" << *nextChild++; 275 | 276 | out_ << '}'; 277 | 278 | endVisitNode(); 279 | } 280 | 281 | bool JsonVisitor::visitFragmentDefinition(const FragmentDefinition &fragmentDefinition) { 282 | visitNode(); 283 | return true; 284 | } 285 | 286 | void JsonVisitor::endVisitFragmentDefinition(const FragmentDefinition &fragmentDefinition) { 287 | startPrintingNode("FragmentDefinition", fragmentDefinition.getLocation()); 288 | 289 | const auto &children = printed_.back(); 290 | 291 | out_ << "\"name\":" << children[0]; 292 | out_ << ",\"typeCondition\":" << children[1]; 293 | 294 | auto nextChild = children.begin() + 2; 295 | 296 | out_ << ",\"directives\":"; 297 | const auto *directives = fragmentDefinition.getDirectives(); 298 | if (directives != nullptr) { 299 | printChildArray(nextChild, directives->size()); 300 | nextChild += directives->size(); 301 | } else { 302 | out_ << "null"; 303 | } 304 | 305 | out_ << ",\"selectionSet\":" << *nextChild++; 306 | 307 | out_ << '}'; 308 | 309 | endVisitNode(); 310 | } 311 | 312 | bool JsonVisitor::visitVariable(const Variable &variable) { 313 | visitNode(); 314 | return true; 315 | } 316 | 317 | void JsonVisitor::endVisitVariable(const Variable &variable) { 318 | startPrintingNode("Variable", variable.getLocation()); 319 | 320 | out_ << "\"name\":" << printed_.back()[0] << '}'; 321 | 322 | endVisitNode(); 323 | } 324 | 325 | template 326 | void JsonVisitor::endVisitValueRepresentedAsString(const char *valueKind, const ValueType &value) { 327 | startPrintingNode(valueKind, value.getLocation()); 328 | 329 | out_ << "\"value\":\"" << value.getValue() << "\"}"; 330 | printed_.back().emplace_back(out_.str()); 331 | } 332 | 333 | void JsonVisitor::endVisitIntValue(const IntValue &intValue) { 334 | endVisitValueRepresentedAsString("IntValue", intValue); 335 | } 336 | 337 | void JsonVisitor::endVisitFloatValue(const FloatValue &floatValue) { 338 | endVisitValueRepresentedAsString("FloatValue", floatValue); 339 | } 340 | 341 | void JsonVisitor::endVisitStringValue(const StringValue &stringValue) { 342 | endVisitValueRepresentedAsString("StringValue", stringValue); 343 | } 344 | 345 | void JsonVisitor::endVisitEnumValue(const EnumValue &enumValue) { 346 | endVisitValueRepresentedAsString("EnumValue", enumValue); 347 | } 348 | 349 | void JsonVisitor::endVisitBooleanValue(const BooleanValue &booleanValue) { 350 | startPrintingNode("BooleanValue", booleanValue.getLocation()); 351 | 352 | out_ << "\"value\":" << (booleanValue.getValue() ? "true" : "false") << '}'; 353 | printed_.back().emplace_back(out_.str()); 354 | } 355 | 356 | bool JsonVisitor::visitArrayValue(const ArrayValue &arrayValue) { 357 | visitNode(); 358 | return true; 359 | } 360 | 361 | void JsonVisitor::endVisitArrayValue(const ArrayValue &arrayValue) { 362 | startPrintingNode("ArrayValue", arrayValue.getLocation()); 363 | 364 | out_ << "\"values\":"; 365 | printChildArray(printed_.back().begin(), arrayValue.getValues().size()); 366 | 367 | out_ << '}'; 368 | 369 | endVisitNode(); 370 | } 371 | 372 | bool JsonVisitor::visitObjectValue(const ObjectValue &objectValue) { 373 | visitNode(); 374 | return true; 375 | } 376 | 377 | void JsonVisitor::endVisitObjectValue(const ObjectValue &objectValue) { 378 | startPrintingNode("ObjectValue", objectValue.getLocation()); 379 | 380 | out_ << "\"fields\":"; 381 | printChildArray(printed_.back().begin(), objectValue.getFields().size()); 382 | 383 | out_ << '}'; 384 | 385 | endVisitNode(); 386 | } 387 | 388 | bool JsonVisitor::visitObjectField(const ObjectField &objectField) { 389 | visitNode(); 390 | return true; 391 | } 392 | 393 | void JsonVisitor::endVisitObjectField(const ObjectField &objectField) { 394 | startPrintingNode("ObjectField", objectField.getLocation()); 395 | 396 | const auto &children = printed_.back(); 397 | 398 | out_ << "\"name\":" << children[0] << ",\"value\":" << children[1]; 399 | 400 | out_ << '}'; 401 | 402 | endVisitNode(); 403 | } 404 | 405 | bool JsonVisitor::visitDirective(const Directive &directive) { 406 | visitNode(); 407 | return true; 408 | } 409 | 410 | void JsonVisitor::endVisitDirective(const Directive &directive) { 411 | startPrintingNode("Directive", directive.getLocation()); 412 | 413 | const auto &children = printed_.back(); 414 | out_ << "\"name\":" << children[0]; 415 | 416 | auto nextChild = children.begin() + 1; 417 | out_ << ",\"arguments\":"; 418 | const auto *arguments = directive.getArguments(); 419 | if (arguments != nullptr) { 420 | printChildArray(nextChild, arguments->size()); 421 | } else { 422 | out_ << "null"; 423 | } 424 | 425 | out_ << '}'; 426 | 427 | endVisitNode(); 428 | } 429 | 430 | void JsonVisitor::endVisitName(const Name &name) { 431 | endVisitValueRepresentedAsString("Name", name); 432 | } 433 | 434 | bool JsonVisitor::visitNamedType(const NamedType &namedType) { 435 | visitNode(); 436 | return true; 437 | } 438 | 439 | void JsonVisitor::endVisitNamedType(const NamedType &namedType) { 440 | startPrintingNode("NamedType", namedType.getLocation()); 441 | 442 | out_ << "\"name\":" << printed_.back()[0]; 443 | 444 | out_ << '}'; 445 | 446 | endVisitNode(); 447 | } 448 | 449 | bool JsonVisitor::visitListType(const ListType &listType) { 450 | visitNode(); 451 | return true; 452 | } 453 | 454 | void JsonVisitor::endVisitListType(const ListType &listType) { 455 | startPrintingNode("ListType", listType.getLocation()); 456 | 457 | out_ << "\"type\":" << printed_.back()[0]; 458 | 459 | out_ << '}'; 460 | 461 | endVisitNode(); 462 | } 463 | 464 | bool JsonVisitor::visitNonNullType(const NonNullType &nonNullType) { 465 | visitNode(); 466 | return true; 467 | } 468 | 469 | void JsonVisitor::endVisitNonNullType(const NonNullType &nonNullType) { 470 | startPrintingNode("NonNullType", nonNullType.getLocation()); 471 | 472 | out_ << "\"type\":" << printed_.back()[0]; 473 | 474 | out_ << '}'; 475 | 476 | endVisitNode(); 477 | } 478 | 479 | } 480 | } 481 | } 482 | } 483 | -------------------------------------------------------------------------------- /internal/parser.ypp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | %require "3" 11 | 12 | %skeleton "lalr1.cc" 13 | 14 | %defines 15 | %define parser_class_name {GraphQLParserImpl} 16 | 17 | %define api.token.prefix {TOK_} 18 | 19 | %define parse.error verbose 20 | 21 | %code requires 22 | { 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include "Ast.h" 30 | 31 | using facebook::graphql::ast::Node; 32 | using facebook::graphql::ast::Name; 33 | using facebook::graphql::ast::Definition; 34 | using facebook::graphql::ast::Document; 35 | using facebook::graphql::ast::OperationDefinition; 36 | using facebook::graphql::ast::VariableDefinition; 37 | using facebook::graphql::ast::Variable; 38 | using facebook::graphql::ast::SelectionSet; 39 | using facebook::graphql::ast::Selection; 40 | using facebook::graphql::ast::Field; 41 | using facebook::graphql::ast::Argument; 42 | using facebook::graphql::ast::FragmentSpread; 43 | using facebook::graphql::ast::InlineFragment; 44 | using facebook::graphql::ast::FragmentDefinition; 45 | using facebook::graphql::ast::Value; 46 | using facebook::graphql::ast::IntValue; 47 | using facebook::graphql::ast::FloatValue; 48 | using facebook::graphql::ast::StringValue; 49 | using facebook::graphql::ast::BooleanValue; 50 | using facebook::graphql::ast::EnumValue; 51 | using facebook::graphql::ast::ArrayValue; 52 | using facebook::graphql::ast::ObjectValue; 53 | using facebook::graphql::ast::ObjectField; 54 | using facebook::graphql::ast::Directive; 55 | using facebook::graphql::ast::Type; 56 | using facebook::graphql::ast::NamedType; 57 | using facebook::graphql::ast::ListType; 58 | using facebook::graphql::ast::NonNullType; 59 | 60 | union yystype { \ 61 | const char *str; \ 62 | const char *heapStr; \ 63 | Name *name; \ 64 | Definition *definition; \ 65 | Document *document; \ 66 | OperationDefinition *operationDefinition; \ 67 | VariableDefinition *variableDefinition; \ 68 | Variable *variable; \ 69 | SelectionSet *selectionSet; \ 70 | Selection *selection; \ 71 | Field *field; \ 72 | Argument *argument; \ 73 | FragmentSpread *fragmentSpread; \ 74 | InlineFragment *inlineFragment; \ 75 | FragmentDefinition *fragmentDefinition; \ 76 | Value *value; \ 77 | IntValue *intValue; \ 78 | FloatValue *floatValue; \ 79 | StringValue *stringValue; \ 80 | BooleanValue *booleanValue; \ 81 | EnumValue *enumValue; \ 82 | ArrayValue *arrayValue; \ 83 | ObjectValue *objectValue; \ 84 | ObjectField *objectField; \ 85 | Directive *directive; \ 86 | Type *type; \ 87 | NamedType *namedType; \ 88 | ListType *listType; \ 89 | NonNullType *nonNullType; \ 90 | \ 91 | std::vector> *nameList; \ 92 | std::vector> *definitionList; \ 93 | std::vector> *documentList; \ 94 | std::vector> *operationDefinitionList; \ 95 | std::vector> *variableDefinitionList; \ 96 | std::vector> *variableList; \ 97 | std::vector> *selectionSetList; \ 98 | std::vector> *selectionList; \ 99 | std::vector> *fieldList; \ 100 | std::vector> *argumentList; \ 101 | std::vector> *fragmentSpreadList; \ 102 | std::vector> *inlineFragmentList; \ 103 | std::vector> *fragmentDefinitionList; \ 104 | std::vector> *valueList; \ 105 | std::vector> *intValueList; \ 106 | std::vector> *floatValueList; \ 107 | std::vector> *stringValueList; \ 108 | std::vector> *booleanValueList; \ 109 | std::vector> *enumValueList; \ 110 | std::vector> *arrayValueList; \ 111 | std::vector> *objectValueList; \ 112 | std::vector> *objectFieldList; \ 113 | std::vector> *directiveList; \ 114 | std::vector> *typeList; \ 115 | std::vector> *listTypeList; \ 116 | std::vector> *nonNullTypeList; \ 117 | }; 118 | 119 | #define YYSTYPE union yystype 120 | #define YYLTYPE yy::location 121 | } 122 | 123 | %lex-param { void *scanner } 124 | %parse-param { Node **outAST } { const char **outError } { void *scanner } 125 | 126 | %locations 127 | 128 | %code 129 | { 130 | #include "lexer.h" 131 | #include "syntaxdefs.h" 132 | } 133 | 134 | %token EOF 0 135 | %token FALSE "false" 136 | %token FRAGMENT "fragment" 137 | %token MUTATION "mutation" 138 | %token NULL "null" 139 | %token QUERY "query" 140 | %token ON "on" 141 | %token TRUE "true" 142 | %token BANG "!" 143 | %token LPAREN "(" 144 | %token RPAREN ")" 145 | %token ELLIPSIS "..." 146 | %token COLON ":" 147 | %token EQUAL "=" 148 | %token AT "@" 149 | %token LBRACKET "[" 150 | %token RBRACKET "]" 151 | %token LBRACE "{" 152 | %token PIPE "|" 153 | %token RBRACE "}" 154 | 155 | %token VARIABLE 156 | %token INTEGER 157 | %token FLOAT 158 | %token STRING 159 | %token IDENTIFIER 160 | 161 | %type variable 162 | %type int_value 163 | %type float_value 164 | %type string_value 165 | 166 | %type start 167 | %type document 168 | %type fragment_name 169 | %type name 170 | %type name_opt 171 | 172 | %type definition_list 173 | %type definition 174 | 175 | %type operation_definition 176 | %type variable_definitions 177 | %type variable_definition_list 178 | %type variable_definition 179 | %type default_value_opt 180 | %type default_value 181 | %type selection_set 182 | %type selection_set_opt 183 | %type selection_list 184 | %type selection 185 | %type field 186 | %type arguments_opt 187 | %type arguments 188 | %type argument_list 189 | %type argument 190 | 191 | %type fragment_spread 192 | %type inline_fragment 193 | %type fragment_definition 194 | %type type_condition 195 | 196 | %type value 197 | %type value_const 198 | %type boolean_value 199 | %type enum_value 200 | %type array_value 201 | %type array_value_const 202 | %type value_list 203 | %type value_const_list 204 | %type object_value 205 | %type object_value_const 206 | %type object_field_list 207 | %type object_field_const_list 208 | %type object_field 209 | %type object_field_const 210 | 211 | 212 | %type directives 213 | %type directives_opt 214 | %type directive_list 215 | %type directive 216 | 217 | %type type 218 | %type type_name 219 | %type list_type 220 | %type non_null_type 221 | 222 | %type operation_type 223 | 224 | %destructor { } 225 | %destructor { free((void *)$$); } 226 | %destructor { } /* we steal it and put it in outAST, don't free! */ 227 | %destructor { delete $$; } <*> 228 | 229 | %printer { yyoutput << $$; } 230 | 231 | %% 232 | 233 | start: document { *outAST = $1; } 234 | ; 235 | 236 | /* All of the non-identifier tokens are to accommodate various flavors 237 | of name that don't include those tokens. */ 238 | fragment_name: IDENTIFIER { $$ = new Name(@1, strdup($1)); } 239 | | FALSE { $$ = new Name(@1, strdup($1)); } 240 | | FRAGMENT { $$ = new Name(@1, strdup($1)); } 241 | | MUTATION { $$ = new Name(@1, strdup($1)); } 242 | | NULL { $$ = new Name(@1, strdup($1)); } 243 | | QUERY { $$ = new Name(@1, strdup($1)); } 244 | | TRUE { $$ = new Name(@1, strdup($1)); } 245 | ; 246 | 247 | name: fragment_name 248 | | ON { $$ = new Name(@1, strdup($1)); } 249 | ; 250 | 251 | name_opt: 252 | %empty {$$ = nullptr;} 253 | | name 254 | ; 255 | 256 | /* 8.3.1 Document */ 257 | 258 | document: definition_list { $$ = new Document(@$, $1); } 259 | ; 260 | 261 | definition_list:definition { $$ = new std::vector>(); $$->emplace_back($1); } 262 | | definition_list definition { $1->emplace_back($2); $$ = $1; } 263 | ; 264 | 265 | definition: operation_definition { $$ = static_cast($1); } 266 | | fragment_definition { $$ = static_cast($1);} 267 | ; 268 | 269 | 270 | /* 8.3.2 Operations */ 271 | operation_definition: 272 | selection_set { $$ = new OperationDefinition(@$, strdup("query"), nullptr, nullptr, nullptr, $1); } 273 | | operation_type name_opt selection_set { $$ = new OperationDefinition(@$, $1, $2, nullptr, nullptr, $3); } 274 | | operation_type name_opt variable_definitions selection_set { $$ = new OperationDefinition(@$, $1, $2, $3, nullptr, $4); } 275 | | operation_type name_opt directives selection_set { $$ = new OperationDefinition(@$, $1, $2, nullptr, $3, $4); } 276 | | operation_type name_opt variable_definitions directives selection_set { $$ = new OperationDefinition(@$, $1, $2, $3, $4, $5); } 277 | ; 278 | 279 | operation_type: QUERY { $$ = strdup($1); } 280 | | MUTATION { $$ = strdup($1); } 281 | ; 282 | 283 | variable_definitions: 284 | "(" variable_definition_list ")" { $$ = $2; } 285 | ; 286 | 287 | variable_definition_list: 288 | variable_definition { $$ = new std::vector>(); $$->emplace_back($1); } 289 | | variable_definition_list variable_definition { $1->emplace_back($2); $$ = $1; } 290 | ; 291 | 292 | variable: VARIABLE { $$ = new Variable(@$, new Name(@1, strdup($1))); } 293 | ; 294 | 295 | variable_definition: 296 | variable ":" type default_value_opt { $$ = new VariableDefinition(@$, $1, $3, $4); } 297 | ; 298 | 299 | default_value_opt: 300 | %empty { $$ = nullptr; } 301 | | default_value 302 | ; 303 | 304 | default_value: "=" value_const { $$ = $2; } 305 | ; 306 | 307 | selection_set: 308 | "{" selection_list "}" { $$ = new SelectionSet(@$, $2); } 309 | ; 310 | 311 | selection_set_opt: 312 | %empty { $$ = nullptr; } 313 | | selection_set 314 | ; 315 | selection_list: selection { $$ = new std::vector>(); $$->emplace_back($1); } 316 | | selection_list selection { $1->emplace_back($2); $$ = $1; } 317 | ; 318 | 319 | selection: field { $$ = static_cast($1); } 320 | | fragment_spread { $$ = static_cast($1); } 321 | | inline_fragment { $$ = static_cast($1); } 322 | ; 323 | 324 | field: name arguments_opt directives_opt selection_set_opt { $$ = new Field(@$, nullptr, $1, $2, $3, $4); } 325 | | name ":" name arguments_opt directives_opt selection_set_opt { $$ = new Field(@$, $1, $3, $4, $5, $6); } 326 | ; 327 | 328 | arguments: "(" argument_list ")" { $$ = $2; } 329 | ; 330 | 331 | arguments_opt: %empty { $$ = nullptr; } 332 | | arguments { $$ = $1; } 333 | ; 334 | 335 | argument_list: argument { $$ = new std::vector>(); $$->emplace_back($1); } 336 | | argument_list argument { $1->emplace_back($2); $$ = $1; } 337 | ; 338 | 339 | argument: name ":" value { $$ = new Argument(@$, $1, $3); } 340 | ; 341 | 342 | /* 8.3.3 Fragments */ 343 | fragment_spread: 344 | "..." fragment_name directives_opt { $$ = new FragmentSpread(@$, $2, $3); } 345 | ; 346 | 347 | inline_fragment: 348 | "..." "on" type_condition directives_opt selection_set { $$ = new InlineFragment(@$, $3, $4, $5); } 349 | ; 350 | 351 | fragment_definition: 352 | "fragment" fragment_name "on" type_condition directives_opt selection_set { $$ = new FragmentDefinition(@$, $2, $4, $5, $6); } 353 | ; 354 | 355 | type_condition: type_name 356 | ; 357 | 358 | /* 8.3.4 Values */ 359 | value: variable { $$ = static_cast($1); } 360 | | int_value { $$ = static_cast($1); } 361 | | float_value { $$ = static_cast($1); } 362 | | string_value { $$ = static_cast($1); } 363 | | boolean_value { $$ = static_cast($1); } 364 | | enum_value { $$ = static_cast($1); } 365 | | array_value { $$ = static_cast($1); } 366 | | object_value { $$ = static_cast($1); } 367 | ; 368 | 369 | int_value: INTEGER { $$ = new IntValue(@$, strdup($1)); } 370 | ; 371 | 372 | float_value: FLOAT { $$ = new FloatValue(@$, strdup($1)); } 373 | ; 374 | 375 | string_value: STRING { $$ = new StringValue(@$, strdup($1)); } 376 | ; 377 | 378 | value_const: int_value { $$ = static_cast($1); } 379 | | float_value { $$ = static_cast($1); } 380 | | string_value { $$ = static_cast($1); } 381 | | boolean_value { $$ = static_cast($1); } 382 | | enum_value { $$ = static_cast($1); } 383 | | array_value_const { $$ = static_cast($1); } 384 | | object_value_const { $$ = static_cast($1); } 385 | ; 386 | 387 | boolean_value: TRUE { $$ = new BooleanValue(@$, true); } 388 | | FALSE { $$ = new BooleanValue(@$, false); } 389 | ; 390 | 391 | enum_value: IDENTIFIER { $$ = new EnumValue(@$, strdup($1)); } 392 | | FRAGMENT { $$ = new EnumValue(@$, strdup($1)); } 393 | | MUTATION { $$ = new EnumValue(@$, strdup($1)); } 394 | | ON { $$ = new EnumValue(@$, strdup($1)); } 395 | | QUERY { $$ = new EnumValue(@$, strdup($1)); } 396 | ; 397 | 398 | /* 8.3.4.1 Array Value */ 399 | 400 | /* REVIEW: the empty case is inefficient; consider implementing 401 | ArrayValue manually. Don't forget to also do array_value_const. */ 402 | array_value: "[" "]" { $$ = new ArrayValue(@$, new std::vector>()); } 403 | | "[" value_list "]" { $$ = new ArrayValue(@$, $2); } 404 | ; 405 | 406 | value_list: value { $$ = new std::vector>(); $$->emplace_back($1); } 407 | | value_list value { $1->emplace_back($2); $$ = $1; } 408 | ; 409 | 410 | array_value_const: 411 | "[" "]" { $$ = new ArrayValue(@$, new std::vector>()); } 412 | | "[" value_const_list "]" { $$ = new ArrayValue(@$, $2); } 413 | ; 414 | 415 | value_const_list: 416 | value_const { $$ = new std::vector>(); $$->emplace_back($1); } 417 | | value_const_list value_const { $1->emplace_back($2); $$ = $1; } 418 | ; 419 | 420 | /* 8.3.4.2 Object Value */ 421 | /* REVIEW: Inefficient, like ArrayValue. */ 422 | object_value: "{" "}" { $$ = new ObjectValue(@$, new std::vector>()); } 423 | | "{" object_field_list "}" { $$ = new ObjectValue(@$, $2); } 424 | ; 425 | 426 | object_field_list: 427 | object_field { $$ = new std::vector>(); $$->emplace_back($1); } 428 | | object_field_list object_field { $1->emplace_back($2); $$ = $1; } 429 | ; 430 | 431 | object_field: name ":" value { $$ = new ObjectField(@$, $1, $3); } 432 | ; 433 | 434 | object_value_const: 435 | "{" "}" { $$ = new ObjectValue(@$, new std::vector>()); } 436 | | "{" object_field_const_list "}" { $$ = new ObjectValue(@$, $2); } 437 | ; 438 | 439 | object_field_const_list: 440 | object_field_const { $$ = new std::vector>(); $$->emplace_back($1); } 441 | | object_field_const_list object_field_const { $1->emplace_back($2); $$ = $1; } 442 | ; 443 | 444 | object_field_const: name ":" value_const { $$ = new ObjectField(@$, $1, $3); } 445 | ; 446 | 447 | /* 8.3.5 Directives */ 448 | 449 | directives: directive_list 450 | ; 451 | 452 | directives_opt: %empty { $$ = nullptr; } 453 | | directives 454 | ; 455 | 456 | directive_list: directive { $$ = new std::vector>(); $$->emplace_back($1); } 457 | | directive_list directive { $1->emplace_back($2); $$ = $1; } 458 | ; 459 | 460 | directive: "@" name arguments_opt { $$ = new Directive(@$, $2, $3); } 461 | ; 462 | 463 | /* 8.3.6 Types */ 464 | 465 | type: type_name { $$ = static_cast($1); } 466 | | list_type { $$ = static_cast($1); } 467 | | non_null_type { $$ = static_cast($1); } 468 | ; 469 | 470 | type_name: name { $$ = new NamedType(@$, $1); } 471 | ; 472 | 473 | list_type: "[" type "]" { $$ = new ListType(@$, $2); } 474 | ; 475 | 476 | non_null_type: type_name "!" { $$ = new NonNullType(@$, $1); } 477 | | list_type "!" { $$ = new NonNullType(@$, $1); } 478 | ; 479 | %% 480 | void yy::GraphQLParserImpl::error(const yy::location &loc, const std::string &str) { 481 | std::ostringstream out; 482 | out << loc << ": " << str; 483 | if (outError) { 484 | *outError = strdup(out.str().c_str()); 485 | } 486 | } 487 | 488 | /* Workaround for syntax_error ctor being marked inline, which causes link 489 | errors if used from lexer.lpp. */ 490 | yy::GraphQLParserImpl::syntax_error make_error(const yy::location &loc, const std::string &str) { 491 | return yy::GraphQLParserImpl::syntax_error(loc, str); 492 | } 493 | -------------------------------------------------------------------------------- /internal/Ast.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | /** @generated */ 10 | #pragma once 11 | 12 | #include "AstNode.h" 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | namespace facebook { 20 | namespace graphql { 21 | namespace ast { 22 | 23 | // The parser uses strdup to move from yytext to the heap, so we need 24 | // to use free instead of delete. 25 | struct CDeleter { 26 | void operator()(const char *p) const { free((void *)p); } 27 | }; 28 | 29 | class Definition; 30 | class Document; 31 | class OperationDefinition; 32 | class VariableDefinition; 33 | class SelectionSet; 34 | class Selection; 35 | class Field; 36 | class Argument; 37 | class FragmentSpread; 38 | class InlineFragment; 39 | class FragmentDefinition; 40 | class Value; 41 | class Variable; 42 | class IntValue; 43 | class FloatValue; 44 | class StringValue; 45 | class BooleanValue; 46 | class EnumValue; 47 | class ArrayValue; 48 | class ObjectValue; 49 | class ObjectField; 50 | class Directive; 51 | class Type; 52 | class NamedType; 53 | class ListType; 54 | class NonNullType; 55 | class Name; 56 | 57 | class Definition : public Node { 58 | public: 59 | explicit Definition( 60 | const yy::location &location 61 | 62 | ) 63 | : Node(location) 64 | 65 | {} 66 | }; 67 | 68 | class Document : public Node { 69 | std::unique_ptr>> definitions_; 70 | public: 71 | explicit Document( 72 | const yy::location &location, 73 | std::vector> * definitions 74 | ) 75 | : Node(location), 76 | definitions_(definitions) 77 | {} 78 | 79 | ~Document() {} 80 | 81 | Document(const Document&) = delete; 82 | Document& operator=(const Document&) = delete; 83 | 84 | const std::vector>& getDefinitions() const 85 | { return *definitions_; } 86 | 87 | void accept(visitor::AstVisitor *visitor) override; 88 | }; 89 | 90 | 91 | class OperationDefinition : public Definition { 92 | std::unique_ptr operation_; 93 | std::unique_ptr name_; 94 | std::unique_ptr>> variableDefinitions_; 95 | std::unique_ptr>> directives_; 96 | std::unique_ptr selectionSet_; 97 | public: 98 | explicit OperationDefinition( 99 | const yy::location &location, 100 | const char * operation, 101 | Name * name, 102 | std::vector> * variableDefinitions, 103 | std::vector> * directives, 104 | SelectionSet * selectionSet 105 | ) 106 | : Definition(location), 107 | operation_(operation), 108 | name_(name), 109 | variableDefinitions_(variableDefinitions), 110 | directives_(directives), 111 | selectionSet_(selectionSet) 112 | {} 113 | 114 | ~OperationDefinition() {} 115 | 116 | OperationDefinition(const OperationDefinition&) = delete; 117 | OperationDefinition& operator=(const OperationDefinition&) = delete; 118 | 119 | const char * getOperation() const 120 | { return operation_.get(); } 121 | 122 | const Name* getName() const 123 | { return name_.get(); } 124 | 125 | const std::vector>* getVariableDefinitions() const 126 | { return variableDefinitions_.get(); } 127 | 128 | const std::vector>* getDirectives() const 129 | { return directives_.get(); } 130 | 131 | const SelectionSet& getSelectionSet() const 132 | { return *selectionSet_; } 133 | 134 | void accept(visitor::AstVisitor *visitor) override; 135 | }; 136 | 137 | 138 | class VariableDefinition : public Node { 139 | std::unique_ptr variable_; 140 | std::unique_ptr type_; 141 | std::unique_ptr defaultValue_; 142 | public: 143 | explicit VariableDefinition( 144 | const yy::location &location, 145 | Variable * variable, 146 | Type * type, 147 | Value * defaultValue 148 | ) 149 | : Node(location), 150 | variable_(variable), 151 | type_(type), 152 | defaultValue_(defaultValue) 153 | {} 154 | 155 | ~VariableDefinition() {} 156 | 157 | VariableDefinition(const VariableDefinition&) = delete; 158 | VariableDefinition& operator=(const VariableDefinition&) = delete; 159 | 160 | const Variable& getVariable() const 161 | { return *variable_; } 162 | 163 | const Type& getType() const 164 | { return *type_; } 165 | 166 | const Value* getDefaultValue() const 167 | { return defaultValue_.get(); } 168 | 169 | void accept(visitor::AstVisitor *visitor) override; 170 | }; 171 | 172 | 173 | class SelectionSet : public Node { 174 | std::unique_ptr>> selections_; 175 | public: 176 | explicit SelectionSet( 177 | const yy::location &location, 178 | std::vector> * selections 179 | ) 180 | : Node(location), 181 | selections_(selections) 182 | {} 183 | 184 | ~SelectionSet() {} 185 | 186 | SelectionSet(const SelectionSet&) = delete; 187 | SelectionSet& operator=(const SelectionSet&) = delete; 188 | 189 | const std::vector>& getSelections() const 190 | { return *selections_; } 191 | 192 | void accept(visitor::AstVisitor *visitor) override; 193 | }; 194 | 195 | 196 | class Selection : public Node { 197 | public: 198 | explicit Selection( 199 | const yy::location &location 200 | 201 | ) 202 | : Node(location) 203 | 204 | {} 205 | }; 206 | 207 | class Field : public Selection { 208 | std::unique_ptr alias_; 209 | std::unique_ptr name_; 210 | std::unique_ptr>> arguments_; 211 | std::unique_ptr>> directives_; 212 | std::unique_ptr selectionSet_; 213 | public: 214 | explicit Field( 215 | const yy::location &location, 216 | Name * alias, 217 | Name * name, 218 | std::vector> * arguments, 219 | std::vector> * directives, 220 | SelectionSet * selectionSet 221 | ) 222 | : Selection(location), 223 | alias_(alias), 224 | name_(name), 225 | arguments_(arguments), 226 | directives_(directives), 227 | selectionSet_(selectionSet) 228 | {} 229 | 230 | ~Field() {} 231 | 232 | Field(const Field&) = delete; 233 | Field& operator=(const Field&) = delete; 234 | 235 | const Name* getAlias() const 236 | { return alias_.get(); } 237 | 238 | const Name& getName() const 239 | { return *name_; } 240 | 241 | const std::vector>* getArguments() const 242 | { return arguments_.get(); } 243 | 244 | const std::vector>* getDirectives() const 245 | { return directives_.get(); } 246 | 247 | const SelectionSet* getSelectionSet() const 248 | { return selectionSet_.get(); } 249 | 250 | void accept(visitor::AstVisitor *visitor) override; 251 | }; 252 | 253 | 254 | class Argument : public Node { 255 | std::unique_ptr name_; 256 | std::unique_ptr value_; 257 | public: 258 | explicit Argument( 259 | const yy::location &location, 260 | Name * name, 261 | Value * value 262 | ) 263 | : Node(location), 264 | name_(name), 265 | value_(value) 266 | {} 267 | 268 | ~Argument() {} 269 | 270 | Argument(const Argument&) = delete; 271 | Argument& operator=(const Argument&) = delete; 272 | 273 | const Name& getName() const 274 | { return *name_; } 275 | 276 | const Value& getValue() const 277 | { return *value_; } 278 | 279 | void accept(visitor::AstVisitor *visitor) override; 280 | }; 281 | 282 | 283 | class FragmentSpread : public Selection { 284 | std::unique_ptr name_; 285 | std::unique_ptr>> directives_; 286 | public: 287 | explicit FragmentSpread( 288 | const yy::location &location, 289 | Name * name, 290 | std::vector> * directives 291 | ) 292 | : Selection(location), 293 | name_(name), 294 | directives_(directives) 295 | {} 296 | 297 | ~FragmentSpread() {} 298 | 299 | FragmentSpread(const FragmentSpread&) = delete; 300 | FragmentSpread& operator=(const FragmentSpread&) = delete; 301 | 302 | const Name& getName() const 303 | { return *name_; } 304 | 305 | const std::vector>* getDirectives() const 306 | { return directives_.get(); } 307 | 308 | void accept(visitor::AstVisitor *visitor) override; 309 | }; 310 | 311 | 312 | class InlineFragment : public Selection { 313 | std::unique_ptr typeCondition_; 314 | std::unique_ptr>> directives_; 315 | std::unique_ptr selectionSet_; 316 | public: 317 | explicit InlineFragment( 318 | const yy::location &location, 319 | NamedType * typeCondition, 320 | std::vector> * directives, 321 | SelectionSet * selectionSet 322 | ) 323 | : Selection(location), 324 | typeCondition_(typeCondition), 325 | directives_(directives), 326 | selectionSet_(selectionSet) 327 | {} 328 | 329 | ~InlineFragment() {} 330 | 331 | InlineFragment(const InlineFragment&) = delete; 332 | InlineFragment& operator=(const InlineFragment&) = delete; 333 | 334 | const NamedType& getTypeCondition() const 335 | { return *typeCondition_; } 336 | 337 | const std::vector>* getDirectives() const 338 | { return directives_.get(); } 339 | 340 | const SelectionSet& getSelectionSet() const 341 | { return *selectionSet_; } 342 | 343 | void accept(visitor::AstVisitor *visitor) override; 344 | }; 345 | 346 | 347 | class FragmentDefinition : public Definition { 348 | std::unique_ptr name_; 349 | std::unique_ptr typeCondition_; 350 | std::unique_ptr>> directives_; 351 | std::unique_ptr selectionSet_; 352 | public: 353 | explicit FragmentDefinition( 354 | const yy::location &location, 355 | Name * name, 356 | NamedType * typeCondition, 357 | std::vector> * directives, 358 | SelectionSet * selectionSet 359 | ) 360 | : Definition(location), 361 | name_(name), 362 | typeCondition_(typeCondition), 363 | directives_(directives), 364 | selectionSet_(selectionSet) 365 | {} 366 | 367 | ~FragmentDefinition() {} 368 | 369 | FragmentDefinition(const FragmentDefinition&) = delete; 370 | FragmentDefinition& operator=(const FragmentDefinition&) = delete; 371 | 372 | const Name& getName() const 373 | { return *name_; } 374 | 375 | const NamedType& getTypeCondition() const 376 | { return *typeCondition_; } 377 | 378 | const std::vector>* getDirectives() const 379 | { return directives_.get(); } 380 | 381 | const SelectionSet& getSelectionSet() const 382 | { return *selectionSet_; } 383 | 384 | void accept(visitor::AstVisitor *visitor) override; 385 | }; 386 | 387 | 388 | class Value : public Node { 389 | public: 390 | explicit Value( 391 | const yy::location &location 392 | 393 | ) 394 | : Node(location) 395 | 396 | {} 397 | }; 398 | 399 | class Variable : public Value { 400 | std::unique_ptr name_; 401 | public: 402 | explicit Variable( 403 | const yy::location &location, 404 | Name * name 405 | ) 406 | : Value(location), 407 | name_(name) 408 | {} 409 | 410 | ~Variable() {} 411 | 412 | Variable(const Variable&) = delete; 413 | Variable& operator=(const Variable&) = delete; 414 | 415 | const Name& getName() const 416 | { return *name_; } 417 | 418 | void accept(visitor::AstVisitor *visitor) override; 419 | }; 420 | 421 | 422 | class IntValue : public Value { 423 | std::unique_ptr value_; 424 | public: 425 | explicit IntValue( 426 | const yy::location &location, 427 | const char * value 428 | ) 429 | : Value(location), 430 | value_(value) 431 | {} 432 | 433 | ~IntValue() {} 434 | 435 | IntValue(const IntValue&) = delete; 436 | IntValue& operator=(const IntValue&) = delete; 437 | 438 | const char * getValue() const 439 | { return value_.get(); } 440 | 441 | void accept(visitor::AstVisitor *visitor) override; 442 | }; 443 | 444 | 445 | class FloatValue : public Value { 446 | std::unique_ptr value_; 447 | public: 448 | explicit FloatValue( 449 | const yy::location &location, 450 | const char * value 451 | ) 452 | : Value(location), 453 | value_(value) 454 | {} 455 | 456 | ~FloatValue() {} 457 | 458 | FloatValue(const FloatValue&) = delete; 459 | FloatValue& operator=(const FloatValue&) = delete; 460 | 461 | const char * getValue() const 462 | { return value_.get(); } 463 | 464 | void accept(visitor::AstVisitor *visitor) override; 465 | }; 466 | 467 | 468 | class StringValue : public Value { 469 | std::unique_ptr value_; 470 | public: 471 | explicit StringValue( 472 | const yy::location &location, 473 | const char * value 474 | ) 475 | : Value(location), 476 | value_(value) 477 | {} 478 | 479 | ~StringValue() {} 480 | 481 | StringValue(const StringValue&) = delete; 482 | StringValue& operator=(const StringValue&) = delete; 483 | 484 | const char * getValue() const 485 | { return value_.get(); } 486 | 487 | void accept(visitor::AstVisitor *visitor) override; 488 | }; 489 | 490 | 491 | class BooleanValue : public Value { 492 | bool value_; 493 | public: 494 | explicit BooleanValue( 495 | const yy::location &location, 496 | bool value 497 | ) 498 | : Value(location), 499 | value_(value) 500 | {} 501 | 502 | ~BooleanValue() {} 503 | 504 | BooleanValue(const BooleanValue&) = delete; 505 | BooleanValue& operator=(const BooleanValue&) = delete; 506 | 507 | bool getValue() const 508 | { return value_; } 509 | 510 | void accept(visitor::AstVisitor *visitor) override; 511 | }; 512 | 513 | 514 | class EnumValue : public Value { 515 | std::unique_ptr value_; 516 | public: 517 | explicit EnumValue( 518 | const yy::location &location, 519 | const char * value 520 | ) 521 | : Value(location), 522 | value_(value) 523 | {} 524 | 525 | ~EnumValue() {} 526 | 527 | EnumValue(const EnumValue&) = delete; 528 | EnumValue& operator=(const EnumValue&) = delete; 529 | 530 | const char * getValue() const 531 | { return value_.get(); } 532 | 533 | void accept(visitor::AstVisitor *visitor) override; 534 | }; 535 | 536 | 537 | class ArrayValue : public Value { 538 | std::unique_ptr>> values_; 539 | public: 540 | explicit ArrayValue( 541 | const yy::location &location, 542 | std::vector> * values 543 | ) 544 | : Value(location), 545 | values_(values) 546 | {} 547 | 548 | ~ArrayValue() {} 549 | 550 | ArrayValue(const ArrayValue&) = delete; 551 | ArrayValue& operator=(const ArrayValue&) = delete; 552 | 553 | const std::vector>& getValues() const 554 | { return *values_; } 555 | 556 | void accept(visitor::AstVisitor *visitor) override; 557 | }; 558 | 559 | 560 | class ObjectValue : public Value { 561 | std::unique_ptr>> fields_; 562 | public: 563 | explicit ObjectValue( 564 | const yy::location &location, 565 | std::vector> * fields 566 | ) 567 | : Value(location), 568 | fields_(fields) 569 | {} 570 | 571 | ~ObjectValue() {} 572 | 573 | ObjectValue(const ObjectValue&) = delete; 574 | ObjectValue& operator=(const ObjectValue&) = delete; 575 | 576 | const std::vector>& getFields() const 577 | { return *fields_; } 578 | 579 | void accept(visitor::AstVisitor *visitor) override; 580 | }; 581 | 582 | 583 | class ObjectField : public Node { 584 | std::unique_ptr name_; 585 | std::unique_ptr value_; 586 | public: 587 | explicit ObjectField( 588 | const yy::location &location, 589 | Name * name, 590 | Value * value 591 | ) 592 | : Node(location), 593 | name_(name), 594 | value_(value) 595 | {} 596 | 597 | ~ObjectField() {} 598 | 599 | ObjectField(const ObjectField&) = delete; 600 | ObjectField& operator=(const ObjectField&) = delete; 601 | 602 | const Name& getName() const 603 | { return *name_; } 604 | 605 | const Value& getValue() const 606 | { return *value_; } 607 | 608 | void accept(visitor::AstVisitor *visitor) override; 609 | }; 610 | 611 | 612 | class Directive : public Node { 613 | std::unique_ptr name_; 614 | std::unique_ptr>> arguments_; 615 | public: 616 | explicit Directive( 617 | const yy::location &location, 618 | Name * name, 619 | std::vector> * arguments 620 | ) 621 | : Node(location), 622 | name_(name), 623 | arguments_(arguments) 624 | {} 625 | 626 | ~Directive() {} 627 | 628 | Directive(const Directive&) = delete; 629 | Directive& operator=(const Directive&) = delete; 630 | 631 | const Name& getName() const 632 | { return *name_; } 633 | 634 | const std::vector>* getArguments() const 635 | { return arguments_.get(); } 636 | 637 | void accept(visitor::AstVisitor *visitor) override; 638 | }; 639 | 640 | 641 | class Type : public Node { 642 | public: 643 | explicit Type( 644 | const yy::location &location 645 | 646 | ) 647 | : Node(location) 648 | 649 | {} 650 | }; 651 | 652 | class NamedType : public Type { 653 | std::unique_ptr name_; 654 | public: 655 | explicit NamedType( 656 | const yy::location &location, 657 | Name * name 658 | ) 659 | : Type(location), 660 | name_(name) 661 | {} 662 | 663 | ~NamedType() {} 664 | 665 | NamedType(const NamedType&) = delete; 666 | NamedType& operator=(const NamedType&) = delete; 667 | 668 | const Name& getName() const 669 | { return *name_; } 670 | 671 | void accept(visitor::AstVisitor *visitor) override; 672 | }; 673 | 674 | 675 | class ListType : public Type { 676 | std::unique_ptr type_; 677 | public: 678 | explicit ListType( 679 | const yy::location &location, 680 | Type * type 681 | ) 682 | : Type(location), 683 | type_(type) 684 | {} 685 | 686 | ~ListType() {} 687 | 688 | ListType(const ListType&) = delete; 689 | ListType& operator=(const ListType&) = delete; 690 | 691 | const Type& getType() const 692 | { return *type_; } 693 | 694 | void accept(visitor::AstVisitor *visitor) override; 695 | }; 696 | 697 | 698 | class NonNullType : public Type { 699 | std::unique_ptr type_; 700 | public: 701 | explicit NonNullType( 702 | const yy::location &location, 703 | Type * type 704 | ) 705 | : Type(location), 706 | type_(type) 707 | {} 708 | 709 | ~NonNullType() {} 710 | 711 | NonNullType(const NonNullType&) = delete; 712 | NonNullType& operator=(const NonNullType&) = delete; 713 | 714 | const Type& getType() const 715 | { return *type_; } 716 | 717 | void accept(visitor::AstVisitor *visitor) override; 718 | }; 719 | 720 | 721 | class Name : public Node { 722 | std::unique_ptr value_; 723 | public: 724 | explicit Name( 725 | const yy::location &location, 726 | const char * value 727 | ) 728 | : Node(location), 729 | value_(value) 730 | {} 731 | 732 | ~Name() {} 733 | 734 | Name(const Name&) = delete; 735 | Name& operator=(const Name&) = delete; 736 | 737 | const char * getValue() const 738 | { return value_.get(); } 739 | 740 | void accept(visitor::AstVisitor *visitor) override; 741 | }; 742 | 743 | 744 | 745 | } 746 | } 747 | } 748 | -------------------------------------------------------------------------------- /internal/parser.tab.hpp: -------------------------------------------------------------------------------- 1 | // A Bison parser, made by GNU Bison 3.0.4. 2 | 3 | // Skeleton interface for Bison LALR(1) parsers in C++ 4 | 5 | // Copyright (C) 2002-2015 Free Software Foundation, Inc. 6 | 7 | // This program is free software: you can redistribute it and/or modify 8 | // it under the terms of the GNU General Public License as published by 9 | // the Free Software Foundation, either version 3 of the License, or 10 | // (at your option) any later version. 11 | 12 | // This program is distributed in the hope that it will be useful, 13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | // GNU General Public License for more details. 16 | 17 | // You should have received a copy of the GNU General Public License 18 | // along with this program. If not, see . 19 | 20 | // As a special exception, you may create a larger work that contains 21 | // part or all of the Bison parser skeleton and distribute that work 22 | // under terms of your choice, so long as that work isn't itself a 23 | // parser generator using the skeleton or a modified version thereof 24 | // as a parser skeleton. Alternatively, if you modify or redistribute 25 | // the parser skeleton itself, you may (at your option) remove this 26 | // special exception, which will cause the skeleton and the resulting 27 | // Bison output files to be licensed under the GNU General Public 28 | // License without this special exception. 29 | 30 | // This special exception was added by the Free Software Foundation in 31 | // version 2.2 of Bison. 32 | 33 | /** 34 | ** \file parser.tab.hpp 35 | ** Define the yy::parser class. 36 | */ 37 | 38 | // C++ LALR(1) parser skeleton written by Akim Demaille. 39 | 40 | #ifndef YY_YY_PARSER_TAB_HPP_INCLUDED 41 | # define YY_YY_PARSER_TAB_HPP_INCLUDED 42 | // // "%code requires" blocks. 43 | #line 22 "parser.ypp" // lalr1.cc:392 44 | 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | 51 | #include "Ast.h" 52 | 53 | using facebook::graphql::ast::Node; 54 | using facebook::graphql::ast::Name; 55 | using facebook::graphql::ast::Definition; 56 | using facebook::graphql::ast::Document; 57 | using facebook::graphql::ast::OperationDefinition; 58 | using facebook::graphql::ast::VariableDefinition; 59 | using facebook::graphql::ast::Variable; 60 | using facebook::graphql::ast::SelectionSet; 61 | using facebook::graphql::ast::Selection; 62 | using facebook::graphql::ast::Field; 63 | using facebook::graphql::ast::Argument; 64 | using facebook::graphql::ast::FragmentSpread; 65 | using facebook::graphql::ast::InlineFragment; 66 | using facebook::graphql::ast::FragmentDefinition; 67 | using facebook::graphql::ast::Value; 68 | using facebook::graphql::ast::IntValue; 69 | using facebook::graphql::ast::FloatValue; 70 | using facebook::graphql::ast::StringValue; 71 | using facebook::graphql::ast::BooleanValue; 72 | using facebook::graphql::ast::EnumValue; 73 | using facebook::graphql::ast::ArrayValue; 74 | using facebook::graphql::ast::ObjectValue; 75 | using facebook::graphql::ast::ObjectField; 76 | using facebook::graphql::ast::Directive; 77 | using facebook::graphql::ast::Type; 78 | using facebook::graphql::ast::NamedType; 79 | using facebook::graphql::ast::ListType; 80 | using facebook::graphql::ast::NonNullType; 81 | 82 | union yystype { \ 83 | const char *str; \ 84 | const char *heapStr; \ 85 | Name *name; \ 86 | Definition *definition; \ 87 | Document *document; \ 88 | OperationDefinition *operationDefinition; \ 89 | VariableDefinition *variableDefinition; \ 90 | Variable *variable; \ 91 | SelectionSet *selectionSet; \ 92 | Selection *selection; \ 93 | Field *field; \ 94 | Argument *argument; \ 95 | FragmentSpread *fragmentSpread; \ 96 | InlineFragment *inlineFragment; \ 97 | FragmentDefinition *fragmentDefinition; \ 98 | Value *value; \ 99 | IntValue *intValue; \ 100 | FloatValue *floatValue; \ 101 | StringValue *stringValue; \ 102 | BooleanValue *booleanValue; \ 103 | EnumValue *enumValue; \ 104 | ArrayValue *arrayValue; \ 105 | ObjectValue *objectValue; \ 106 | ObjectField *objectField; \ 107 | Directive *directive; \ 108 | Type *type; \ 109 | NamedType *namedType; \ 110 | ListType *listType; \ 111 | NonNullType *nonNullType; \ 112 | \ 113 | std::vector> *nameList; \ 114 | std::vector> *definitionList; \ 115 | std::vector> *documentList; \ 116 | std::vector> *operationDefinitionList; \ 117 | std::vector> *variableDefinitionList; \ 118 | std::vector> *variableList; \ 119 | std::vector> *selectionSetList; \ 120 | std::vector> *selectionList; \ 121 | std::vector> *fieldList; \ 122 | std::vector> *argumentList; \ 123 | std::vector> *fragmentSpreadList; \ 124 | std::vector> *inlineFragmentList; \ 125 | std::vector> *fragmentDefinitionList; \ 126 | std::vector> *valueList; \ 127 | std::vector> *intValueList; \ 128 | std::vector> *floatValueList; \ 129 | std::vector> *stringValueList; \ 130 | std::vector> *booleanValueList; \ 131 | std::vector> *enumValueList; \ 132 | std::vector> *arrayValueList; \ 133 | std::vector> *objectValueList; \ 134 | std::vector> *objectFieldList; \ 135 | std::vector> *directiveList; \ 136 | std::vector> *typeList; \ 137 | std::vector> *listTypeList; \ 138 | std::vector> *nonNullTypeList; \ 139 | }; 140 | 141 | #define YYSTYPE union yystype 142 | #define YYLTYPE yy::location 143 | 144 | #line 145 "parser.tab.hpp" // lalr1.cc:392 145 | 146 | 147 | # include // std::abort 148 | # include 149 | # include 150 | # include 151 | # include 152 | # include "stack.hh" 153 | # include "location.hh" 154 | 155 | 156 | #ifndef YY_ATTRIBUTE 157 | # if (defined __GNUC__ \ 158 | && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \ 159 | || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C 160 | # define YY_ATTRIBUTE(Spec) __attribute__(Spec) 161 | # else 162 | # define YY_ATTRIBUTE(Spec) /* empty */ 163 | # endif 164 | #endif 165 | 166 | #ifndef YY_ATTRIBUTE_PURE 167 | # define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__)) 168 | #endif 169 | 170 | #ifndef YY_ATTRIBUTE_UNUSED 171 | # define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) 172 | #endif 173 | 174 | #if !defined _Noreturn \ 175 | && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) 176 | # if defined _MSC_VER && 1200 <= _MSC_VER 177 | # define _Noreturn __declspec (noreturn) 178 | # else 179 | # define _Noreturn YY_ATTRIBUTE ((__noreturn__)) 180 | # endif 181 | #endif 182 | 183 | /* Suppress unused-variable warnings by "using" E. */ 184 | #if ! defined lint || defined __GNUC__ 185 | # define YYUSE(E) ((void) (E)) 186 | #else 187 | # define YYUSE(E) /* empty */ 188 | #endif 189 | 190 | #if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ 191 | /* Suppress an incorrect diagnostic about yylval being uninitialized. */ 192 | # define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ 193 | _Pragma ("GCC diagnostic push") \ 194 | _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ 195 | _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") 196 | # define YY_IGNORE_MAYBE_UNINITIALIZED_END \ 197 | _Pragma ("GCC diagnostic pop") 198 | #else 199 | # define YY_INITIAL_VALUE(Value) Value 200 | #endif 201 | #ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN 202 | # define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN 203 | # define YY_IGNORE_MAYBE_UNINITIALIZED_END 204 | #endif 205 | #ifndef YY_INITIAL_VALUE 206 | # define YY_INITIAL_VALUE(Value) /* Nothing. */ 207 | #endif 208 | 209 | /* Debug traces. */ 210 | #ifndef YYDEBUG 211 | # define YYDEBUG 0 212 | #endif 213 | 214 | 215 | namespace yy { 216 | #line 217 "parser.tab.hpp" // lalr1.cc:392 217 | 218 | 219 | 220 | 221 | 222 | /// A Bison parser. 223 | class GraphQLParserImpl 224 | { 225 | public: 226 | #ifndef YYSTYPE 227 | /// Symbol semantic values. 228 | 229 | #else 230 | typedef YYSTYPE semantic_type; 231 | #endif 232 | /// Symbol locations. 233 | typedef location location_type; 234 | 235 | /// Syntax errors thrown from user actions. 236 | struct syntax_error : std::runtime_error 237 | { 238 | syntax_error (const location_type& l, const std::string& m); 239 | location_type location; 240 | }; 241 | 242 | /// Tokens. 243 | struct token 244 | { 245 | enum yytokentype 246 | { 247 | TOK_EOF = 0, 248 | TOK_FALSE = 258, 249 | TOK_FRAGMENT = 259, 250 | TOK_MUTATION = 260, 251 | TOK_NULL = 261, 252 | TOK_QUERY = 262, 253 | TOK_ON = 263, 254 | TOK_TRUE = 264, 255 | TOK_BANG = 265, 256 | TOK_LPAREN = 266, 257 | TOK_RPAREN = 267, 258 | TOK_ELLIPSIS = 268, 259 | TOK_COLON = 269, 260 | TOK_EQUAL = 270, 261 | TOK_AT = 271, 262 | TOK_LBRACKET = 272, 263 | TOK_RBRACKET = 273, 264 | TOK_LBRACE = 274, 265 | TOK_PIPE = 275, 266 | TOK_RBRACE = 276, 267 | TOK_VARIABLE = 277, 268 | TOK_INTEGER = 278, 269 | TOK_FLOAT = 279, 270 | TOK_STRING = 280, 271 | TOK_IDENTIFIER = 281 272 | }; 273 | }; 274 | 275 | /// (External) token type, as returned by yylex. 276 | typedef token::yytokentype token_type; 277 | 278 | /// Symbol type: an internal symbol number. 279 | typedef int symbol_number_type; 280 | 281 | /// The symbol type number to denote an empty symbol. 282 | enum { empty_symbol = -2 }; 283 | 284 | /// Internal symbol number for tokens (subsumed by symbol_number_type). 285 | typedef unsigned char token_number_type; 286 | 287 | /// A complete symbol. 288 | /// 289 | /// Expects its Base type to provide access to the symbol type 290 | /// via type_get(). 291 | /// 292 | /// Provide access to semantic value and location. 293 | template 294 | struct basic_symbol : Base 295 | { 296 | /// Alias to Base. 297 | typedef Base super_type; 298 | 299 | /// Default constructor. 300 | basic_symbol (); 301 | 302 | /// Copy constructor. 303 | basic_symbol (const basic_symbol& other); 304 | 305 | /// Constructor for valueless symbols. 306 | basic_symbol (typename Base::kind_type t, 307 | const location_type& l); 308 | 309 | /// Constructor for symbols with semantic value. 310 | basic_symbol (typename Base::kind_type t, 311 | const semantic_type& v, 312 | const location_type& l); 313 | 314 | /// Destroy the symbol. 315 | ~basic_symbol (); 316 | 317 | /// Destroy contents, and record that is empty. 318 | void clear (); 319 | 320 | /// Whether empty. 321 | bool empty () const; 322 | 323 | /// Destructive move, \a s is emptied into this. 324 | void move (basic_symbol& s); 325 | 326 | /// The semantic value. 327 | semantic_type value; 328 | 329 | /// The location. 330 | location_type location; 331 | 332 | private: 333 | /// Assignment operator. 334 | basic_symbol& operator= (const basic_symbol& other); 335 | }; 336 | 337 | /// Type access provider for token (enum) based symbols. 338 | struct by_type 339 | { 340 | /// Default constructor. 341 | by_type (); 342 | 343 | /// Copy constructor. 344 | by_type (const by_type& other); 345 | 346 | /// The symbol type as needed by the constructor. 347 | typedef token_type kind_type; 348 | 349 | /// Constructor from (external) token numbers. 350 | by_type (kind_type t); 351 | 352 | /// Record that this symbol is empty. 353 | void clear (); 354 | 355 | /// Steal the symbol type from \a that. 356 | void move (by_type& that); 357 | 358 | /// The (internal) type number (corresponding to \a type). 359 | /// \a empty when empty. 360 | symbol_number_type type_get () const; 361 | 362 | /// The token. 363 | token_type token () const; 364 | 365 | /// The symbol type. 366 | /// \a empty_symbol when empty. 367 | /// An int, not token_number_type, to be able to store empty_symbol. 368 | int type; 369 | }; 370 | 371 | /// "External" symbols: returned by the scanner. 372 | typedef basic_symbol symbol_type; 373 | 374 | 375 | /// Build a parser object. 376 | GraphQLParserImpl (Node **outAST_yyarg, const char **outError_yyarg, void *scanner_yyarg); 377 | virtual ~GraphQLParserImpl (); 378 | 379 | /// Parse. 380 | /// \returns 0 iff parsing succeeded. 381 | virtual int parse (); 382 | 383 | #if YYDEBUG 384 | /// The current debugging stream. 385 | std::ostream& debug_stream () const YY_ATTRIBUTE_PURE; 386 | /// Set the current debugging stream. 387 | void set_debug_stream (std::ostream &); 388 | 389 | /// Type for debugging levels. 390 | typedef int debug_level_type; 391 | /// The current debugging level. 392 | debug_level_type debug_level () const YY_ATTRIBUTE_PURE; 393 | /// Set the current debugging level. 394 | void set_debug_level (debug_level_type l); 395 | #endif 396 | 397 | /// Report a syntax error. 398 | /// \param loc where the syntax error is found. 399 | /// \param msg a description of the syntax error. 400 | virtual void error (const location_type& loc, const std::string& msg); 401 | 402 | /// Report a syntax error. 403 | void error (const syntax_error& err); 404 | 405 | private: 406 | /// This class is not copyable. 407 | GraphQLParserImpl (const GraphQLParserImpl&); 408 | GraphQLParserImpl& operator= (const GraphQLParserImpl&); 409 | 410 | /// State numbers. 411 | typedef int state_type; 412 | 413 | /// Generate an error message. 414 | /// \param yystate the state where the error occurred. 415 | /// \param yyla the lookahead token. 416 | virtual std::string yysyntax_error_ (state_type yystate, 417 | const symbol_type& yyla) const; 418 | 419 | /// Compute post-reduction state. 420 | /// \param yystate the current state 421 | /// \param yysym the nonterminal to push on the stack 422 | state_type yy_lr_goto_state_ (state_type yystate, int yysym); 423 | 424 | /// Whether the given \c yypact_ value indicates a defaulted state. 425 | /// \param yyvalue the value to check 426 | static bool yy_pact_value_is_default_ (int yyvalue); 427 | 428 | /// Whether the given \c yytable_ value indicates a syntax error. 429 | /// \param yyvalue the value to check 430 | static bool yy_table_value_is_error_ (int yyvalue); 431 | 432 | static const signed char yypact_ninf_; 433 | static const signed char yytable_ninf_; 434 | 435 | /// Convert a scanner token number \a t to a symbol number. 436 | static token_number_type yytranslate_ (int t); 437 | 438 | // Tables. 439 | // YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing 440 | // STATE-NUM. 441 | static const short int yypact_[]; 442 | 443 | // YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. 444 | // Performed when YYTABLE does not specify something else to do. Zero 445 | // means the default is an error. 446 | static const unsigned char yydefact_[]; 447 | 448 | // YYPGOTO[NTERM-NUM]. 449 | static const signed char yypgoto_[]; 450 | 451 | // YYDEFGOTO[NTERM-NUM]. 452 | static const short int yydefgoto_[]; 453 | 454 | // YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If 455 | // positive, shift that token. If negative, reduce the rule whose 456 | // number is the opposite. If YYTABLE_NINF, syntax error. 457 | static const unsigned char yytable_[]; 458 | 459 | static const short int yycheck_[]; 460 | 461 | // YYSTOS[STATE-NUM] -- The (internal number of the) accessing 462 | // symbol of state STATE-NUM. 463 | static const unsigned char yystos_[]; 464 | 465 | // YYR1[YYN] -- Symbol number of symbol that rule YYN derives. 466 | static const unsigned char yyr1_[]; 467 | 468 | // YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. 469 | static const unsigned char yyr2_[]; 470 | 471 | 472 | /// Convert the symbol name \a n to a form suitable for a diagnostic. 473 | static std::string yytnamerr_ (const char *n); 474 | 475 | 476 | /// For a symbol, its name in clear. 477 | static const char* const yytname_[]; 478 | #if YYDEBUG 479 | // YYRLINE[YYN] -- Source line where rule number YYN was defined. 480 | static const unsigned short int yyrline_[]; 481 | /// Report on the debug stream that the rule \a r is going to be reduced. 482 | virtual void yy_reduce_print_ (int r); 483 | /// Print the state stack on the debug stream. 484 | virtual void yystack_print_ (); 485 | 486 | // Debugging. 487 | int yydebug_; 488 | std::ostream* yycdebug_; 489 | 490 | /// \brief Display a symbol type, value and location. 491 | /// \param yyo The output stream. 492 | /// \param yysym The symbol. 493 | template 494 | void yy_print_ (std::ostream& yyo, const basic_symbol& yysym) const; 495 | #endif 496 | 497 | /// \brief Reclaim the memory associated to a symbol. 498 | /// \param yymsg Why this token is reclaimed. 499 | /// If null, print nothing. 500 | /// \param yysym The symbol. 501 | template 502 | void yy_destroy_ (const char* yymsg, basic_symbol& yysym) const; 503 | 504 | private: 505 | /// Type access provider for state based symbols. 506 | struct by_state 507 | { 508 | /// Default constructor. 509 | by_state (); 510 | 511 | /// The symbol type as needed by the constructor. 512 | typedef state_type kind_type; 513 | 514 | /// Constructor. 515 | by_state (kind_type s); 516 | 517 | /// Copy constructor. 518 | by_state (const by_state& other); 519 | 520 | /// Record that this symbol is empty. 521 | void clear (); 522 | 523 | /// Steal the symbol type from \a that. 524 | void move (by_state& that); 525 | 526 | /// The (internal) type number (corresponding to \a state). 527 | /// \a empty_symbol when empty. 528 | symbol_number_type type_get () const; 529 | 530 | /// The state number used to denote an empty symbol. 531 | enum { empty_state = -1 }; 532 | 533 | /// The state. 534 | /// \a empty when empty. 535 | state_type state; 536 | }; 537 | 538 | /// "Internal" symbol: element of the stack. 539 | struct stack_symbol_type : basic_symbol 540 | { 541 | /// Superclass. 542 | typedef basic_symbol super_type; 543 | /// Construct an empty symbol. 544 | stack_symbol_type (); 545 | /// Steal the contents from \a sym to build this. 546 | stack_symbol_type (state_type s, symbol_type& sym); 547 | /// Assignment, needed by push_back. 548 | stack_symbol_type& operator= (const stack_symbol_type& that); 549 | }; 550 | 551 | /// Stack type. 552 | typedef stack stack_type; 553 | 554 | /// The stack. 555 | stack_type yystack_; 556 | 557 | /// Push a new state on the stack. 558 | /// \param m a debug message to display 559 | /// if null, no trace is output. 560 | /// \param s the symbol 561 | /// \warning the contents of \a s.value is stolen. 562 | void yypush_ (const char* m, stack_symbol_type& s); 563 | 564 | /// Push a new look ahead token on the state on the stack. 565 | /// \param m a debug message to display 566 | /// if null, no trace is output. 567 | /// \param s the state 568 | /// \param sym the symbol (for its value and location). 569 | /// \warning the contents of \a s.value is stolen. 570 | void yypush_ (const char* m, state_type s, symbol_type& sym); 571 | 572 | /// Pop \a n symbols the three stacks. 573 | void yypop_ (unsigned int n = 1); 574 | 575 | /// Constants. 576 | enum 577 | { 578 | yyeof_ = 0, 579 | yylast_ = 362, ///< Last index in yytable_. 580 | yynnts_ = 54, ///< Number of nonterminal symbols. 581 | yyfinal_ = 30, ///< Termination state number. 582 | yyterror_ = 1, 583 | yyerrcode_ = 256, 584 | yyntokens_ = 27 ///< Number of tokens. 585 | }; 586 | 587 | 588 | // User arguments. 589 | Node **outAST; 590 | const char **outError; 591 | void *scanner; 592 | }; 593 | 594 | 595 | 596 | } // yy 597 | #line 598 "parser.tab.hpp" // lalr1.cc:392 598 | 599 | 600 | 601 | 602 | #endif // !YY_YY_PARSER_TAB_HPP_INCLUDED 603 | --------------------------------------------------------------------------------