summaryrefslogtreecommitdiff
path: root/xml/registry.rnc
blob: 34d71d600e354617bd57b88ff42ce82e39141724 (plain)
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
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
# Copyright 2013-2023 The Khronos Group Inc.
# SPDX-License-Identifier: Apache-2.0

# Relax NG schema for Khronos API Registry XML
#
# This definition is subject to change (mostly in the form of additions)

namespace xsd = "http://www.w3.org/2001/XMLSchema-datatypes"

# Toplevel is a <registry> tag.
# May be led by an optional <comment> tag containing e.g. copyrights.
start = element registry {
    (
        element comment { text } ? |
        Platforms         * |
        Tags              * |
        Types             * |
        Enums             * |
        Commands          * |
        Feature           * |
        Extensions        * |
        Formats           * |
        Sync              * |
        SpirvExtensions   * |
        SpirvCapabilities *
    ) *
}

# <platforms> defines a group of platform names
Platforms = element platforms {
    Comment ? ,
    Platform *
}

# <platform> defines a single platform name.
#   name - string name of the platform, used as part of extension names
#   protect - preprocessor symbol to include platform headers from <vulkan.h>
#   comment - platform description
Platform = element platform {
    attribute name { text } ,
    attribute protect { text } ,
    Comment
}

# <tags> defines a group of author tags
Tags = element tags {
    Comment ? ,
    Tag *
}

# <tag> defines a single author tag.
#   name - name of the tag
#   author - name of the author (usually a company or project name)
#   contact - contact responsible for the tag (name and contact information)
Tag = element tag {
    attribute name { text } ,
    attribute author { text } ,
    attribute contact { text }
}

# <types> defines a group of types
Types = element types {
    Comment ? ,
    (
        Type |
        element comment { text }
    ) *
}

