Modified BNF rules
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 )+ ;
Tokens
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.
Grammar
file is the starting symbol.
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 ,
( layout-subtype ) , layout-body ;
declaration-modifiers = "flexible" | "strict" | "resource",
( modifier-availability ) ; [NOTE 2]
layout-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 , "=" ,
constant ; [NOTE 4]
struct-layout = "{" , ( struct-layout-member , ";" )* , "}" ;
struct-layout-member = ( attribute-list ) , member-field , ( '=' , constant ) ; [NOTE 10]
ordinal-layout = "{" , ( ordinal-layout-member , ";" )* , "}" ; [NOTE 5]
ordinal-layout-member = ( attribute-list ) , ordinal , ":" ,
member-field ;
protocol-declaration = ( attribute-list ) , ( protocol-modifiers )* ,
"protocol" , IDENTIFIER , "{" , ( protocol-member , ";" )* , "}" ;
protocol-modifiers = "closed" | "ajar" | "closed" , ( modifier-availability ) ;
protocol-member = protocol-method | protocol-event | protocol-compose ;
protocol-method = ( attribute-list ) , ( method-modifiers )* , IDENTIFIER ,
parameter-list , ( "->" , parameter-list ,
( "error" type-constructor ) ) ; [NOTE 6]
protocol-event = ( attribute-list ) , ( method-modifiers )* , "->" ,
IDENTIFIER , parameter-list ;
method-modifiers = "strict" | "flexible" , ( modifier-availability ) ;
parameter-list = "(" , ( type-constructor ) , ")" ; [NOTE 7]
protocol-compose = ( attribute-list ) , "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 8]
member-field = IDENTIFIER , type-constructor ;
attribute-list = ( attribute )* ;
attribute = "@" , IDENTIFIER , ( "(" , constant | attribute-args , ")" ) ;
attribute-args = attribute-arg | attribute-arg , "," attribute-args ;
attribute-arg = IDENTIFIER , "=" , constant ;
modifier-availability = "(" , attribute-args , ")" ; [NOTE 9]
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 , ( '|' , constant ) | literal , ( '|' , constant );
ordinal = NUMERIC-LITERAL ;
literal = STRING-LITERAL | NUMERIC-LITERAL | "true" | "false" ;
STRING-LITERAL
The grammar for STRING-LITERAL is as follows:
STRING-LITERAL = "\"" ( unicode-value )* "\"" ;
unicode-value = literal-char | escaped-basic | escaped-unicode ;
literal-char = any unicode character except CR, LF, "\" or "\"" ;
escaped-basic = "\" ( "\" | "\"" | "n" | "r" | "t" ) ;
escaped-unicode = "\u{" ( hex-digit ){1,6} "}" ;
NOTE 1
Attributes for an anonymous layout introduction can be placed in one of two locations:
- before the
typekeyword, or - as part of the
inline-layout.
Placing attributes in both locations for a single layout definition is not allowed by the compiler.
NOTE 2
The grammar allows ( declaration-modifiers )* on all declarations, but the
compiler limits this as follows:
- A modifier cannot occur twice on the same declaration.
- The
flexibleandstrictmodifiers cannot be used together. - The
flexibleandstrictmodifiers can only be used when thelayout-kindisbits,enum, orunion. - The
resourcemodifier can only be when thelayout-kindisstruct,table, orunion.
NOTE 3
The grammar allows ( layout-subtype ) on all declarations, but the compiler limits
this to only be allowed when the layout-kind is bits or enum.
Further, layout-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.
NOTE 4
The value-layout-member allows the more liberal constant in the grammar, but
the compiler limits the values the constant may take:
- Any value that fits the specified
subtype, in the context of anenum. - Any value that fits the specified
subtypeand is a power of two, in the context of abits.
NOTE 5
The ordinal-layout grammar allows any number of members, but strict unions
specifically must have at least one member.
NOTE 6
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.
NOTE 7
The parameter-list allows the more liberal type-constructor in the grammar,
but the compiler only supports layouts that are structs, tables, or unions.
NOTE 8
The service-member allows the more liberal type-constructor in the grammar,
but the compiler limits this to client_end types.
NOTE 9
The modifier-availability allows the more liberal attribute-args in the
grammar, but the compiler limits this to added and removed arguments.
NOTE 10
Default values for struct fields are currently supported, but deprecated. Support will be dropped when all uses of struct defaults are removed (see this issue).