forked from Rantanen/protofish
-
Notifications
You must be signed in to change notification settings - Fork 0
/
proto.pest
95 lines (76 loc) · 4.11 KB
/
proto.pest
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
WHITESPACE = _{ " " | "\t" | "\n" | "\r" }
COMMENT = _{ "//" ~ (!"\n" ~ ANY)* | "/*" ~ (!"*/" ~ ANY)* ~ "*/" }
BOM = _{ "\u{feff}" }
letter = { 'A'..'Z' | 'a'..'z' }
decimalDigit = { '0'..'9' }
octalDigit = { '0'..'7' }
hexDigit = { '0'..'9' | 'A'..'F' | 'a'..'f' }
ident = @{ letter ~ ( letter | decimalDigit | "_" )* }
fullIdent = { ident ~ ( "." ~ ident )* }
messageName = { ident }
enumName = { ident }
fieldName = { ident }
oneofName = { ident }
mapName = { ident }
serviceName = { ident }
rpcName = { ident }
messageType = { "."? ~ ( ident ~ "." )* ~ messageName }
enumType = { "."? ~ ( ident ~ "." )* ~ enumName }
sign = { "-" | "+" }
intLit = { sign? ~ ( hexLit | octalLit | decimalLit ) }
decimalLit = @{ '1'..'9' ~ decimalDigit* }
octalLit = @{ "0" ~ octalDigit* }
hexLit = @{ "0" ~ ( "x" | "X" ) ~ hexDigit+ }
floatLit = { sign? ~ ( ( decimals ~ "." ~ decimals? ~ exponent? | decimals ~ exponent | "." ~ decimals ~ exponent? ) | "inf" | "nan" ) }
decimals = { decimalDigit+ }
exponent = { ( "e" | "E" ) ~ sign? ~ decimals }
boolLit = { "true" | "false" }
strLit = ${ "'" ~ charValueQuot* ~ "'" | "\"" ~ charValueDblQuot* ~ "\"" }
charValueQuot = ${ hexEscape | octEscape | charEscape | !( "\0" | "\n" | "\\" | "'" ) ~ anyChar }
charValueDblQuot = ${ hexEscape | octEscape | charEscape | !( "\0" | "\n" | "\\" | "\"" ) ~ anyChar }
hexEscape = ${ "\\" ~ ( "x" | "X" ) ~ hexByte }
hexByte = ${ hexDigit ~ hexDigit }
octEscape = ${ "\\" ~ octByte }
octByte = ${ octalDigit ~ octalDigit? ~ octalDigit? }
charEscape = ${ "\\" ~ escapeChar }
escapeChar = { "a" | "b" | "f" | "n" | "r" | "t" | "v" | "\\" | "'" | "\"" }
anyChar = ${ ANY }
quote = { "'" | "\"" }
emptyStatement = { ";" }
constant = { intLit | floatLit | strLit | boolLit | fullIdent }
syntax = { "syntax" ~ "=" ~ quote ~ "proto3" ~ quote ~ ";" }
import = { "import" ~ ( "weak" | "public" )? ~ strLit ~ ";" }
package = { "package" ~ fullIdent ~ ";" }
option = { "option" ~ optionName ~ "=" ~ constant ~ ";" }
optionName = { ( ident | "(" ~ fullIdent ~ ")" ) ~ ( "." ~ ident )* }
type_ = { "double" | "float" | "int32" | "int64" | "uint32" | "uint64"
| "sint32" | "sint64" | "fixed32" | "fixed64" | "sfixed32" | "sfixed64"
| "bool" | "string" | "bytes" | messageType | enumType }
fieldNumber = { intLit }
repeated = { "repeated" }
opt_repeated = { repeated? }
field = { opt_repeated ~ type_ ~ fieldName ~ "=" ~ fieldNumber ~ ( "[" ~ fieldOptions ~ "]" )? ~ ";" }
fieldOptions = { fieldOption ~ ( "," ~ fieldOption )* }
fieldOption = { optionName ~ "=" ~ constant }
oneof = { "oneof" ~ oneofName ~ "{" ~ ( option | oneofField | emptyStatement )* ~ "}" }
oneofField = { type_ ~ fieldName ~ "=" ~ fieldNumber ~ ( "[" ~ fieldOptions ~ "]" )? ~ ";" }
mapField = { "map" ~ "<" ~ keyType ~ "," ~ type_ ~ ">" ~ mapName ~ "=" ~ fieldNumber ~ ( "[" ~ fieldOptions ~ "]" )? ~ ";" }
keyType = { "int32" | "int64" | "uint32" | "uint64" | "sint32" | "sint64" |
"fixed32" | "fixed64" | "sfixed32" | "sfixed64" | "bool" | "string" }
reserved = { "reserved" ~ ( ranges | fieldNames ) ~ ";" }
ranges = { range ~ ( "," ~ range )* }
range = { intLit ~ ( "to" ~ ( intLit | "max" ) )? }
fieldNames = { fieldName ~ ( "," ~ fieldName )* }
enum_ = { "enum" ~ enumName ~ enumBody }
enumBody = { "{" ~ ( option | enumField | emptyStatement )* ~ "}" }
enumField = { ident ~ "=" ~ intLit ~ ( "[" ~ enumValueOption ~ ( "," ~ enumValueOption )* ~ "]" )* ~ ";" }
enumValueOption = { optionName ~ "=" ~ constant }
message = { "message" ~ messageName ~ messageBody }
messageBody = { "{" ~ ( field | enum_ | message | option | oneof | mapField | reserved | emptyStatement )* ~ "}" }
service = { "service" ~ serviceName ~ "{" ~ ( option | rpc | emptyStatement )* ~ "}" }
stream = { "stream" }
opt_stream = { stream? }
rpcParam = { opt_stream ~ messageType }
rpc = { "rpc" ~ rpcName ~ "(" ~ rpcParam ~ ")" ~ "returns" ~ "(" ~ rpcParam ~ ")" ~ (( "{" ~ ( option | emptyStatement )* ~ "}" ) | ";") }
proto = { SOI ~ BOM? ~ syntax ~ ( import | package | option | topLevelDef | emptyStatement )* ~ EOI }
topLevelDef = { message | enum_ | service }