# <type> defines a single type. It is usually a C typedef but
# may contain arbitrary C code.
#   name - name of this type, if not present in the <name> tag
#   api - matches a <feature> api attribute, if present
#   alias - name of a type this type aliases
#   requires - name of another type definition required by this one
#   bitvalues - for a *Flags type, name of an enum definition that
#       defines the valid values for parameters of that type
#   category - if present, 'enum' indicates a matching <enums>
#       block to generate an enumerated type for, and 'struct'
#       causes special interpretation of the contents of the type
#       tag including ... TBD ...
#       Other allowed values are 'include', 'define', 'handle' and 'bitmask',
#       which do not change syntactic interpretation but allow organization
#       in the generated header.
#   deprecated - denotes that this type is deprecated, and why.
#       Valid values: 'aliased', 'true'.
#   parent - only applicable if category is 'handle'. Notes another type with
#       the 'handle' category that acts as a parent object for this type.
#   returnedonly - only applicable if category is 'struct'. Notes that this
#       struct is going to be filled in by the API, rather than an application
#       filling it out and passing it to the API.
#   structextends - only applicable if category is 'struct'. Lists parent
#       structures which this structure may extend via the pNext chain
#       of the parent.
#       When present it suppresses generation of automatic validity for the
#       pNext member of that structure, and instead the structure is added
#       to pNext chain validity for the parent structures it extends.
#   allowduplicate - only applicable if category is 'struct'. pNext can include
#       multiple structures of this type.
#   objtypeenum - name of VK_OBJECT_TYPE_* API enumerant which corresponds
#       to this type. Currently only specified for category="handle" types.
#   comment - descriptive text with no semantic meaning
# For types without a category, contents include
#   <apientry /> - substitutes for an APIENTRY-style macro on output
#   <name> - contains name of the type being defined
#   <type> - contains name of types used to define this type. There
#       may be multiple imbedded <type> tags
# For types with category 'enum', contents should be empty
# For types with category 'struct', contents should be one or more
#   <member> - like <param> for a struct or union member
#       len - if the member is an array, len may be one or more of the following
#           things, separated by commas (one for each array indirection):
#           another member of that struct, 'null-terminated' for a string,
#           '1' to indicate it is just a pointer (used for nested pointers),
#           or a latex equation (prefixed with 'latexmath:')
#       altlen - if len has latexmath equations, this contains equivalent C99
#                expressions separated by commas.
#       deprecated - denotes that this member is deprecated, and why.
#           Valid values: 'ignored', 'true'.
#       externsync - denotes that the member should be externally synchronized
#           when accessed by Vulkan
#       optional - whether this value can be omitted by providing NULL (for
#           pointers), VK_NULL_HANDLE (for handles) or 0 (for bitmasks/values)
#       selector - for a union member, identifies a separate enum member that
#           selects which of the union's members are valid
#       selection - for a member of a union, identifies an enum value indicating the member is valid
#       noautovalidity - tag stating that no automatic validity language should be generated
#       values - comma-separated list of legal values, usually used only for sType enums
#       limittype - only applicable for members of VkPhysicalDeviceProperties and
#           VkPhysicalDeviceProperties2, their substructures, and extensions.
#           Specifies the type of a device limit.
#           Valid values: 'min', 'max', 'not', 'pot', 'mul', 'bits', bitmask', 'range', 'struct', 'exact', 'noauto'
#       objecttype - only applicable for members representing a handle as
#           a uint64_t value. Specifies the name of another member which is
#           a VkObjectType or VkDebugReportObjectTypeEXT value specifying
#           the type of object the handle references.
#   <comment> - containing arbitrary text (unused)
#
# *** There is a problem here: I am not sure how to represent the <type>
# syntax where it may contain arbitrarily interleaved text, <type>, and
# <enum> child tags. This allows only the syntax
#   text <type>name</type> text <enum>name</enum> text
# where <type> and <enum> are both optional and occur in the specified
# order, which might eventually be a problem.
Type = element type {
    attribute api { text } ? ,
    attribute alias { text } ? ,
    attribute requires { text } ? ,
    attribute bitvalues { text } ? ,
    attribute name { TypeName } ? ,
    attribute category { text } ? ,
    attribute deprecated { text } ? ,
    attribute parent { TypeName } ? ,
    attribute returnedonly { text } ? ,
    attribute structextends { text } ? ,
    attribute allowduplicate { text } ? ,
    attribute objtypeenum { text } ? ,
    Comment ? ,
    (
        (
            ( text ,
              element type { text } *
            ) * ,
            element apientry { text } ? ,
            ( text ,
              element type { text } *
            ) * ,
            element name { TypeName } ? ,
            ( text ,
              element type { text } *
            ) *
        ) |
        (
            element member {
                attribute api { text } ? ,
                attribute len { text } ? ,
                attribute altlen { text } ? ,
                attribute externsync { text } ? ,
                attribute optional { text } ? ,
                attribute selector { text } ? ,
                attribute selection { EnumName } ? ,
                attribute noautovalidity { text } ? ,
                attribute values { text } ? ,
                attribute limittype { text } ? ,
                attribute objecttype { text } ? ,
                attribute deprecated { text } ? ,
                mixed {
                    element type { TypeName } ? ,
                    element name { text } ? ,
                    element enum { EnumName } ? ,
                    element comment { text } ?
                } +
            } |
            element comment { text }
        ) *
    )
}

# <enums> defines a group of enumerants
#   name - identifies a type name associated with this group. Should
#       match a <type> name to trigger generation of the type.
#   type - 'enum' or 'bitmask', if present
#   bitwidth - bit width of the enum value type.
#   comment - descriptive text with no semantic meaning
Enums = element enums {
    attribute name { text } ? ,
    attribute type { text } ? ,
    attribute bitwidth { Integer } ? ,
    Comment ? ,
    (
        Enum |
        Unused |
        element comment { text}
    ) *
}

