1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
|
# -*- coding: utf-8 -*- #
# frozen_string_literal: true
module Rouge
module Lexers
class GraphQL < RegexLexer
desc 'GraphQL'
tag 'graphql'
filenames '*.graphql', '*.gql'
mimetypes 'application/graphql'
name = /[_A-Za-z][_0-9A-Za-z]*/
state :root do
rule %r/\b(?:query|mutation|subscription)\b/, Keyword, :query_definition
rule %r/\{/ do
token Punctuation
push :query_definition
push :selection_set
end
rule %r/\bfragment\b/, Keyword, :fragment_definition
rule %r/\bscalar\b/, Keyword, :value
rule %r/\b(?:type|interface|enum)\b/, Keyword, :type_definition
rule %r/\b(?:input|schema)\b/, Keyword, :type_definition
rule %r/\bunion\b/, Keyword, :union_definition
rule %r/\bextend\b/, Keyword
mixin :basic
# Markdown descriptions
rule %r/(""")(\n)(.*?)(\n)(""")/m do |m|
token Str::Double, m[1]
token Text::Whitespace, m[2]
delegate Markdown, m[3]
token Text::Whitespace, m[4]
token Str::Double, m[5]
end
end
state :basic do
rule %r/\s+/m, Text::Whitespace
rule %r/#.*$/, Comment
rule %r/[!,]/, Punctuation
end
state :has_directives do
rule %r/(@#{name})(\s*)(\()/ do
groups Keyword, Text::Whitespace, Punctuation
push :arguments
end
rule %r/@#{name}\b/, Keyword
end
state :fragment_definition do
rule %r/\bon\b/, Keyword
mixin :query_definition
end
state :query_definition do
mixin :has_directives
rule %r/\b#{name}\b/, Name
rule %r/\(/, Punctuation, :variable_definitions
rule %r/\{/, Punctuation, :selection_set
mixin :basic
end
state :type_definition do
rule %r/\bimplements\b/, Keyword
rule %r/\b#{name}\b/, Name
rule %r/\(/, Punctuation, :variable_definitions
rule %r/\{/, Punctuation, :type_definition_set
mixin :basic
end
state :union_definition do
rule %r/\b#{name}\b/, Name
rule %r/\=/, Punctuation, :union_definition_variant
mixin :basic
end
state :union_definition_variant do
rule %r/\b#{name}\b/ do
token Name
pop!
push :union_definition_pipe
end
mixin :basic
end
state :union_definition_pipe do
rule %r/\|/ do
token Punctuation
pop!
push :union_definition_variant
end
rule %r/(?!\||\s+|#[^\n]*)/ do
pop! 2
end
mixin :basic
end
state :type_definition_set do
rule %r/\}/ do
token Punctuation
pop! 2
end
rule %r/\b(#{name})(\s*)(\()/ do
groups Name, Text::Whitespace, Punctuation
push :variable_definitions
end
rule %r/\b#{name}\b/, Name
rule %r/:/, Punctuation, :type_names
mixin :basic
end
state :arguments do
rule %r/\)/ do
token Punctuation
pop!
end
rule %r/\b#{name}\b/, Name
rule %r/:/, Punctuation, :value
mixin :basic
end
state :variable_definitions do
rule %r/\)/ do
token Punctuation
pop!
end
rule %r/\$#{name}\b/, Name::Variable
rule %r/\b#{name}\b/, Name
rule %r/:/, Punctuation, :type_names
rule %r/\=/, Punctuation, :value
mixin :basic
end
state :type_names do
rule %r/\b(?:Int|Float|String|Boolean|ID)\b/, Name::Builtin, :pop!
rule %r/\b#{name}\b/, Name, :pop!
rule %r/\[/, Punctuation, :type_name_list
mixin :basic
end
state :type_name_list do
rule %r/\b(?:Int|Float|String|Boolean|ID)\b/, Name::Builtin
rule %r/\b#{name}\b/, Name
rule %r/\]/ do
token Punctuation
pop! 2
end
mixin :basic
end
state :selection_set do
mixin :has_directives
rule %r/\}/ do
token Punctuation
pop!
pop! if state?(:query_definition) || state?(:fragment_definition)
end
rule %r/\b(#{name})(\s*)(\()/ do
groups Name, Text::Whitespace, Punctuation
push :arguments
end
rule %r/\b(#{name})(\s*)(:)/ do
groups Name, Text::Whitespace, Punctuation
end
rule %r/\b#{name}\b/, Name
rule %r/(\.\.\.)(\s+)(on)\b/ do
groups Punctuation, Text::Whitespace, Keyword
end
rule %r/\.\.\./, Punctuation
rule %r/\{/, Punctuation, :selection_set
mixin :basic
end
state :list do
rule %r/\]/ do
token Punctuation
pop!
pop! if state?(:value)
end
mixin :value
end
state :object do
rule %r/\}/ do
token Punctuation
pop!
pop! if state?(:value)
end
rule %r/\b(#{name})(\s*)(:)/ do
groups Name, Text::Whitespace, Punctuation
push :value
end
mixin :basic
end
state :value do
pop_unless_list = ->(t) {
->(m) {
token t
pop! unless state?(:list)
}
}
# Multiline strings
rule %r/""".*?"""/m, Str::Double
rule %r/\$#{name}\b/, &pop_unless_list[Name::Variable]
rule %r/\b(?:true|false|null)\b/, &pop_unless_list[Keyword::Constant]
rule %r/[+-]?[0-9]+\.[0-9]+(?:[eE][+-]?[0-9]+)?/, &pop_unless_list[Num::Float]
rule %r/[+-]?[1-9][0-9]*(?:[eE][+-]?[0-9]+)?/, &pop_unless_list[Num::Integer]
rule %r/"(\\[\\"]|[^"])*"/, &pop_unless_list[Str::Double]
rule %r/\b#{name}\b/, &pop_unless_list[Name]
rule %r/\{/, Punctuation, :object
rule %r/\[/, Punctuation, :list
mixin :basic
end
end
end
end
|