This is the grammar for FIDL source files. The grammar is expressed in a modified BNF format.
A nonterminal symbol matches a sequence of other symbols, delimited by commas.
nonterminal = list , of , symbols ;
Some symbols are terminals, which are either in all caps or are in double quotes.
another-nonterminal = THESE , ARE , TERMINALS , AND , SO , IS , "this" ;
Alternation is expressed with a pipe.
choice = this | that | the-other ;
An option (zero or one) is expressed with parentheses.
optional = ( maybe , these ) , but , definitely , these ;
Repetition (zero or more) is expressed with parentheses and a star.
zero-or-more = ( list-part )* ;
Repetition (one or more) is expressed with parentheses and a plus.
one-or-more = ( list-part )+ ;
Whitespace and comments are ignored during lexing, and thus not present in the following grammar.
Comments can start with two slashes (‘//’) or three slashes (‘///’), or they can be embodied within a [Doc]
attribute. The three-slash variant and the [Doc]
attribute behave the same way, propagating the comments to the generated target.
The fidldoc tool processes comments propagated into the JSON-based Intermediate Representation (IR) to generate reference documentation pages for FIDL files.
See the FIDL style guide for more details on comments.
file
is the starting symbol.
{% dynamic if request.query_string.syntax == “old” %}
file = "deprecated_syntax" , ";" , library-header , ( using-list ) , declaration-list ; library-header = ( attribute-list ) , "library" , compound-identifier , ";" ; using-list = ( using , ";" )* ; using = "using" , compound-identifier , ( "as" , IDENTIFIER ) ; declaration-list = ( declaration , ";" )* ; compound-identifier = IDENTIFIER ( "." , IDENTIFIER )* ; declaration = bits-declaration | const-declaration | enum-declaration | protocol-declaration | struct-declaration | table-declaration | union-declaration | type-alias-declaration | resource-declaration | service-declaration ; declaration-modifiers = "flexible" | "strict" | "resource"; [NOTE 1] const-declaration = ( attribute-list ) , "const" , type-constructor , IDENTIFIER , "=" , constant ; enum-declaration = ( attribute-list ) , ( declaration-modifiers )* , "enum" , IDENTIFIER , ( ":" , type-constructor ) , "{" , ( bits-or-enum-member , ";" )+ , "}" ; [NOTE 2] bits-declaration = ( attribute-list ) , ( declaration-modifiers )* , "bits" , IDENTIFIER , ( ":" , type-constructor ) , "{" , ( bits-or-enum-member , ";" )+ , "}" ; [NOTE 3] bits-or-enum-member = ( attribute-list ) , IDENTIFIER , "=" , bits-or-enum-member-value ; bits-or-enum-member-value = IDENTIFIER | literal ; [NOTE 4] protocol-declaration = ( attribute-list ) , "protocol" , IDENTIFIER , "{" , ( protocol-member , ";" )* , "}" ; protocol-member = protocol-method | protocol-event | protocol-compose ; protocol-method = ( attribute-list ) , IDENTIFIER , parameter-list, ( "->" , parameter-list , ( "error" type-constructor ) ) ; [NOTE 5] protocol-event = ( attribute-list ) , "->" , IDENTIFIER , parameter-list ; parameter-list = "(" , ( parameter ( "," , parameter )+ ) , ")" ; parameter = ( attribute-list ) , type-constructor , IDENTIFIER ; protocol-compose = "compose" , compound-identifier ; struct-declaration = ( attribute-list ) , "struct" , IDENTIFIER , "{" , ( member-field , ";" )* , "}" ; union-declaration = ( attribute-list ) , ( declaration-modifiers )* , "union" , IDENTIFIER , "{" , ( ordinal-member-field , ";" )+ , "}" ; table-declaration = ( attribute-list ) , ( declaration-modifiers )* , "table" , IDENTIFIER , "{" , ( ordinal-member-field , ";" )* , "}" ; member-field = ( attribute-list ) , type-constructor , IDENTIFIER , ( "=" , constant ) ; ordinal-member-field = ( attribute-list ) , ordinal , ":" , ordinal-member-field-body ; [NOTE 6] ordinal-member-field-body = member-field | "reserved"; type-alias-declaration = ( attribute-list ) , "alias" , IDENTIFIER , "=" , type-constructor ; resource-declaration = ( attribute-list ) , "resource_definition" , IDENTIFIER , ":", "uint32" , "{" , resource-properties , "}" ; resource-properties = "properties" , "{" , ( type-constructor , IDENTIFIER , ";" )* , "}" , ";" service-declaration = ( attribute-list ) , "service" , IDENTIFIER , "{" , ( service-member , ";" )* , "}" ; service-member = ( attribute-list ) , type-constructor , IDENTIFIER ; [NOTE 7] attribute-list = "[" , attributes , "]" ; attributes = attribute | attribute , "," , attributes ; attribute = IDENTIFIER , ( "=" , STRING-LITERAL ) ; type-constructor = compound-identifier ( "<" type-constructor ">" ) , ( type-constraint ) , ( "?" ) | handle-type ; handle-type = "handle" , ( "<" , handle-subtype , ">" ) , ( "?" ) ; handle-subtype = "bti" | "channel" | "clock" | "debuglog" | "event" | "eventpair" | "exception" | "fifo" | "guest" | "interrupt" | "iommu" | "job" | "pager" | "pcidevice" | "pmt" | "port" | "process" | "profile" | "resource" | "socket" | "suspendtoken" | "thread" | "timer" | "vcpu" | "vmar" | "vmo" ; type-constraint = ":" , constant ; constant = compound-identifier | literal ; ordinal = NUMERIC-LITERAL ; literal = STRING-LITERAL | NUMERIC-LITERAL | "true" | "false" ;
The grammar allows ( declaration-modifiers )*
on all declarations, but the compiler limits this as follows:
flexible
and strict
modifiers cannot be used together.flexible
and strict
modifiers can only be used on bits
, enum
, and union
.resource
modifier can only be used on struct
, table
, and union
.The enum-declaration
allows the more liberal type-constructor
in the grammar, but the compiler limits this to signed or unsigned integer types, see primitives.
The bits-declaration
allows the more liberal type-constructor
in the grammar, but the compiler limits this to unsigned integer types, see primitives.
The bits-or-enum-member-value
allows the more liberal literal
in the grammar, but the compiler limits this to:
NUMERIC-LITERAL
in the context of an enum
;NUMERIC-LITERAL
, which must be a power of two, in the context of a bits
.The protocol-method
error stanza allows the more liberal type-constructor
in the grammar, but the compiler limits this to an int32
, uint32
, or an enum thereof.
Attributes cannot be placed on a reserved member.
The service-member
allows the more liberal type-constructor
in the grammar, but the compiler limits this to protocols.
{% dynamic endif %}
{% dynamic if request.query_string.syntax == “new” %}
file = library-header , ( using-list ) , declaration-list ; library-header = ( attribute-list ) , "library" , compound-identifier , ";" ; using-list = ( using , ";" )* ; using = "using" , compound-identifier , ( "as" , IDENTIFIER ) ; compound-identifier = IDENTIFIER ( "." , IDENTIFIER )* ; declaration-list = ( declaration , ";" )* ; declaration = const-declaration | layout-declaration | protocol-declaration | type-alias-declaration | resource-declaration | service-declaration ; const-declaration = ( attribute-list ) , "const" , IDENTIFIER , type-constructor , "=" , constant ; layout-declaration = ( attribute-list ) , "type" , IDENTIFIER , "=" , inline-layout ; [NOTE 1] inline-layout = ( attribute-list ) , ( declaration-modifiers )* , layout-kind , ( subtype ) , layout-body ; declaration-modifiers = "flexible" | "strict" | "resource" ; [NOTE 2] subtype = ":" , type-constructor ; [NOTE 3] layout-kind = "struct" | "bits" | "enum" | "union" | "table" ; layout-body = value-layout | struct-layout | ordinal-layout ; value-layout = "{" , ( value-layout-member , ";" )+ , "}" ; value-layout-member = ( attribute-list ) , IDENTIFIER , "=" , value-layout-member-value ; value-layout-member-value = IDENTIFIER | literal ; [NOTE 4] struct-layout = "{" , ( struct-layout-member, ";" )* , "}" ; struct-layout-member = ( attribute-list ) , member-field , ( "=" , constant ) ; ordinal-layout = "{" , ( ordinal-layout-member , ";" )* , "}" ; [NOTE 5] ordinal-layout-member = ( attribute-list ) , ordinal , ":" , ordinal-layout-member-body ; [NOTE 6] ordinal-layout-member-body = member-field | "reserved" ; protocol-declaration = ( attribute-list ) , "protocol" , IDENTIFIER , "{" , ( protocol-member , ";" )* , "}" ; protocol-member = protocol-method | protocol-event | protocol-compose ; protocol-method = ( attribute-list ) , IDENTIFIER , parameter-list, ( "->" , parameter-list , ( "error" type-constructor ) ) ; [NOTE 7] protocol-event = ( attribute-list ) , "->" , IDENTIFIER , parameter-list ; parameter-list = "(" , ( type-constructor ) , ")" ; [NOTE 8] protocol-compose = "compose" , compound-identifier ; type-alias-declaration = ( attribute-list ) , "alias" , IDENTIFIER , "=" , type-constructor ; resource-declaration = ( attribute-list ) , "resource_definition" , IDENTIFIER , ":", "uint32" , "{" , resource-properties , "}" ; resource-properties = "properties" , "{" , ( member-field , ";" )* , "}" , ";" service-declaration = ( attribute-list ) , "service" , IDENTIFIER , "{" , ( service-member , ";" )* , "}" ; service-member = ( attribute-list ) , member-field ; [NOTE 9] member-field = IDENTIFIER , type-constructor ; attribute-list = attribute | attribute , "," , attribute-list ; attribute = "@", IDENTIFIER , ( "(" , constant | attribute-args, ")" ) ; attribute-args = attribute-arg | attribute-arg, "," attribute-args ; attribute-arg = IDENTIFIER , "=" , constant ; type-constructor = layout , ( "<" , layout-parameters , ">" ) , ( ":" type-constraints ) ; layout = compound-identifier | inline-layout ; layout-parameters = layout-parameter | layout-parameter , "," , layout-parameters ; layout-parameter = type-constructor | constant ; type-constraints = type-constraint | "<" type-constraint-list ">" ; type-constraint-list = type-constraint | type-constraint , "," , type-constraint-list ; type-constraint = constant ; constant = compound-identifier | literal ; ordinal = NUMERIC-LITERAL ; literal = STRING-LITERAL | NUMERIC-LITERAL | "true" | "false" ;
Attributes for an anonymous layout introduction can be placed in one of two locations:
type
keyword, orinline-layout
.Placing attributes in both locations for a single layout definition is not allowed by the compiler.
The grammar allows ( declaration-modifiers )*
on all declarations, but the compiler limits this as follows:
flexible
and strict
modifiers cannot be used together.flexible
and strict
modifiers can only be used when the layout-kind
is bits
, enum
, or union
.resource
modifier can only be when the layout-kind
is struct
, table
, or union
.The grammar allows ( subtype )
on all declarations, but the compiler limits this to only be allowed when the layout-kind
is bits
or enum
.
Further, subtype
allows the more liberal type-constructor
in the grammar, but the compiler limits this to signed or unsigned integer types (see primitives) for enums and unsigned integer types for bits.
The value-layout-member-value
allows the more liberal literal
in the grammar, but the compiler limits this to:
NUMERIC-LITERAL
in the context of an enum
;NUMERIC-LITERAL
, which must be a power of two, in the context of a bits
.The ordinal-layout
grammar allows any number of members, but unions specifically must at least one non-reserved member.
Attributes cannot be placed on a reserved member.
Also, though ordinals can be any numeric literal, the compiler enforces that the specified ordinals for any union or table cover a contiguous range starting from 1.
The protocol-method
error stanza allows the more liberal type-constructor
in the grammar, but the compiler limits this to an int32
, uint32
, or an enum thereof.
The parameter-list
allows the more liberal type-constructor
in the grammar, but the compiler only supports layouts that are non-empty structs.
The service-member
allows the more liberal type-constructor
in the grammar, but the compiler limits this to protocols.
{% dynamic endif %}