# <enum> defines or references a single enumerant. There are two places it
# can be used: in an <enums> block, providing a global definition which
# may later be required by a feature or extension; or in a feature or
# extension, defining an enumerant specific to that feature. The second
# form has more possible attributes. Some combinations of attributes are
# nonsensical in on or the other place, but these are not detected by the
# validator.
#
# Ways to specify the enumerant value:
#   value - integer (including hex) value of the enumerant
#   bitpos - integer bit position of the enumerant in a bitmask
#   [extnumber], offset, [dir] - integer extension number specifying a
#       base block value (inherited from surrounding <extension> if
#       not specified); integer offset in that block; and direction
#       of offset ('-' for negative, positive if not specified).
#   alias - name of another enum this is an alias of
#
# value and bitpos allow, and extnumber/offset/dir require:
#   extends - type name of the enumerant being extended
#
# Other attributes:
#   api - matches a <feature> api attribute, if present
#   type - 'uint32_t', 'uint64_t', or 'float', if present. There are
#       certain conditions under which the tag must be present, or absent,
#       but they are context-dependent and difficult to express in the
#       RNC syntax.
#   name - enumerant name
#   alias - another enumerant this is semantically identical to
#   protect - additional #ifdef symbol to place around the enum
#   comment - descriptive text with no semantic meaning
#   deprecated - denotes that this enum is deprecated, and why.
#       Valid values: 'aliased', 'ignored', 'true'.
Enum = element enum {
    (
      (
        (
          attribute value { Integer } &
          attribute extends { TypeName } ?
        ) |
        (
          attribute bitpos { Integer } &
          attribute extends { TypeName } ?
        ) |
        (
          attribute extnumber { Integer } ? &
          attribute offset { Integer } &
          attribute dir { text } ? &
          attribute extends { TypeName }
        ) |
        (
          attribute extends { TypeName } ? &
          attribute alias { TypeName }
        )
      ) ? &
      attribute protect { text } ? &
      attribute api { text } ? &
      attribute type { TypeSuffix } ? &
      attribute name { text } &
      attribute deprecated { text } ? &
      Comment ?
    )
}

# <unused> defines a range of enumerants not currently being used
#   start, end - beginning and end of an unused numeric range
#   vendor - unused
#   comment - descriptive text with no semantic meaning
Unused = element unused {
    attribute start { Integer } ,
    attribute end { Integer } ? ,
    Vendor ? ,
    Comment ?
}

# <commands> defines a group of commands
Commands = element commands {
    Comment ? ,
    Command *
}

