1# A simple grammar for GraphQL 2%grammar graphql 3%version 0.01 4%include pegex-atoms 5 6# canonical: https://github.com/facebook/graphql/blob/master/spec/Appendix%20B%20--%20Grammar%20Summary.md 7# IDL RFC: https://github.com/facebook/graphql/pull/90 8# inspiration drawn from the slightly obsolete https://github.com/antlr/grammars-v4/blob/master/graphql/GraphQL.g4 9# string and number from https://github.com/ingydotnet/json-pgx/blob/master/json.pgx 10 11# in order to capture comments *before* a given rule-group *into* it, 12# can't suck up whitespace *after* rule-groups as part of them 13graphql: definition+ 14 15definition: (operationDefinition | fragment | typeSystemDefinition | .ws2) 16 17operationDefinition: selectionSet | operationType .(-) name? .(-) variableDefinitions? .(-) directives? selectionSet 18 19operationType: /(query|mutation|subscription)/ 20 21selectionSet: .(/- LCURLY -/) ( selection+ | `Expected name` ) .(/- RCURLY -/) 22 23selection: (field | inline_fragment | fragment_spread) .(-) 24 25field: alias? name .(-) arguments? .(-) directives? selectionSet? 26 27alias: name .(/- COLON -/) 28 29arguments: .(/- LPAREN -/) argument+ .(/- RPAREN -/) 30 31argument: name .(/- COLON -/) value 32 33fragment_spread: .spread fragmentName .(-) directives? 34 35inline_fragment: .spread typeCondition? .(-) directives? selectionSet 36 37fragment: .(/- 'fragment' -/) fragmentName .(-) (typeCondition | `Expected "on"`) .(-) directives? selectionSet 38 39fragmentName: ('on' `Unexpected Name "on"` | name) 40 41typeCondition: .(/'on' -/) namedType 42 43value: (variable | float | int | string | boolean | null | enumValue | listValue | objectValue) .(-) 44 45value_const: (float | int | string | boolean | null | enumValue | listValue_const | objectValue_const) .(-) 46 47boolean: /(true|false)/ 48 49null: /(null)/ 50 51enumValue: (/(true|false|null)/ `Invalid enum value` | name) 52 53listValue: .(/- LSQUARE -/) value* .(/- RSQUARE -/) 54 55listValue_const: .(/- LSQUARE -/) value_const* .(/- RSQUARE -/) 56 57objectValue: .(/- LCURLY -/) ( objectField+ | `Expected name` ) .(/- RCURLY -/) 58 59objectValue_const: .(/- LCURLY -/) ( objectField_const+ | `Expected name or constant` ) .(/- RCURLY -/) 60 61objectField: name .(/- COLON -/) value .(-) 62 63objectField_const: name .(/- COLON -/) value_const 64 65variableDefinitions: .(/- LPAREN -/) ( variableDefinition+ | `Expected $argument: Type` ) .(/- RPAREN -/) 66 67variableDefinition: variable .(/- COLON -/) typedef defaultValue? .(-) 68 69variable: .(/- DOLLAR/) name 70 71defaultValue: .(/- EQUAL -/) value_const 72 73# not "type" as using that for "objectTypeDefinition" 74typedef: nonNullType | namedType | listType 75 76namedType: name .(-) 77 78listType: LSQUARE typedef RSQUARE 79 80nonNullType: namedType /- BANG/ | listType /- BANG/ 81 82directives: directiveactual+ 83 84directiveactual: .(/- AT/) name arguments? 85 86string: blockStringValue | stringValue 87 88stringValue: / 89 DOUBLE 90 ( 91 (: 92 BACK (: # Backslash escapes 93 [ 94 DOUBLE # Double Quote 95 BACK # Back Slash 96 SLASH # Foreward Slash 97 'b' # Back Space 98 'f' # Form Feed 99 'n' # New Line 100 'r' # Carriage Return 101 't' # Horizontal Tab 102 ] 103 | 104 'u' HEX{4} # Unicode octet pair 105 ) 106 | 107 [^ DOUBLE CONTROLS BACK ] # Anything else 108 )* 109 ) 110 DOUBLE 111/ 112 113blockStringValue: / 114 DOUBLE DOUBLE DOUBLE 115 ( 116 (: 117 (: BACK DOUBLE DOUBLE DOUBLE ) | 118 [^ CONTROLS DOUBLE ] | 119 [ TAB NL CR ] | 120 (: DOUBLE (?!"") ) 121 )* 122 ) 123 DOUBLE DOUBLE DOUBLE 124/ 125 126float: /( 127 DASH? 128 (: 0 | [1-9] DIGIT* ) 129 (: 130 # one or other or both. not neither 131 (: DOT DIGIT+ ) (: [eE] [ DASH PLUS ]? DIGIT+ ) | 132 (: DOT DIGIT+ ) | 133 (: [eE] [ DASH PLUS ]? DIGIT+ ) 134 ) 135)/ 136 137int: /( 138 DASH? 139 (: 0 | [1-9] DIGIT* ) 140)/ 141 142name: /([ UNDER ALPHAS ] [ WORDS ]*)/ 143 144spread: /\.{3}/ .(-) 145 146ws: / (: WS | \x{FEFF} | COMMA | comment ) / 147 148comment: / BLANK* HASH BLANK* [^\r\n]* (: EOL | CR !NL | EOS ) / # CR is because MacOS 9 149 150description: .(/ [ WS NL ]* /) string .(/ [ WS NL ]* /) | .(-) 151 152typeSystemDefinition: description? (schema | typeDefinition | typeExtensionDefinition | directive) 153 154schema: .(/'schema' -/) directives? ( .(/- LCURLY -/) operationTypeDefinition+ .(/- RCURLY /) )? 155 156operationTypeDefinition: operationType .(/- COLON -/) namedType .(-) 157 158typeDefinition: scalar | type | interface | union | enumTypeDefinition | input 159 160# aka scalarTypeDefinition 161scalar: .(/'scalar' -/) name .(-) directives? 162 163# aka objectTypeDefinition 164type: .(/'type' -/) name .(-) implementsInterfaces? .(-) directives? ( .(/- LCURLY /) fieldDefinition+ .(/- RCURLY /) )? 165 166implementsInterfaces: .(/'implements' -/) .(/- AMP -/)? (namedType+ % .(/- AMP -/)) 167 168fieldDefinition: description? name .(-) argumentsDefinition? .(/- COLON -/) typedef .(-) directives? 169 170argumentsDefinition: .(/- LPAREN /) inputValueDefinition+ .(/- RPAREN /) 171 172inputValueDefinition: description? name .(/- COLON -/) typedef .(-) defaultValue? .(-) directives? .(-) 173 174interface: .(/'interface' -/) name .(-) directives? ( .(/- LCURLY /) fieldDefinition+ .(/- RCURLY /) )? 175 176union: .(/'union' -/) name .(-) directives? ( .(/- EQUAL -/) unionMembers )? 177 178unionMembers: .(/- PIPE -/)? namedType+ % .(/- PIPE -/) 179 180enumTypeDefinition: .(/'enum' -/) name .(-) directives? ( .(/- LCURLY /) enumValueDefinition+ .(/- RCURLY /) )? 181 182enumValueDefinition: description? enumValue (.(-) directives)? 183 184input: .(/'input' -/) name .(-) directives? ( .(/- LCURLY /) inputValueDefinition+ .(/- RCURLY /) )? 185 186typeExtensionDefinition: .(/'extend' -/) (schema | typeDefinition) 187 188directive: .(/'directive' - AT -/) name .(-) argumentsDefinition? .(/- 'on' -/) directiveLocations 189 190directiveLocations: .(/- PIPE -/)? name+ % .(/- PIPE -/) 191