rails-graphql 0.2.1 → 1.0.0.beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/console.rb +18 -0
- data/ext/extconf.h +3 -0
- data/ext/extconf.rb +1 -54
- data/ext/gql_parser.c +646 -0
- data/ext/shared.c +482 -0
- data/ext/shared.h +177 -0
- data/lib/gql_parser.so +0 -0
- data/lib/rails/graphql/adapters/mysql_adapter.rb +59 -0
- data/lib/rails/graphql/adapters/pg_adapter.rb +25 -22
- data/lib/rails/graphql/adapters/sqlite_adapter.rb +17 -14
- data/lib/rails/graphql/alternative/field_set.rb +36 -0
- data/lib/rails/graphql/alternative/mutation.rb +17 -0
- data/lib/rails/graphql/alternative/query.rb +93 -0
- data/lib/rails/graphql/alternative/subscription.rb +17 -0
- data/lib/rails/graphql/alternative.rb +20 -0
- data/lib/rails/graphql/argument.rb +21 -24
- data/lib/rails/graphql/callback.rb +24 -9
- data/lib/rails/graphql/collectors/hash_collector.rb +14 -6
- data/lib/rails/graphql/collectors/idented_collector.rb +10 -7
- data/lib/rails/graphql/collectors/json_collector.rb +22 -17
- data/lib/rails/graphql/collectors.rb +4 -4
- data/lib/rails/graphql/config.rb +130 -15
- data/lib/rails/graphql/directive/cached_directive.rb +33 -0
- data/lib/rails/graphql/directive/deprecated_directive.rb +10 -10
- data/lib/rails/graphql/directive/include_directive.rb +5 -4
- data/lib/rails/graphql/directive/skip_directive.rb +5 -4
- data/lib/rails/graphql/directive.rb +118 -63
- data/lib/rails/graphql/errors.rb +33 -4
- data/lib/rails/graphql/event.rb +16 -5
- data/lib/rails/graphql/field/authorized_field.rb +19 -3
- data/lib/rails/graphql/field/input_field.rb +11 -10
- data/lib/rails/graphql/field/mutation_field.rb +42 -7
- data/lib/rails/graphql/field/output_field.rb +102 -13
- data/lib/rails/graphql/field/proxied_field.rb +31 -22
- data/lib/rails/graphql/field/resolved_field.rb +26 -24
- data/lib/rails/graphql/field/scoped_config.rb +10 -4
- data/lib/rails/graphql/field/subscription_field.rb +140 -0
- data/lib/rails/graphql/field/typed_field.rb +43 -22
- data/lib/rails/graphql/field.rb +70 -56
- data/lib/rails/graphql/global_id.rb +85 -0
- data/lib/rails/graphql/helpers/attribute_delegator.rb +5 -5
- data/lib/rails/graphql/helpers/inherited_collection/array.rb +50 -0
- data/lib/rails/graphql/helpers/inherited_collection/base.rb +43 -0
- data/lib/rails/graphql/helpers/inherited_collection/hash.rb +87 -0
- data/lib/rails/graphql/helpers/inherited_collection.rb +25 -76
- data/lib/rails/graphql/helpers/instantiable.rb +15 -0
- data/lib/rails/graphql/helpers/leaf_from_ar.rb +7 -7
- data/lib/rails/graphql/helpers/registerable.rb +44 -62
- data/lib/rails/graphql/helpers/unregisterable.rb +16 -0
- data/lib/rails/graphql/helpers/with_arguments.rb +31 -27
- data/lib/rails/graphql/helpers/with_assignment.rb +6 -6
- data/lib/rails/graphql/helpers/with_callbacks.rb +25 -8
- data/lib/rails/graphql/helpers/with_description.rb +71 -0
- data/lib/rails/graphql/helpers/with_directives.rb +54 -30
- data/lib/rails/graphql/helpers/with_events.rb +21 -23
- data/lib/rails/graphql/helpers/with_fields.rb +76 -22
- data/lib/rails/graphql/helpers/with_global_id.rb +22 -0
- data/lib/rails/graphql/helpers/with_name.rb +43 -0
- data/lib/rails/graphql/helpers/with_namespace.rb +7 -4
- data/lib/rails/graphql/helpers/with_owner.rb +8 -7
- data/lib/rails/graphql/helpers/with_schema_fields.rb +137 -55
- data/lib/rails/graphql/helpers/with_validator.rb +9 -9
- data/lib/rails/graphql/helpers.rb +10 -3
- data/lib/rails/graphql/introspection.rb +43 -36
- data/lib/rails/graphql/railtie.rb +88 -33
- data/lib/rails/graphql/railties/base_generator.rb +3 -9
- data/lib/rails/graphql/railties/channel.rb +157 -0
- data/lib/rails/graphql/railties/controller.rb +62 -17
- data/lib/rails/graphql/railties/controller_runtime.rb +5 -5
- data/lib/rails/graphql/railties/log_subscriber.rb +81 -14
- data/lib/rails/graphql/request/arguments.rb +24 -49
- data/lib/rails/graphql/request/backtrace.rb +191 -0
- data/lib/rails/graphql/request/component/field.rb +86 -65
- data/lib/rails/graphql/request/component/fragment.rb +72 -24
- data/lib/rails/graphql/request/component/operation/subscription.rb +164 -4
- data/lib/rails/graphql/request/component/operation.rb +63 -31
- data/lib/rails/graphql/request/component/spread.rb +68 -25
- data/lib/rails/graphql/request/component/typename.rb +27 -12
- data/lib/rails/graphql/request/component.rb +75 -36
- data/lib/rails/graphql/request/context.rb +18 -8
- data/lib/rails/graphql/request/errors.rb +16 -6
- data/lib/rails/graphql/request/event.rb +19 -8
- data/lib/rails/graphql/request/helpers/directives.rb +68 -27
- data/lib/rails/graphql/request/helpers/selection_set.rb +51 -25
- data/lib/rails/graphql/request/helpers/value_writers.rb +18 -16
- data/lib/rails/graphql/request/prepared_data.rb +98 -0
- data/lib/rails/graphql/request/steps/authorizable.rb +24 -14
- data/lib/rails/graphql/request/steps/organizable.rb +110 -48
- data/lib/rails/graphql/request/steps/{prepareable.rb → preparable.rb} +20 -7
- data/lib/rails/graphql/request/steps/{resolveable.rb → resolvable.rb} +15 -6
- data/lib/rails/graphql/request/strategy/cached_strategy.rb +64 -0
- data/lib/rails/graphql/request/strategy/dynamic_instance.rb +6 -6
- data/lib/rails/graphql/request/strategy/multi_query_strategy.rb +6 -13
- data/lib/rails/graphql/request/strategy/sequenced_strategy.rb +9 -9
- data/lib/rails/graphql/request/strategy.rb +131 -75
- data/lib/rails/graphql/request/subscription.rb +80 -0
- data/lib/rails/graphql/request.rb +305 -86
- data/lib/rails/graphql/schema.rb +240 -48
- data/lib/rails/graphql/shortcuts.rb +22 -3
- data/lib/rails/graphql/source/active_record/builders.rb +49 -35
- data/lib/rails/graphql/source/active_record_source.rb +70 -54
- data/lib/rails/graphql/source/base.rb +111 -0
- data/lib/rails/graphql/source/builder.rb +128 -0
- data/lib/rails/graphql/source/scoped_arguments.rb +31 -19
- data/lib/rails/graphql/source.rb +89 -213
- data/lib/rails/graphql/subscription/provider/action_cable.rb +112 -0
- data/lib/rails/graphql/subscription/provider/base.rb +191 -0
- data/lib/rails/graphql/subscription/provider.rb +18 -0
- data/lib/rails/graphql/subscription/store/base.rb +145 -0
- data/lib/rails/graphql/subscription/store/memory.rb +127 -0
- data/lib/rails/graphql/subscription/store.rb +19 -0
- data/lib/rails/graphql/subscription.rb +17 -0
- data/lib/rails/graphql/to_gql.rb +29 -32
- data/lib/rails/graphql/type/enum/directive_location_enum.rb +11 -11
- data/lib/rails/graphql/type/enum/type_kind_enum.rb +3 -3
- data/lib/rails/graphql/type/enum.rb +34 -48
- data/lib/rails/graphql/type/input.rb +74 -23
- data/lib/rails/graphql/type/interface.rb +16 -26
- data/lib/rails/graphql/type/object/directive_object.rb +4 -4
- data/lib/rails/graphql/type/object/enum_value_object.rb +3 -3
- data/lib/rails/graphql/type/object/field_object.rb +24 -6
- data/lib/rails/graphql/type/object/input_value_object.rb +3 -3
- data/lib/rails/graphql/type/object/schema_object.rb +5 -8
- data/lib/rails/graphql/type/object/type_object.rb +29 -19
- data/lib/rails/graphql/type/object.rb +26 -23
- data/lib/rails/graphql/type/scalar/any_scalar.rb +30 -0
- data/lib/rails/graphql/type/scalar/bigint_scalar.rb +5 -5
- data/lib/rails/graphql/type/scalar/binary_scalar.rb +3 -3
- data/lib/rails/graphql/type/scalar/boolean_scalar.rb +8 -8
- data/lib/rails/graphql/type/scalar/date_scalar.rb +3 -3
- data/lib/rails/graphql/type/scalar/date_time_scalar.rb +3 -3
- data/lib/rails/graphql/type/scalar/decimal_scalar.rb +3 -3
- data/lib/rails/graphql/type/scalar/float_scalar.rb +5 -5
- data/lib/rails/graphql/type/scalar/id_scalar.rb +6 -5
- data/lib/rails/graphql/type/scalar/int_scalar.rb +6 -5
- data/lib/rails/graphql/type/scalar/json_scalar.rb +39 -0
- data/lib/rails/graphql/type/scalar/string_scalar.rb +18 -4
- data/lib/rails/graphql/type/scalar/time_scalar.rb +5 -5
- data/lib/rails/graphql/type/scalar.rb +25 -22
- data/lib/rails/graphql/type/union.rb +14 -16
- data/lib/rails/graphql/type.rb +34 -25
- data/lib/rails/graphql/type_map.rb +256 -164
- data/lib/rails/graphql/uri.rb +166 -0
- data/lib/rails/graphql/version.rb +15 -3
- data/lib/rails/graphql.rake +3 -0
- data/lib/rails/graphql.rb +85 -52
- data/lib/rails-graphql.rb +1 -1
- data/test/assets/en.yml +29 -0
- data/test/assets/introspection-mem.txt +1 -1
- data/test/assets/mem.gql +18 -45
- data/test/assets/mysql.gql +392 -0
- data/test/assets/sqlite.gql +21 -12
- data/test/assets/translate.gql +335 -0
- data/test/config.rb +18 -8
- data/test/graphql/schema_test.rb +12 -19
- data/test/graphql/source_test.rb +8 -75
- data/test/graphql/type/enum_test.rb +207 -203
- data/test/graphql/type/input_test.rb +14 -9
- data/test/graphql/type/interface_test.rb +4 -4
- data/test/graphql/type/scalar/any_scalar_test.rb +38 -0
- data/test/graphql/type/scalar/boolean_scalar_test.rb +6 -3
- data/test/graphql/type/scalar/json_scalar_test.rb +23 -0
- data/test/graphql/type_map_test.rb +51 -66
- data/test/graphql/type_test.rb +0 -19
- data/test/graphql_test.rb +1 -1
- data/test/integration/{authorization/authorization_test.rb → authorization_test.rb} +40 -14
- data/test/integration/config.rb +36 -3
- data/test/integration/customization_test.rb +39 -0
- data/test/integration/global_id_test.rb +99 -0
- data/test/integration/memory/star_wars_introspection_test.rb +24 -16
- data/test/integration/memory/star_wars_query_test.rb +54 -3
- data/test/integration/memory/star_wars_validation_test.rb +1 -1
- data/test/integration/mysql/star_wars_introspection_test.rb +25 -0
- data/test/integration/persisted_query_test.rb +87 -0
- data/test/integration/resolver_precedence_test.rb +154 -0
- data/test/integration/schemas/memory.rb +22 -7
- data/test/integration/schemas/mysql.rb +62 -0
- data/test/integration/schemas/sqlite.rb +21 -12
- data/test/integration/sqlite/star_wars_global_id_test.rb +83 -0
- data/test/integration/sqlite/star_wars_introspection_test.rb +10 -0
- data/test/integration/sqlite/star_wars_query_test.rb +14 -1
- data/test/integration/translate_test.rb +61 -0
- data/test/test_ext.rb +16 -13
- metadata +108 -157
- data/ext/depend +0 -3
- data/ext/graphqlparser/Ast.cpp +0 -346
- data/ext/graphqlparser/Ast.h +0 -1214
- data/ext/graphqlparser/AstNode.h +0 -36
- data/ext/graphqlparser/AstVisitor.h +0 -137
- data/ext/graphqlparser/GraphQLParser.cpp +0 -76
- data/ext/graphqlparser/GraphQLParser.h +0 -55
- data/ext/graphqlparser/JsonVisitor.cpp +0 -161
- data/ext/graphqlparser/JsonVisitor.cpp.inc +0 -456
- data/ext/graphqlparser/JsonVisitor.h +0 -121
- data/ext/graphqlparser/JsonVisitor.h.inc +0 -110
- data/ext/graphqlparser/VERSION +0 -1
- data/ext/graphqlparser/c/GraphQLAst.cpp +0 -324
- data/ext/graphqlparser/c/GraphQLAst.h +0 -180
- data/ext/graphqlparser/c/GraphQLAstForEachConcreteType.h +0 -44
- data/ext/graphqlparser/c/GraphQLAstNode.cpp +0 -25
- data/ext/graphqlparser/c/GraphQLAstNode.h +0 -33
- data/ext/graphqlparser/c/GraphQLAstToJSON.cpp +0 -21
- data/ext/graphqlparser/c/GraphQLAstToJSON.h +0 -24
- data/ext/graphqlparser/c/GraphQLAstVisitor.cpp +0 -55
- data/ext/graphqlparser/c/GraphQLAstVisitor.h +0 -53
- data/ext/graphqlparser/c/GraphQLParser.cpp +0 -35
- data/ext/graphqlparser/c/GraphQLParser.h +0 -54
- data/ext/graphqlparser/dump_json_ast.cpp +0 -48
- data/ext/graphqlparser/lexer.lpp +0 -324
- data/ext/graphqlparser/parser.ypp +0 -693
- data/ext/graphqlparser/parsergen/lexer.cpp +0 -2633
- data/ext/graphqlparser/parsergen/lexer.h +0 -528
- data/ext/graphqlparser/parsergen/location.hh +0 -189
- data/ext/graphqlparser/parsergen/parser.tab.cpp +0 -3300
- data/ext/graphqlparser/parsergen/parser.tab.hpp +0 -646
- data/ext/graphqlparser/parsergen/position.hh +0 -179
- data/ext/graphqlparser/parsergen/stack.hh +0 -156
- data/ext/graphqlparser/syntaxdefs.h +0 -19
- data/ext/libgraphqlparser/AstNode.h +0 -36
- data/ext/libgraphqlparser/CMakeLists.txt +0 -148
- data/ext/libgraphqlparser/CONTRIBUTING.md +0 -23
- data/ext/libgraphqlparser/GraphQLParser.cpp +0 -76
- data/ext/libgraphqlparser/GraphQLParser.h +0 -55
- data/ext/libgraphqlparser/JsonVisitor.cpp +0 -161
- data/ext/libgraphqlparser/JsonVisitor.h +0 -121
- data/ext/libgraphqlparser/LICENSE +0 -22
- data/ext/libgraphqlparser/README.clang-tidy +0 -7
- data/ext/libgraphqlparser/README.md +0 -84
- data/ext/libgraphqlparser/ast/ast.ast +0 -203
- data/ext/libgraphqlparser/ast/ast.py +0 -61
- data/ext/libgraphqlparser/ast/c.py +0 -100
- data/ext/libgraphqlparser/ast/c.pyc +0 -0
- data/ext/libgraphqlparser/ast/c_impl.py +0 -61
- data/ext/libgraphqlparser/ast/c_impl.pyc +0 -0
- data/ext/libgraphqlparser/ast/c_visitor_impl.py +0 -39
- data/ext/libgraphqlparser/ast/c_visitor_impl.pyc +0 -0
- data/ext/libgraphqlparser/ast/casing.py +0 -26
- data/ext/libgraphqlparser/ast/casing.pyc +0 -0
- data/ext/libgraphqlparser/ast/cxx.py +0 -197
- data/ext/libgraphqlparser/ast/cxx.pyc +0 -0
- data/ext/libgraphqlparser/ast/cxx_impl.py +0 -61
- data/ext/libgraphqlparser/ast/cxx_impl.pyc +0 -0
- data/ext/libgraphqlparser/ast/cxx_json_visitor_header.py +0 -42
- data/ext/libgraphqlparser/ast/cxx_json_visitor_header.pyc +0 -0
- data/ext/libgraphqlparser/ast/cxx_json_visitor_impl.py +0 -80
- data/ext/libgraphqlparser/ast/cxx_json_visitor_impl.pyc +0 -0
- data/ext/libgraphqlparser/ast/cxx_visitor.py +0 -64
- data/ext/libgraphqlparser/ast/cxx_visitor.pyc +0 -0
- data/ext/libgraphqlparser/ast/js.py +0 -65
- data/ext/libgraphqlparser/ast/license.py +0 -10
- data/ext/libgraphqlparser/ast/license.pyc +0 -0
- data/ext/libgraphqlparser/c/GraphQLAstNode.cpp +0 -25
- data/ext/libgraphqlparser/c/GraphQLAstNode.h +0 -33
- data/ext/libgraphqlparser/c/GraphQLAstToJSON.cpp +0 -21
- data/ext/libgraphqlparser/c/GraphQLAstToJSON.h +0 -24
- data/ext/libgraphqlparser/c/GraphQLAstVisitor.cpp +0 -55
- data/ext/libgraphqlparser/c/GraphQLAstVisitor.h +0 -53
- data/ext/libgraphqlparser/c/GraphQLParser.cpp +0 -35
- data/ext/libgraphqlparser/c/GraphQLParser.h +0 -54
- data/ext/libgraphqlparser/clang-tidy-all.sh +0 -3
- data/ext/libgraphqlparser/cmake/version.cmake +0 -16
- data/ext/libgraphqlparser/dump_json_ast.cpp +0 -48
- data/ext/libgraphqlparser/go/README.md +0 -20
- data/ext/libgraphqlparser/go/callbacks.go +0 -18
- data/ext/libgraphqlparser/go/gotest.go +0 -64
- data/ext/libgraphqlparser/lexer.lpp +0 -324
- data/ext/libgraphqlparser/libgraphqlparser.pc.in +0 -11
- data/ext/libgraphqlparser/parser.ypp +0 -693
- data/ext/libgraphqlparser/parsergen/lexer.cpp +0 -2633
- data/ext/libgraphqlparser/parsergen/lexer.h +0 -528
- data/ext/libgraphqlparser/parsergen/location.hh +0 -189
- data/ext/libgraphqlparser/parsergen/parser.tab.cpp +0 -3300
- data/ext/libgraphqlparser/parsergen/parser.tab.hpp +0 -646
- data/ext/libgraphqlparser/parsergen/position.hh +0 -179
- data/ext/libgraphqlparser/parsergen/stack.hh +0 -156
- data/ext/libgraphqlparser/python/CMakeLists.txt +0 -14
- data/ext/libgraphqlparser/python/README.md +0 -5
- data/ext/libgraphqlparser/python/example.py +0 -31
- data/ext/libgraphqlparser/syntaxdefs.h +0 -19
- data/ext/libgraphqlparser/test/BuildCAPI.c +0 -5
- data/ext/libgraphqlparser/test/CMakeLists.txt +0 -25
- data/ext/libgraphqlparser/test/JsonVisitorTests.cpp +0 -28
- data/ext/libgraphqlparser/test/ParserTests.cpp +0 -352
- data/ext/libgraphqlparser/test/kitchen-sink.graphql +0 -59
- data/ext/libgraphqlparser/test/kitchen-sink.json +0 -1
- data/ext/libgraphqlparser/test/schema-kitchen-sink.graphql +0 -78
- data/ext/libgraphqlparser/test/schema-kitchen-sink.json +0 -1
- data/ext/libgraphqlparser/test/valgrind.supp +0 -33
- data/ext/version.cpp +0 -21
- data/lib/graphqlparser.so +0 -0
- data/lib/rails/graphql/native/functions.rb +0 -38
- data/lib/rails/graphql/native/location.rb +0 -41
- data/lib/rails/graphql/native/pointers.rb +0 -23
- data/lib/rails/graphql/native/visitor.rb +0 -349
- data/lib/rails/graphql/native.rb +0 -56
- data/test/integration/schemas/authorization.rb +0 -12
data/ext/shared.c
ADDED
@@ -0,0 +1,482 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
|
3
|
+
#include "shared.h"
|
4
|
+
|
5
|
+
VALUE GQLParser = Qnil;
|
6
|
+
VALUE QLGParserToken = Qnil;
|
7
|
+
VALUE gql_eParserError = Qnil;
|
8
|
+
|
9
|
+
const char *GQL_VALUE_KEYWORDS[] = {
|
10
|
+
"true",
|
11
|
+
"false",
|
12
|
+
"null"
|
13
|
+
};
|
14
|
+
|
15
|
+
const char *GQL_EXECUTION_KEYWORDS[] = {
|
16
|
+
"query",
|
17
|
+
"mutation",
|
18
|
+
"subscription",
|
19
|
+
"fragment",
|
20
|
+
"on"
|
21
|
+
};
|
22
|
+
|
23
|
+
const char *GQL_DEFINITION_KEYWORDS[] = {
|
24
|
+
"schema",
|
25
|
+
"directive",
|
26
|
+
"enum",
|
27
|
+
"input",
|
28
|
+
"interface",
|
29
|
+
"scalar",
|
30
|
+
"type",
|
31
|
+
"union",
|
32
|
+
"extend",
|
33
|
+
"implements",
|
34
|
+
"repeatable"
|
35
|
+
};
|
36
|
+
|
37
|
+
/* INTERNAL HELPERS */
|
38
|
+
// Just a helper to print things on the console while testing/debugging
|
39
|
+
void gql_debug_print(const char *message)
|
40
|
+
{
|
41
|
+
rb_funcall(rb_mKernel, rb_intern("puts"), 1, rb_str_new2(message));
|
42
|
+
}
|
43
|
+
|
44
|
+
// Initialize a new scanner
|
45
|
+
struct gql_scanner gql_new_scanner(VALUE source)
|
46
|
+
{
|
47
|
+
char *doc = RSTRING_PTR(source);
|
48
|
+
struct gql_scanner scanner = {
|
49
|
+
.start_pos = 1, // Set to 1 just to begin different from the current position
|
50
|
+
.current_pos = 0,
|
51
|
+
.current_line = 1,
|
52
|
+
.last_ln_at = 0,
|
53
|
+
.current = doc[0],
|
54
|
+
.doc = doc};
|
55
|
+
|
56
|
+
return scanner;
|
57
|
+
}
|
58
|
+
|
59
|
+
// Returns the base index of the lexeme from where the upgrade should move from
|
60
|
+
enum gql_lexeme gql_upgrade_basis(const char *upgrade_from[])
|
61
|
+
{
|
62
|
+
if (*upgrade_from == *GQL_VALUE_KEYWORDS)
|
63
|
+
return gql_iv_true;
|
64
|
+
else if (*upgrade_from == *GQL_EXECUTION_KEYWORDS)
|
65
|
+
return gql_ie_query;
|
66
|
+
else if (*upgrade_from == *GQL_DEFINITION_KEYWORDS)
|
67
|
+
return gql_id_schema;
|
68
|
+
else
|
69
|
+
return gql_i_unknown;
|
70
|
+
}
|
71
|
+
|
72
|
+
// This checks if the identifier in the scanner should be upgraded to a keyword
|
73
|
+
enum gql_lexeme gql_name_to_keyword(struct gql_scanner *scanner, const char *upgrade_from[])
|
74
|
+
{
|
75
|
+
unsigned long pos, len = GQL_SCAN_SIZE(scanner);
|
76
|
+
unsigned int valid = 0, i = 0;
|
77
|
+
const char *keyword;
|
78
|
+
|
79
|
+
// Check until it finds the end of the array
|
80
|
+
while ((keyword = upgrade_from[i]) != 0)
|
81
|
+
{
|
82
|
+
// Move ot the next item and check the current for different size
|
83
|
+
if(strlen(keyword) == len)
|
84
|
+
{
|
85
|
+
// We cannot use the normal strcomp because we are comparing a mid part of the string
|
86
|
+
for (pos = 0, valid = 1; valid == 1 && pos < len; pos++)
|
87
|
+
{
|
88
|
+
if (keyword[pos] != scanner->doc[scanner->start_pos + pos])
|
89
|
+
valid = 0;
|
90
|
+
}
|
91
|
+
|
92
|
+
// Only return if valid was kept as true
|
93
|
+
if (valid == 1) return gql_upgrade_basis(upgrade_from) + i;
|
94
|
+
}
|
95
|
+
|
96
|
+
// Move to the next index
|
97
|
+
i++;
|
98
|
+
}
|
99
|
+
|
100
|
+
// Return name if was not able to upgrade to a keyword
|
101
|
+
return gql_i_name;
|
102
|
+
}
|
103
|
+
|
104
|
+
/* SCANNER HELPERS */
|
105
|
+
enum gql_lexeme gql_read_name(struct gql_scanner *scanner)
|
106
|
+
{
|
107
|
+
// Read all the chars and digits
|
108
|
+
GQL_SCAN_WHILE(scanner, GQL_S_CHARACTER(scanner->current) || GQL_S_DIGIT(scanner->current));
|
109
|
+
return gql_i_name;
|
110
|
+
}
|
111
|
+
|
112
|
+
enum gql_lexeme gql_read_comment(struct gql_scanner *scanner)
|
113
|
+
{
|
114
|
+
// Move forward until it finds a new line, change the line indicator and return
|
115
|
+
GQL_SCAN_WHILE(scanner, scanner->current != '\n');
|
116
|
+
GQL_SCAN_NEW_LINE(scanner);
|
117
|
+
return gql_i_comment;
|
118
|
+
}
|
119
|
+
|
120
|
+
enum gql_lexeme gql_read_hash(struct gql_scanner *scanner)
|
121
|
+
{
|
122
|
+
// Start with 1 curly open and get the next
|
123
|
+
int curly_opens = 1;
|
124
|
+
GQL_SCAN_NEXT(scanner);
|
125
|
+
|
126
|
+
while (curly_opens > 0)
|
127
|
+
{
|
128
|
+
// EOF returns unknown, { adds to the open, } removes from the open, " reads as string
|
129
|
+
if (scanner->current == '\0')
|
130
|
+
return gql_i_unknown;
|
131
|
+
else if (scanner->current == '"' && gql_read_string(scanner, 0) != gql_iv_string)
|
132
|
+
return gql_i_unknown;
|
133
|
+
else if (scanner->current == '{')
|
134
|
+
curly_opens++;
|
135
|
+
else if (scanner->current == '}')
|
136
|
+
curly_opens--;
|
137
|
+
else if (scanner->current == '\n')
|
138
|
+
GQL_SCAN_NEW_LINE(scanner);
|
139
|
+
|
140
|
+
// Just move to the next char
|
141
|
+
GQL_SCAN_NEXT(scanner);
|
142
|
+
}
|
143
|
+
|
144
|
+
// Save the last position, move to the next and return as hash
|
145
|
+
return gql_iv_hash;
|
146
|
+
}
|
147
|
+
|
148
|
+
enum gql_lexeme gql_read_float(struct gql_scanner *scanner)
|
149
|
+
{
|
150
|
+
// If what made it get in here was an '.', then it can recurse to the exponent of a fraction
|
151
|
+
int at_fraction = scanner->current == '.';
|
152
|
+
|
153
|
+
// Skip the float mark and maybe
|
154
|
+
GQL_SCAN_NEXT(scanner);
|
155
|
+
|
156
|
+
// Skip the exponent sign if possible
|
157
|
+
if (!at_fraction && (scanner->current == '+' || scanner->current == '-'))
|
158
|
+
GQL_SCAN_NEXT(scanner);
|
159
|
+
|
160
|
+
// If the current char is not a digit, we have an unknown
|
161
|
+
if (!GQL_S_DIGIT(scanner->current)) return gql_i_unknown;
|
162
|
+
GQL_SCAN_NEXT(scanner);
|
163
|
+
|
164
|
+
// Read all the numbers
|
165
|
+
GQL_SCAN_WHILE(scanner, GQL_S_DIGIT(scanner->current));
|
166
|
+
|
167
|
+
// If it is at fraction and the next is an exponent marker, then recurse
|
168
|
+
if (at_fraction && (scanner->current == 'e' || scanner->current == 'E'))
|
169
|
+
return gql_read_float(scanner);
|
170
|
+
|
171
|
+
// Otherwise save the last position and just finish the float
|
172
|
+
return gql_iv_float;
|
173
|
+
}
|
174
|
+
|
175
|
+
enum gql_lexeme gql_read_number(struct gql_scanner *scanner)
|
176
|
+
{
|
177
|
+
// Pass over the negative sign
|
178
|
+
if (scanner->current == '-') GQL_SCAN_NEXT(scanner);
|
179
|
+
|
180
|
+
// If begins with zero, it can only be 0 or error
|
181
|
+
if (scanner->current == '0')
|
182
|
+
return (GQL_S_DIGIT(GQL_SCAN_LOOK(scanner, 1))) ? gql_i_unknown : gql_iv_integer;
|
183
|
+
|
184
|
+
// Read all the numbers
|
185
|
+
GQL_SCAN_WHILE(scanner, GQL_S_DIGIT(scanner->current));
|
186
|
+
|
187
|
+
// Save the last position and halt the process if it's not a float marker
|
188
|
+
return (GQL_S_FLOAT_MARK(scanner->current)) ? gql_read_float(scanner) : gql_iv_integer;
|
189
|
+
}
|
190
|
+
|
191
|
+
enum gql_lexeme gql_read_string(struct gql_scanner *scanner, int allow_heredoc)
|
192
|
+
{
|
193
|
+
int start_size, end_size = 0;
|
194
|
+
unsigned long start = scanner->current_pos;
|
195
|
+
|
196
|
+
// Read all the initial quotes and save the size
|
197
|
+
GQL_SCAN_WHILE(scanner, scanner->current == '"');
|
198
|
+
start_size = (int)(scanner->current_pos - start);
|
199
|
+
|
200
|
+
// 4, 5, or more than 6 means an invalid triple-quotes block
|
201
|
+
if (start_size == 4 || start_size == 5 || start_size > 6)
|
202
|
+
return gql_i_unknown;
|
203
|
+
|
204
|
+
// 3 but not accepting heredoc returns an unknown
|
205
|
+
if (allow_heredoc == 0 && start_size == 3)
|
206
|
+
return gql_i_unknown;
|
207
|
+
|
208
|
+
// 2 or 6 means empty string
|
209
|
+
if (start_size == 2 || start_size == 6)
|
210
|
+
return gql_iv_string;
|
211
|
+
|
212
|
+
// Read until the start and end number of quotes matches
|
213
|
+
while (start_size != end_size)
|
214
|
+
{
|
215
|
+
// If it is a quote, add to end and move ot the next
|
216
|
+
if (scanner->current == '"')
|
217
|
+
{
|
218
|
+
end_size++;
|
219
|
+
}
|
220
|
+
else
|
221
|
+
{
|
222
|
+
// Anything that is not a quote reset the end size
|
223
|
+
end_size = 0;
|
224
|
+
|
225
|
+
// If we get to the end of the file, return an unknown
|
226
|
+
if (scanner->current == '\0')
|
227
|
+
return gql_i_unknown;
|
228
|
+
|
229
|
+
// Make sure to mark any new lines
|
230
|
+
if (scanner->current == '\n')
|
231
|
+
GQL_SCAN_NEW_LINE(scanner);
|
232
|
+
|
233
|
+
// Skip one extra character, which means it is skipping the escaped char
|
234
|
+
if (scanner->current == '\\')
|
235
|
+
GQL_SCAN_NEXT(scanner);
|
236
|
+
}
|
237
|
+
|
238
|
+
// Move the cursor
|
239
|
+
GQL_SCAN_NEXT(scanner);
|
240
|
+
}
|
241
|
+
|
242
|
+
// Regardless if a quote comes next, this is now a valid string
|
243
|
+
return (start_size == 3) ? gql_iv_heredoc : gql_iv_string;
|
244
|
+
}
|
245
|
+
|
246
|
+
/* MOST IMPORTANT TOKEN READ FUNCTION */
|
247
|
+
void gql_next_lexeme(struct gql_scanner *scanner)
|
248
|
+
{
|
249
|
+
// Do not move forward if it is unknown
|
250
|
+
if (scanner->lexeme == gql_i_unknown)
|
251
|
+
return;
|
252
|
+
|
253
|
+
// Temporary save the end line and end column
|
254
|
+
GQL_SCAN_SET_END(scanner, 0);
|
255
|
+
|
256
|
+
// Skip everything that can be ignored
|
257
|
+
GQL_SCAN_WHILE(scanner, GQL_S_IGNORE(scanner->current));
|
258
|
+
|
259
|
+
// Mark where the new interesting thing has started
|
260
|
+
scanner->start_pos = scanner->current_pos;
|
261
|
+
scanner->begin_line = scanner->current_line;
|
262
|
+
scanner->begin_column = scanner->current_pos - scanner->last_ln_at;
|
263
|
+
|
264
|
+
// Find what might be the next interesting thing
|
265
|
+
if (scanner->current == '\0')
|
266
|
+
scanner->lexeme = gql_i_eof;
|
267
|
+
else if (GQL_S_CHARACTER(scanner->current))
|
268
|
+
scanner->lexeme = gql_read_name(scanner);
|
269
|
+
else if (scanner->current == '#')
|
270
|
+
scanner->lexeme = gql_read_comment(scanner);
|
271
|
+
else if (GQL_S_DIGIT(scanner->current) || scanner->current == '-')
|
272
|
+
scanner->lexeme = gql_read_number(scanner);
|
273
|
+
else if (scanner->current == '"')
|
274
|
+
scanner->lexeme = gql_read_string(scanner, 1);
|
275
|
+
else if (scanner->current == '[')
|
276
|
+
scanner->lexeme = gql_is_op_brack;
|
277
|
+
else if (scanner->current == '{')
|
278
|
+
scanner->lexeme = gql_is_op_curly;
|
279
|
+
else if (scanner->current == '}')
|
280
|
+
scanner->lexeme = gql_is_cl_curly;
|
281
|
+
else if (scanner->current == '(')
|
282
|
+
scanner->lexeme = gql_is_op_paren;
|
283
|
+
else if (scanner->current == ')')
|
284
|
+
scanner->lexeme = gql_is_cl_paren;
|
285
|
+
else if (scanner->current == ':')
|
286
|
+
scanner->lexeme = gql_is_colon;
|
287
|
+
else if (scanner->current == '=')
|
288
|
+
scanner->lexeme = gql_is_equal;
|
289
|
+
else if (scanner->current == '.')
|
290
|
+
scanner->lexeme = gql_is_period;
|
291
|
+
else if (scanner->current == '@')
|
292
|
+
scanner->lexeme = gql_i_directive;
|
293
|
+
else if (scanner->current == '$')
|
294
|
+
scanner->lexeme = gql_i_variable;
|
295
|
+
else
|
296
|
+
scanner->lexeme = gql_i_unknown;
|
297
|
+
}
|
298
|
+
|
299
|
+
// Skip all comment lexemes
|
300
|
+
void gql_next_lexeme_no_comments(struct gql_scanner *scanner)
|
301
|
+
{
|
302
|
+
do
|
303
|
+
{
|
304
|
+
gql_next_lexeme(scanner);
|
305
|
+
} while (scanner->lexeme == gql_i_comment);
|
306
|
+
}
|
307
|
+
|
308
|
+
/* TOKEN CLASS HELPERS AND METHODS */
|
309
|
+
// Simply add the type of the token and return self for simplicity
|
310
|
+
VALUE gql_set_token_type(VALUE self, const char *type)
|
311
|
+
{
|
312
|
+
rb_iv_set(self, "@type", ID2SYM(rb_intern(type)));
|
313
|
+
return self;
|
314
|
+
}
|
315
|
+
|
316
|
+
// Just simply format the string with the token prefix
|
317
|
+
VALUE gql_inspect_token(VALUE self)
|
318
|
+
{
|
319
|
+
VALUE text = rb_call_super(0, 0);
|
320
|
+
|
321
|
+
if (rb_ivar_defined(self, rb_intern("@type")) == Qfalse)
|
322
|
+
return rb_sprintf("<GQLParser::Token %" PRIsVALUE ">", text);
|
323
|
+
|
324
|
+
VALUE type = rb_iv_get(self, "@type");
|
325
|
+
return rb_sprintf("<GQLParser::Token [%" PRIsVALUE "] %" PRIsVALUE ">", type, text);
|
326
|
+
}
|
327
|
+
|
328
|
+
// Check if the token is of the given type
|
329
|
+
VALUE gql_token_of_type_check(VALUE self, VALUE other)
|
330
|
+
{
|
331
|
+
VALUE type = rb_iv_get(self, "@type");
|
332
|
+
return rb_equal(type, other);
|
333
|
+
}
|
334
|
+
|
335
|
+
// Add the token module to the object and assign its location information
|
336
|
+
VALUE gql_as_token(VALUE self, struct gql_scanner *scanner, int save_type)
|
337
|
+
{
|
338
|
+
// Initialize the instance
|
339
|
+
VALUE instance = rb_class_new_instance(1, &self, QLGParserToken);
|
340
|
+
|
341
|
+
// Add the location instance variables
|
342
|
+
int offset = scanner->begin_line == 1 ? 1 : 0;
|
343
|
+
rb_iv_set(instance, "@begin_line", ULONG2NUM(scanner->begin_line));
|
344
|
+
rb_iv_set(instance, "@begin_column", ULONG2NUM(scanner->begin_column + offset));
|
345
|
+
|
346
|
+
offset = scanner->end_line == 1 ? 1 : 0;
|
347
|
+
rb_iv_set(instance, "@end_line", ULONG2NUM(scanner->end_line));
|
348
|
+
rb_iv_set(instance, "@end_column", ULONG2NUM(scanner->end_column + offset));
|
349
|
+
|
350
|
+
// Check if it has to save the type
|
351
|
+
if (save_type == 1)
|
352
|
+
{
|
353
|
+
// This only covers value types
|
354
|
+
if (scanner->lexeme == gql_iv_integer)
|
355
|
+
gql_set_token_type(instance, "int");
|
356
|
+
else if (scanner->lexeme == gql_iv_float)
|
357
|
+
gql_set_token_type(instance, "float");
|
358
|
+
else if (scanner->lexeme == gql_iv_string)
|
359
|
+
gql_set_token_type(instance, "string");
|
360
|
+
else if (scanner->lexeme == gql_iv_true)
|
361
|
+
gql_set_token_type(instance, "boolean");
|
362
|
+
else if (scanner->lexeme == gql_iv_false)
|
363
|
+
gql_set_token_type(instance, "boolean");
|
364
|
+
else if (scanner->lexeme == gql_iv_enum)
|
365
|
+
gql_set_token_type(instance, "enum");
|
366
|
+
else if (scanner->lexeme == gql_iv_array)
|
367
|
+
gql_set_token_type(instance, "array");
|
368
|
+
else if (scanner->lexeme == gql_iv_hash)
|
369
|
+
gql_set_token_type(instance, "hash");
|
370
|
+
else if (scanner->lexeme == gql_iv_heredoc)
|
371
|
+
gql_set_token_type(instance, "heredoc");
|
372
|
+
}
|
373
|
+
|
374
|
+
// Return the token instance
|
375
|
+
return instance;
|
376
|
+
}
|
377
|
+
|
378
|
+
/* RUBY-BASED HELPERS */
|
379
|
+
// Creates a Ruby String from the scanner
|
380
|
+
VALUE gql_scanner_to_s(struct gql_scanner *scanner)
|
381
|
+
{
|
382
|
+
return rb_str_new(scanner->doc + scanner->start_pos, GQL_SCAN_SIZE(scanner));
|
383
|
+
}
|
384
|
+
|
385
|
+
// Same as the above, but already extend it to a parser token
|
386
|
+
VALUE gql_scanner_to_token(struct gql_scanner *scanner)
|
387
|
+
{
|
388
|
+
return gql_as_token(gql_scanner_to_s(scanner), scanner, 0);
|
389
|
+
}
|
390
|
+
|
391
|
+
// Goes over an array and grab all the elements
|
392
|
+
VALUE gql_array_to_rb(struct gql_scanner *scanner)
|
393
|
+
{
|
394
|
+
// Start the array and the temporary element
|
395
|
+
VALUE result = rb_ary_new();
|
396
|
+
VALUE element;
|
397
|
+
|
398
|
+
// Save the scan and grab the next char
|
399
|
+
GQL_SCAN_NEXT(scanner);
|
400
|
+
|
401
|
+
// Iterate until it finds the end of the array
|
402
|
+
while (scanner->current != ']')
|
403
|
+
{
|
404
|
+
// If we got to the end of the file and the array was not closed, then we have something wrong
|
405
|
+
if (scanner->current == '\0')
|
406
|
+
{
|
407
|
+
scanner->lexeme = gql_i_unknown;
|
408
|
+
return Qnil;
|
409
|
+
}
|
410
|
+
|
411
|
+
// Save the element as an rb token, because we may need the type of each element afterwards
|
412
|
+
element = gql_value_to_token(scanner, 0);
|
413
|
+
|
414
|
+
// If it found an unknown, then we bubble the problem up
|
415
|
+
if (scanner->lexeme == gql_i_unknown)
|
416
|
+
return Qnil;
|
417
|
+
|
418
|
+
// Add the value to the array and scan through everything ignorable
|
419
|
+
rb_ary_push(result, element);
|
420
|
+
GQL_SCAN_WHILE(scanner, GQL_S_IGNORE(scanner->current));
|
421
|
+
}
|
422
|
+
|
423
|
+
// Save where the array has actually ended, change the lexeme and return
|
424
|
+
GQL_SCAN_SET_END(scanner, 0);
|
425
|
+
scanner->lexeme = gql_iv_array;
|
426
|
+
return result;
|
427
|
+
}
|
428
|
+
|
429
|
+
// Turn the current lexeme into its proper ruby object
|
430
|
+
VALUE gql_value_to_rb(struct gql_scanner *scanner, int accept_var)
|
431
|
+
{
|
432
|
+
// EXPERIMENTAL! Skip all the comments
|
433
|
+
gql_next_lexeme_no_comments(scanner);
|
434
|
+
|
435
|
+
// If got a variable and accepts variables,
|
436
|
+
// then it's fine and it won't be resolved in here
|
437
|
+
if (accept_var == 1 && scanner->lexeme == gql_i_variable)
|
438
|
+
return Qnil;
|
439
|
+
|
440
|
+
// Make sure to save the end position of the value
|
441
|
+
GQL_SCAN_SET_END(scanner, 0);
|
442
|
+
|
443
|
+
// If it's a name, then it can be a keyword or a enum value
|
444
|
+
if (scanner->lexeme == gql_i_name)
|
445
|
+
{
|
446
|
+
scanner->lexeme = gql_name_to_keyword(scanner, GQL_VALUE_KEYWORDS);
|
447
|
+
if (scanner->lexeme == gql_iv_true)
|
448
|
+
return Qtrue;
|
449
|
+
else if (scanner->lexeme == gql_iv_false)
|
450
|
+
return Qfalse;
|
451
|
+
else if (scanner->lexeme == gql_iv_null)
|
452
|
+
return Qnil;
|
453
|
+
else
|
454
|
+
scanner->lexeme = gql_iv_enum;
|
455
|
+
}
|
456
|
+
|
457
|
+
// Dealing with an array is way more complex, because you have to turn each
|
458
|
+
// individual value as an rb value
|
459
|
+
if (scanner->lexeme == gql_is_op_brack)
|
460
|
+
return gql_array_to_rb(scanner);
|
461
|
+
|
462
|
+
// If it is a hash, then we can just read through it and later get as a string
|
463
|
+
if (scanner->lexeme == gql_is_op_curly)
|
464
|
+
scanner->lexeme = gql_read_hash(scanner);
|
465
|
+
|
466
|
+
// By getting here with a proper value, just return the string of it, which
|
467
|
+
// will be dealt in the request
|
468
|
+
if (GQL_I_VALUE(scanner->lexeme))
|
469
|
+
return gql_scanner_to_s(scanner);
|
470
|
+
|
471
|
+
// If it got to this point, then it's an unknown
|
472
|
+
scanner->lexeme = gql_i_unknown;
|
473
|
+
return Qnil;
|
474
|
+
}
|
475
|
+
|
476
|
+
// Same as the above, but already extend it to a parser token
|
477
|
+
// IMPORTANT! This might generate a problem because nil, true, and false won't
|
478
|
+
// become parser tokens
|
479
|
+
VALUE gql_value_to_token(struct gql_scanner *scanner, int accept_var)
|
480
|
+
{
|
481
|
+
return gql_as_token(gql_value_to_rb(scanner, accept_var), scanner, 1);
|
482
|
+
}
|
data/ext/shared.h
ADDED
@@ -0,0 +1,177 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
|
3
|
+
#if !defined RB_INT_PARSE_DEFAULT
|
4
|
+
#define RB_INT_PARSE_DEFAULT 0x07
|
5
|
+
#endif
|
6
|
+
|
7
|
+
#define GQL_PUTS(...) gql_debug_print(RSTRING_PTR(rb_sprintf(__VA_ARGS__)))
|
8
|
+
|
9
|
+
#define GQL_I_STRUCTURE_FST 0x10
|
10
|
+
#define GQL_I_STRUCTURE_LST 0x1f
|
11
|
+
|
12
|
+
#define GQL_I_VALUE_FST 0x20
|
13
|
+
#define GQL_I_VALUE_LST 0x2f
|
14
|
+
|
15
|
+
#define GQL_I_EXECUTION_FST 0x30
|
16
|
+
#define GQL_I_EXECUTION_LST 0x3f
|
17
|
+
|
18
|
+
#define GQL_I_OPERATIONS_FST 0x30
|
19
|
+
#define GQL_I_OPERATIONS_LST 0x32
|
20
|
+
|
21
|
+
#define GQL_I_DEFINITION_FST 0x40
|
22
|
+
#define GQL_I_DEFINITION_LST 0x4f
|
23
|
+
|
24
|
+
#define GQL_I_STRUCTURE(x) (x >= GQL_I_STRUCTURE_FST && x <= GQL_I_STRUCTURE_LST)
|
25
|
+
#define GQL_I_VALUE(x) (x >= GQL_I_VALUE_FST && x <= GQL_I_VALUE_LST)
|
26
|
+
#define GQL_I_EXECUTION(x) (x >= GQL_I_EXECUTION_FST && x <= GQL_I_EXECUTION_LST)
|
27
|
+
#define QGL_I_OPERATION(x) (x >= GQL_I_OPERATIONS_FST && x <= GQL_I_OPERATIONS_LST)
|
28
|
+
#define GQL_I_DEFINITION(x) (x >= GQL_I_DEFINITION_FST && x <= GQL_I_DEFINITION_LST)
|
29
|
+
|
30
|
+
// https://www.asciitable.com/
|
31
|
+
#define GQL_S_IGNORE(x) (x == ' ' || x == ',' || x == '\n' || x == '\r' || x == '\t' || x == '\f' || x == '\b')
|
32
|
+
#define GQL_S_CHARACTER(x) ((x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z') || x == '_')
|
33
|
+
#define GQL_S_DIGIT(x) (x >= '0' && x <= '9')
|
34
|
+
#define GQL_S_FLOAT_MARK(x) (x == '.' || x == 'e' || x == 'E')
|
35
|
+
|
36
|
+
#define GQL_SCAN_ERROR(scanner) (scanner->lexeme == gql_i_eof || scanner->lexeme == gql_i_unknown)
|
37
|
+
#define GQL_SCAN_SIZE(scanner) (scanner->current_pos - scanner->start_pos)
|
38
|
+
#define GQL_SCAN_CHAR(scanner) (scanner->doc[scanner->current_pos])
|
39
|
+
#define GQL_SCAN_LOOK(scanner, bytes) (scanner->doc[scanner->current_pos + bytes])
|
40
|
+
#define GQL_SCAN_NEXT(scanner) ({ \
|
41
|
+
scanner->current_pos++; \
|
42
|
+
scanner->current = GQL_SCAN_CHAR(scanner); \
|
43
|
+
})
|
44
|
+
#define GQL_SCAN_NEW_LINE(scanner) ({ \
|
45
|
+
scanner->last_ln_at = scanner->current_pos; \
|
46
|
+
scanner->current_line++; \
|
47
|
+
})
|
48
|
+
#define GQL_SCAN_WHILE(scanner, check) ({ \
|
49
|
+
while (check) \
|
50
|
+
{ \
|
51
|
+
if (GQL_SCAN_CHAR(scanner) == '\n') \
|
52
|
+
{ \
|
53
|
+
GQL_SCAN_NEW_LINE(scanner); \
|
54
|
+
} \
|
55
|
+
GQL_SCAN_NEXT(scanner); \
|
56
|
+
} \
|
57
|
+
})
|
58
|
+
#define GQL_SCAN_SET_END(scanner, offset) ({ \
|
59
|
+
scanner->end_line = scanner->begin_line; \
|
60
|
+
scanner->end_column = scanner->current_pos - offset - scanner->last_ln_at; \
|
61
|
+
})
|
62
|
+
#define GQL_SCAN_SAVE(scanner, memory) ({ \
|
63
|
+
memory[0] = scanner->begin_line; \
|
64
|
+
memory[1] = scanner->begin_column; \
|
65
|
+
})
|
66
|
+
|
67
|
+
#define GQL_SAFE_PUSH(source, value) ({ \
|
68
|
+
if (NIL_P(source)) \
|
69
|
+
source = rb_ary_new(); \
|
70
|
+
rb_ary_push(source, value); \
|
71
|
+
})
|
72
|
+
|
73
|
+
enum gql_lexeme
|
74
|
+
{
|
75
|
+
// Basic identifiers
|
76
|
+
gql_i_eof = 0x00,
|
77
|
+
gql_i_name = 0x01,
|
78
|
+
gql_i_comment = 0x02,
|
79
|
+
gql_i_variable = 0x03,
|
80
|
+
gql_i_directive = 0x04,
|
81
|
+
|
82
|
+
// Structure identifiers
|
83
|
+
gql_is_op_curly = 0x10,
|
84
|
+
gql_is_cl_curly = 0x11,
|
85
|
+
gql_is_op_paren = 0x12,
|
86
|
+
gql_is_cl_paren = 0x13,
|
87
|
+
gql_is_op_brack = 0x14,
|
88
|
+
gql_is_cl_brack = 0x15,
|
89
|
+
gql_is_colon = 0x16,
|
90
|
+
gql_is_equal = 0x17,
|
91
|
+
gql_is_period = 0x18,
|
92
|
+
|
93
|
+
// Value based types
|
94
|
+
gql_iv_integer = 0x20,
|
95
|
+
gql_iv_float = 0x21,
|
96
|
+
gql_iv_string = 0x22,
|
97
|
+
gql_iv_true = 0x23,
|
98
|
+
gql_iv_false = 0x24,
|
99
|
+
gql_iv_null = 0x25,
|
100
|
+
gql_iv_enum = 0x26,
|
101
|
+
gql_iv_array = 0x27,
|
102
|
+
gql_iv_hash = 0x28,
|
103
|
+
gql_iv_heredoc = 0x2f,
|
104
|
+
|
105
|
+
// Execution keywords
|
106
|
+
gql_ie_query = 0x30,
|
107
|
+
gql_ie_mutation = 0x31,
|
108
|
+
gql_ie_subscription = 0x32,
|
109
|
+
gql_ie_fragment = 0x33,
|
110
|
+
gql_ie_on = 0x34,
|
111
|
+
|
112
|
+
// Definition keywords
|
113
|
+
gql_id_schema = 0x40,
|
114
|
+
gql_id_directive = 0x41,
|
115
|
+
gql_id_enum = 0x42,
|
116
|
+
gql_id_input = 0x43,
|
117
|
+
gql_id_interface = 0x44,
|
118
|
+
gql_id_scalar = 0x45,
|
119
|
+
gql_id_type = 0x46,
|
120
|
+
gql_id_union = 0x47,
|
121
|
+
gql_id_extend = 0x48,
|
122
|
+
gql_id_implements = 0x49,
|
123
|
+
gql_id_repeatable = 0x4a,
|
124
|
+
|
125
|
+
// Something went wrong
|
126
|
+
gql_i_unknown = 0xff
|
127
|
+
};
|
128
|
+
|
129
|
+
struct gql_scanner
|
130
|
+
{
|
131
|
+
unsigned long start_pos;
|
132
|
+
unsigned long current_pos;
|
133
|
+
unsigned long current_line;
|
134
|
+
unsigned long last_ln_at;
|
135
|
+
unsigned long begin_line;
|
136
|
+
unsigned long begin_column;
|
137
|
+
unsigned long end_line;
|
138
|
+
unsigned long end_column;
|
139
|
+
char *doc;
|
140
|
+
char current;
|
141
|
+
enum gql_lexeme lexeme;
|
142
|
+
};
|
143
|
+
|
144
|
+
VALUE GQLParser;
|
145
|
+
VALUE QLGParserToken;
|
146
|
+
VALUE gql_eParserError;
|
147
|
+
|
148
|
+
const char *GQL_VALUE_KEYWORDS[3];
|
149
|
+
const char *GQL_EXECUTION_KEYWORDS[5];
|
150
|
+
const char *GQL_DEFINITION_KEYWORDS[12];
|
151
|
+
|
152
|
+
void gql_debug_print(const char *message);
|
153
|
+
struct gql_scanner gql_new_scanner(VALUE source);
|
154
|
+
|
155
|
+
enum gql_lexeme gql_upgrade_basis(const char *upgrade_from[]);
|
156
|
+
enum gql_lexeme gql_name_to_keyword(struct gql_scanner *scanner, const char *upgrade_from[]);
|
157
|
+
|
158
|
+
enum gql_lexeme gql_read_name(struct gql_scanner *scanner);
|
159
|
+
enum gql_lexeme gql_read_comment(struct gql_scanner *scanner);
|
160
|
+
enum gql_lexeme gql_read_hash(struct gql_scanner *scanner);
|
161
|
+
enum gql_lexeme gql_read_float(struct gql_scanner *scanner);
|
162
|
+
enum gql_lexeme gql_read_number(struct gql_scanner *scanner);
|
163
|
+
enum gql_lexeme gql_read_string(struct gql_scanner *scanner, int allow_heredoc);
|
164
|
+
|
165
|
+
void gql_next_lexeme(struct gql_scanner *scanner);
|
166
|
+
void gql_next_lexeme_no_comments(struct gql_scanner *scanner);
|
167
|
+
|
168
|
+
VALUE gql_set_token_type(VALUE self, const char *type);
|
169
|
+
VALUE gql_inspect_token(VALUE self);
|
170
|
+
VALUE gql_token_of_type_check(VALUE self, VALUE other);
|
171
|
+
VALUE gql_as_token(VALUE self, struct gql_scanner *scanner, int save_type);
|
172
|
+
|
173
|
+
VALUE gql_scanner_to_s(struct gql_scanner *scanner);
|
174
|
+
VALUE gql_scanner_to_token(struct gql_scanner *scanner);
|
175
|
+
VALUE gql_array_to_rb(struct gql_scanner *scanner);
|
176
|
+
VALUE gql_value_to_rb(struct gql_scanner *scanner, int accept_var);
|
177
|
+
VALUE gql_value_to_token(struct gql_scanner *scanner, int accept_var);
|
data/lib/gql_parser.so
ADDED
Binary file
|