# <command> defines a single command
#
# There are two forms of the tag.
#
# Either form may have an 'api' attribute
#   api - matches a <feature> api attribute, if present
#
# The first form only has 'name' and 'alias' attributes, and no contents.
# It defines a command alias.
#
# The second form fully defines a command, and has the following structure:
# The possible attributes are not described in this comment block yet, but
# are in registry.html. The "prefix" and "suffix" attributes are currently
# present only in the OpenCL XML registry, where they are currently unused.
#
#   <proto> is the C function prototype, including the return type
#   <param> are function parameters, in order
#     len - if the member is an array, len may be one or more of the following
#           things, separated by commas (one for each array indirection):
#           another member of that struct, 'null-terminated' for a string,
#           '1' to indicate it is just a pointer (used for nested pointers),
#           or a latex equation (prefixed with 'latexmath:')
#     altlen - if len has latexmath equations, this contains equivalent C99
#              expressions separated by commas.
#     externsync - denotes that the member should be externally synchronized
#         when accessed by Vulkan
#     optional - whether this value can be omitted by providing NULL (for
#         pointers), VK_NULL_HANDLE (for handles) or 0 (for bitmasks/values)
#     selector - for a union parameter, identifies a separate enum parameter that
#         selects which of the union's members are valid
#     noautovalidity - tag stating that no automatic validity language should be
#         generated
#     objecttype - only applicable for parameters representing a handle as
#         a uint64_t value. Specifies the name of another parameter which is
#         a VkObjectType or VkDebugReportObjectTypeEXT value specifying
#         the type of object the handle references.
#     validstructs - only applicable for parameters which are pointers to
#         VkBaseInStructure or VkBaseOutStructure types, used as abstract
#         placeholders. Specifies a comma-separated list of structures which
#         may be passed in place of the parameter, or anywhere in the pNext
#         chain of the parameter.
#     stride - if the member is an array, stride specifies the name of
#         another member containing the byte stride between consecutive
#         elements in the array. Is assumed tightly packed if omitted.
#     <type> is a <type> name, if present
#     <name> is the function / parameter name, if present (normally should
#         be, except for void parameters).
# The textual contents of <proto> and <param> should be legal C
# for those parts of a function declaration.
#   <alias> - denotes function aliasing, if present
#     name - name of aliased function
#   <description> - unused text
#   <implicitexternsyncparams> are spec-language descriptions of
#       objects that are not parameters of the command, but
#       are related to them and also require external synchronization.
Command = element command {
    (   attribute name { text } ,
        attribute alias { text } ,
        attribute api { text } ?
        ) |
    (
        attribute tasks { text } ? ,
        attribute queues { text } ? ,
        attribute successcodes { text } ? ,
        attribute errorcodes { text } ? ,
        attribute renderpass { text } ? ,
        attribute videocoding { text } ? ,
        attribute cmdbufferlevel { text } ? ,
        attribute prefix { text } ? ,
        attribute suffix { text } ? ,
        attribute api { text } ? ,
        Comment ? ,
        element proto {
            mixed {
                element type { TypeName } ? ,
                element name { text }
            }
        } ,
        element param {
            attribute api { text } ? ,
            attribute len { text } ? ,
            attribute altlen { text } ? ,
            attribute externsync { text } ? ,
            attribute optional { text } ? ,
            attribute selector { text } ? ,
            attribute noautovalidity { text } ? ,
            attribute objecttype { text } ? ,
            attribute validstructs { text } ? ,
            attribute stride { text } ? ,
            mixed {
                element type { TypeName } ? ,
                element name { text } ?
            }
        } * ,
        (
            element alias {
                Name
            } ? &
            element description {
                text
            } ? &
            element implicitexternsyncparams {
                element param { text } *
            } ?
        )
    )
}

# Each <feature> defines the interface of an API version (e.g. OpenGL 1.2)
#   api - API tag (e.g. 'gl', 'gles2', etc. - used internally, not
#     necessarily an actual API name
#   name - version name (C preprocessor name, e.g. GL_VERSION_4_2)
#   number - version number, e.g. 4.2
#   protect - additional #ifdef symbol to place around the feature
#   sortorder - order relative to other features, default 0
#   <require> / <remove> contains features to require or remove in
#                        this version
#     profile - only require/remove when generated profile matches
#     comment - descriptive text with no semantic meaning
Feature = element feature {
    attribute api { text } ,
    Name ,
    attribute number { xsd:float } ,
    attribute protect { text } ? ,
    attribute sortorder { xsd:integer } ?,
    Comment ? ,
    (
        element require {
            ProfileName ? ,
            Depends ? ,
            Comment ? ,
            (
                InterfaceElement |
                element comment { text }
            ) *
        } |
        element remove {
            ProfileName ? ,
            Comment ? ,
            (
                InterfaceElement |
                element comment { text }
            ) *
        }
    ) *
}

Extensions = element extensions {
    Comment ? ,
    Extension *
}

