1+ (*
2+ Protocol Buffers proto file text grammar
3+
4+ This document describes a context free protobuf grammar in EBNF format.
5+ It does not differentiate between proto2 and proto3 syntax.
6+
7+ Some things are allowed in this grammar that are not allowed in proto files.
8+ For example, the "syntax" statement can be used with any string literal.
9+ *)
10+
11+ any = ? * ? ; (* anything matches here, check usages for any specific exceptions *)
12+ whitespace_char = " " | " \n" | " \t" | " \r" | " \v" | " \f" ;
13+ line_comment = " //" , { any - " \n" } , " \n" ;
14+ block_comment = " /*" , { any - " */" } , " */" ;
15+ whitespace = { whitespace_char | line_comment | block_comment } ;
16+
17+ uppercase =
18+ " A" | " B" | " C" | " D" | " E" | " F" | " G" | " H" |
19+ " I" | " J" | " K" | " L" | " M" | " N" | " O" | " P" |
20+ " Q" | " R" | " S" | " T" | " U" | " V" | " W" | " X" |
21+ " Y" | " Z"
22+ ;
23+
24+ lowercase =
25+ " a" | " b" | " c" | " d" | " e" | " f" | " g" | " h" |
26+ " i" | " j" | " k" | " l" | " m" | " n" | " o" | " p" |
27+ " q" | " r" | " s" | " t" | " u" | " v" | " w" | " x" |
28+ " y" | " z"
29+ ;
30+
31+ letter = uppercase | lowercase ;
32+
33+ decimal_digit = " 0" | " 1" | " 2" | " 3" | " 4" | " 5" | " 6" | " 7" | " 8" | " 9" ;
34+ octal_digit = " 0" | " 1" | " 2" | " 3" | " 4" | " 5" | " 6" | " 7" ;
35+ hex_digit =
36+ decimal_digit |
37+ " A" | " B" | " C" | " D" | " E" | " F" |
38+ " a" | " b" | " c" | " d" | " e" | " f"
39+ ;
40+
41+ identifier = letter , { letter | decimal_digit | " _" } ;
42+ full_identifier = identifier { " ." , identifier } ;
43+
44+ type_name = [" ." ] , full_identifier ;
45+
46+ group_identifier = uppercase , { letter | decimal_digit | " _" } ;
47+
48+ decimal_literal = (" 1" | " 2" | " 3" | " 4" | " 5" | " 6" | " 7" | " 8" | " 9" ) , { decimal_digit } ;
49+ octal_literal = " 0" , { octal_literal } ;
50+ hex_literal = " 0" , (" x" | " X" ) , hex_digit , { hex_digit } ;
51+ int_literal = decimal_literal | octal_literal | hex_literal ;
52+
53+ decimal_digits = decimal_digit , { decimal_digit } ;
54+ exponent = (" e" | " E" ) , [" +" | " -" ] , decimal_digits ;
55+ float_literal = ((decimal_digits , " ." , [decimal_digits ] [exponent ]) | (decimal_digits , exponent ) | (" ." , decimal_digits , [exponent ])) | " inf" | " nan" ;
56+
57+ bool_literal = " true" | " false" ;
58+
59+ hex_escape = " \" , (" x" | " X" ) , hex_digit , hex_digit ;
60+ octal_escape = " \" , octal_digit , octal_digit , octal_digit ;
61+ char_escape = " \" , ( " a" | " b" | " f" | " n" | " r" | " t" | " v" | " \" | " '" | ' "' ) ;
62+ char = hex_escape | octal_escape | char_escape | ? /[^\0\n\\]/ ? ;
63+ string_literal = (' "' , { char } , ' "' ) | (" '" , { char } , " '" ) ;
64+
65+ end_statement = " ;" ;
66+
67+ aggregate_literal = " {" , { identifier , " :" , literal } , " }" ; (* whitespace and or comments seperate each field value *)
68+ literal = full_identifier | ([" -" | " +" ] , int_literal ) | ([" -" | " +" ] , float_literal ) | string_literal | bool_literal | aggregate_literal ;
69+
70+ (* after this point, unless specified, concatinated terminals can be seperated by whitespace and or comments, as defined at the top of this file *)
71+
72+ syntax = " syntax" , " =" , string_literal , end_statement ;
73+ import = " import" , [" weak" | " public" ] , " =" , string_literal , end_statement ;
74+ package = " package" , full_identifier , end_statement ;
75+
76+ option_name = (identifier | " (" , full_identifier , " )" ) , {" ." , identifier } ;
77+ option = " option" , option_name , " =" , literal , end_statement ;
78+
79+ short_option = option_name , " =" , literal ;
80+ short_options = short_option , { " ," , short_option } ;
81+
82+ field_label = " optional" | " repeated" | " required" ;
83+ field_type =
84+ " double" | " float" | " int32" | " int64" | " uint32" | " uint64" |
85+ " sint32" | " sint64" | " fixed32" | " fixed64" | " sfixed32" | " sfixed64" |
86+ " bool" | " string" | " bytes" | type_name
87+ ;
88+ group = [field_label ] , " group" , group_identifier , " =" , int_literal , [" [" , short_options , " ]" ] , message_body ;
89+ field = group | ([field_label ] , field_type , identifier , " =" , int_literal , [" [" , short_options , " ]" ] , end_statement ) ;
90+
91+ oneof_field = field_type , identifier , " =" , int_literal , [" [" , short_options , " ]" ] , end_statement ;
92+ oneof = " oneof" , identifier , " {" , { oneof_field | option | end_statement } , " }" ;
93+
94+ key =
95+ " int32" | " int64" | " uint32" | " uint64" |
96+ " sint32" | " sint64" | " fixed32" | " fixed64" | " sfixed32" | " sfixed64" |
97+ " bool" | " string"
98+ ;
99+ map = " map" , " <" , key , " ," field_type , " >" , identifier , " =" , int_literal , [" [" , short_options , " ]" ] , end_statement ;
100+
101+ range = int_literal , [" to" , (int_literal | " max" )] ;
102+ ranges = range , { " ," , range } ;
103+ extensions = " extensions" , ranges , [" [" , short_options , " ]" ] , end_statement ;
104+
105+ field_names = identifier , { " ," , identifier } ;
106+ reserved = " reserved" , (ranges | field_names ) , end_statement ;
107+
108+ enum_value = identifier , " =" , int_literal , [" [" , short_options , " ]" ] , end_statement ;
109+ enum = " enum" , identifier , " {" , { option | enum_value | end_statement } , " }" ;
110+
111+ message_body = " {" , { field | enum | message | extend | extensions | group | option | oneof | map | reserved | end_statement } , " }" ;
112+ message = " message" , identifier , message_body ;
113+
114+ extend = " extend" , identifier , " {" , { field | group | end_statement } , " }" ;
115+
116+ rpc = " rpc" , identifier , " (" , [" stream" ] , type_name , " )" , " returns" , " (" , [" stream" ] , type_name , " )" , ((" {" , { option , end_statement } , " }" ) | end_statement ) ;
117+ stream = " stream" , identifier , " (" , type_name , " ," , type_name , " )" , ((" {" , { option , end_statement } , " }" ) | end_statement ) ;
118+ service = " service" , identifier , " {" , { option , rpc , stream , end_statement } , " }" ;
119+
120+ file = [syntax ] , { import | package | option | message | enum | extend | service | end_statement } ;
0 commit comments