Skip to content

Commit d1e588f

Browse files
committed
Added initial version of proto file grammar
1 parent f794d4c commit d1e588f

File tree

1 file changed

+120
-0
lines changed

1 file changed

+120
-0
lines changed

spec/grammar.ebnf

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
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

Comments
 (0)