# Each <extension> defines the interface of an API <extension>.
# Like a <feature> tag, but with slightly different attributes:
#   api - regexp pattern matching one or more API tags, indicating
#     which APIs the extension is known to work with. The only
#     syntax supported is <name>{|<name>}* and each name must
#     exactly match an API being generated (implicit ^$ surrounding).
#   name - extension name string
#   number - extension number (positive integer, should be unique)
#   sortorder - order relative to other extensions, default 0
#   protect - C preprocessor symbol to conditionally define the interface
#   platform - should be one of the platform names defined in the
#     <platform> tag. Currently unused.
#   author - name of the author (usually a company or project name)
#   contact - contact responsible for the tag (name and contact information)
#   type - 'device' or 'instance', if present
#   depends - boolean expression of API and/or extension names
#       upon which this extension depends.
#   supported - comma-separated list of API name(s) supporting this extension,
#       e.g. 'vulkan', or 'disabled' to never generate output.
#   ratified - comma-separated list of API name(s) for which this extension
#       has been ratified by Khronos. Defaults to "" if not specified.
#   promotedto - API version or a name of an extension that this
#       extension was promoted to; e.g. 'VK_VERSION_1_1', or
#       'VK_KHR_draw_indirect_county'
#   deprecatedby - API version or a name of an extension that deprecates
#       this extension. It may be an empty string.
#       e.g. 'VK_VERSION_1_1', or 'VK_EXT_debug_utils', or ''
#   obsoletedby - Vulkan version or a name of an extension that obsoletes
#       this extension. It may be an empty string.
#       e.g. 'VK_VERSION_1_1', or 'VK_EXT_debug_utils', or ''
#   provisional - 'true' if this extension is released provisionally
#   specialuse - contains one or more tokens separated by commas, indicating
#       a special purpose of the extension. Tokens may include 'cadsupport',
#       'd3demulation', 'devtools', 'debugging', and 'glemulation'. Others
#       may be added in the future.
# In addition, <require> / <remove> tags also support an api attribute:
#     api - only require/remove these features for the matching API.
#       Not a regular expression.
Extension = element extension {
    Name ,
    attribute number { Integer } ? ,
    attribute sortorder { xsd:integer } ?,
    attribute protect { text } ? ,
    attribute platform { text } ? ,
    attribute author { text } ? ,
    attribute contact { text } ? ,
    attribute type { text } ? ,
    attribute depends { text } ?,
    attribute supported { StringGroup } ? ,
    attribute ratified { text } ? ,
    attribute promotedto { text } ? ,
    attribute deprecatedby { text } ? ,
    attribute obsoletedby { text } ? ,
    attribute provisional { text } ? ,
    attribute specialuse { text } ? ,
    Comment ? ,
    (
        element require {
            attribute api { text } ? ,
            ProfileName ? ,
            Depends ? ,
            Comment ? ,
            (
                InterfaceElement |
                element comment { text }
            ) *
        } |
        element remove {
            attribute api { text } ? ,
            ProfileName ? ,
            Comment ? ,
            (
                InterfaceElement |
                element comment { text }
            ) *
        }
    ) *
}

# Each <format> define information about a VkFormat in a machine readable format
Formats = element formats {
    Format *
}

#    name - Format name, matching a VkFormat enum name
#    class - Used for 'Compatible Formats' table
#    blockSize - Used for 'Compatible Formats' table
#    texelsPerBlock - Used for 'Compatible Formats' table
#    blockExtent - 3D extent, no attribute is same as blockExtent=1,1,1
#    packed - number of bits data type
#    compressed - compression format class
#    planes - number of planes, no attribute is same as planes=1
#    chroma - can be one of [420, 422, 444] and used to mark if YCbCr Sampler are required by default
Format = element format {
    Name ,
    attribute class { text } ,
    attribute blockSize { text } ,
    attribute texelsPerBlock { text } ,
    attribute blockExtent { text } ? ,
    attribute packed { text } ? ,
    attribute compressed { text } ? ,
    attribute chroma { text } ? ,
    Component + ,
    Plane * ,
    SpirvImageFormat *
}

#   bits - size of component or "compressed" if part of block-compression format
#   numericFormat - as per Interpretation of Numeric Format table
#       some formats (depth/stencil) will have different numeric per component
#   planeIndex - For multi-planar formats to map to the plane element
Component = element component {
    Name ,
    attribute bits { text } ,
    attribute numericFormat { text },
    attribute planeIndex { text } ?
}

# For multi-planar formats
Plane = element plane {
    attribute index { text } ,
    attribute widthDivisor { text } ,
    attribute heightDivisor { text } ,
    attribute compatible { text }
}

# labels a SPIR-V Image Format
SpirvImageFormat = element spirvimageformat {
    Name
}

# <sync> is a set of all sync objects
Sync = element sync {
    Comment ? ,
    SyncStage *,
    SyncAccess *,
    SyncPipeline *
}

SyncSupport = element syncsupport {
    attribute queues { text } ? ,
    attribute stage { text } ?
}

SyncEquivalent = element syncequivalent {
    attribute stage { text } ?,
    attribute access { text } ?
}

# describes all Pipeline Stages
SyncStage = element syncstage {
    Name ,
    attribute alias { text } ? ,
    SyncSupport ? ,
    SyncEquivalent ?
}

# describes all Access Flags
SyncAccess = element syncaccess {
    element comment { text } ?,
    Name ,
    attribute alias { text } ? ,
    SyncSupport ? ,
    SyncEquivalent ?
}

SyncPipelineStage = element syncpipelinestage {
    attribute order { text } ? ,
    attribute before { text } ? ,
    attribute after { text } ?,
    text
}

# describes pipelines
SyncPipeline = element syncpipeline {
    Name ,
    attribute depends { text } ? ,
    SyncPipelineStage *
}

# Each <spirvextension> define a SPIR-V extension that can be used in the API.
# Each <spirvcapability> define a SPIR-V capability that can be used in the API.
# Contains information to both generate table in spec as well as validating
# what needs to be enabled or supported to be used in Vulkan
SpirvExtensions = element spirvextensions {
    Comment ? ,
    SpirvExtension *
}

SpirvExtension = element spirvextension {
    Name ,
    Enable +
}

SpirvCapabilities = element spirvcapabilities {
    Comment ? ,
    SpirvCapability *
}

SpirvCapability = element spirvcapability {
    Name ,
    Enable +
}

# <enable> defines a way to enable the parent element in the API.
# If anyone of the <enable> elements are valid then the parent element
# can be used.
#
# There are four forms of the tag.
#
# The first only has the minimal version of Vulkan of the application
#
# The second only has a single Vulkan extension that must be enabled
#
# The third has a single Vulkan feature with the struct where it is from
#
# The fourth has a property struct, the member field in it, and the value
# that must be present
#
# To make scripting easier, each <enable> has a require attribute to map
# to the asciidoctor conditional logic in the spec. For version and
# extension attribute variations, there is no need for the require attribute
# since it is a redundant 1:1 mapping.
#
# The 'alias' attribute is used in cases where the anchor link cannot be
# properly resolved and needs a manual name to link to
Enable = element enable {
    (
        attribute version { text } ) |
    (
        attribute extension { text } ) |
    (
        attribute struct { text },
        attribute feature { text },
        attribute requires { text },
        attribute alias { text } ? ) |
    (
        attribute property { text },
        attribute member { text },
        attribute value { text },
        attribute requires { text } ? )
}

# Contents of a <require> / <remove> tag, defining a group
# of features to require or remove.
#   <type> / <enum> / <command> all have attributes
#     name - feature name which must match
InterfaceElement =
    element type {
        Name ,
        Comment ?
    } |
    Enum |
    element command {
        Name ,
        Comment ?
    }

# Integers are allowed to be either decimal or C-hex (0x[0-9A-F]+), but
# XML Schema types do not seem to support hex notation, so we use this
# as a placeholder.
Integer = text

# EnumName is an compile-time constant name
EnumName = text

# TypeName is an argument/return value C type name
TypeName = text

# TypeSuffix is a C numeric type suffix, e.g. 'u' or 'ull'
TypeSuffix = text

# StringGroup is a regular expression with an implicit
#   '^(' and ')$' bracketing it.
StringGroup = text

# Repeatedly used attributes
ProfileName = attribute profile { text }
ExtensionName = attribute extension { text }
# Boolean expression of core version and extension names using (),+ operators
Depends = attribute depends { text }
Vendor = attribute vendor { text }
Comment = attribute comment { text }
Name = attribute name { text }