1WHITESPACE = _{ " " | "\n" }
2COMMENT = { block_comment | line_comment }
3
4block_comment = { "/*" ~ (!"*/" ~ ANY)* ~ "*/" }
5line_comment = { "//" ~ (!"\n" ~ ANY)* }
6
7alpha = { 'a'..'z' | 'A'..'Z' }
8digit = { '0'..'9' }
9hexdigit = { digit | 'a'..'f' | 'A'..'F' }
10alphanum = { alpha | digit | "_" }
11
12identifier = @{ alpha ~ alphanum* }
13payload_identifier = @{ "_payload_" }
14body_identifier = @{ "_body_" }
15intvalue = @{ digit+ }
16hexvalue = @{ ("0x"|"0X") ~ hexdigit+ }
17integer = @{ hexvalue | intvalue }
18string = @{ "\"" ~ (!"\"" ~ ANY)* ~ "\"" }
19size_modifier = @{
20    ("+"|"-"|"*"|"/") ~ (digit|"+"|"-"|"*"|"/")+
21}
22
23endianness_declaration = { "little_endian_packets" | "big_endian_packets" }
24
25enum_tag = { identifier ~ "=" ~ integer }
26enum_tag_list = { enum_tag ~ ("," ~ enum_tag)* ~ ","? }
27enum_declaration = {
28    "enum" ~ identifier ~ ":" ~ integer ~ "{" ~
29        enum_tag_list ~
30    "}"
31}
32
33constraint = { identifier ~ "=" ~ (identifier|integer) }
34constraint_list = { constraint ~ ("," ~ constraint)* }
35
36checksum_field = { "_checksum_start_" ~ "(" ~ identifier ~ ")" }
37padding_field = { "_padding_" ~ "[" ~ integer ~ "]" }
38size_field = { "_size_" ~ "(" ~ (identifier|payload_identifier|body_identifier)  ~ ")" ~ ":" ~ integer }
39count_field = { "_count_" ~ "(" ~ identifier ~ ")" ~ ":" ~ integer }
40elementsize_field = { "_elementsize_" ~ "(" ~ identifier ~ ")" ~ ":" ~ integer }
41body_field = @{ "_body_" }
42payload_field = { "_payload_" ~ (":" ~ "[" ~ size_modifier ~ "]")? }
43fixed_field = { "_fixed_" ~ "=" ~ (
44    (integer ~ ":" ~ integer) |
45    (identifier ~ ":" ~ identifier)
46)}
47reserved_field = { "_reserved_" ~ ":" ~ integer }
48array_field = { identifier ~ ":" ~ (integer|identifier) ~
49    "[" ~ (size_modifier|integer)? ~ "]"
50}
51scalar_field = { identifier ~ ":" ~ integer }
52typedef_field = { identifier ~ ":" ~ identifier }
53group_field = { identifier ~ ("{" ~ constraint_list ~ "}")? }
54
55field = _{
56    checksum_field |
57    padding_field |
58    size_field |
59    count_field |
60    elementsize_field |
61    body_field |
62    payload_field |
63    fixed_field |
64    reserved_field |
65    array_field |
66    scalar_field |
67    typedef_field |
68    group_field
69}
70field_list = { field ~ ("," ~ field)* ~ ","? }
71
72packet_declaration = {
73   "packet" ~ identifier ~
74        (":" ~ identifier)? ~
75           ("(" ~ constraint_list ~ ")")? ~
76    "{" ~
77        field_list? ~
78    "}"
79}
80
81struct_declaration = {
82    "struct" ~ identifier ~
83        (":" ~ identifier)? ~
84           ("(" ~ constraint_list ~ ")")? ~
85    "{" ~
86        field_list? ~
87    "}"
88}
89
90group_declaration = {
91    "group" ~ identifier ~ "{" ~ field_list ~ "}"
92}
93
94checksum_declaration = {
95    "checksum" ~ identifier ~ ":" ~ integer ~ string
96}
97
98custom_field_declaration = {
99    "custom_field" ~ identifier ~ (":" ~ integer)? ~ string
100}
101
102test_case = { string }
103test_case_list = _{ test_case ~ ("," ~ test_case)* ~ ","? }
104test_declaration = {
105    "test" ~ identifier ~ "{" ~
106        test_case_list ~
107    "}"
108}
109
110declaration = _{
111    enum_declaration |
112    packet_declaration |
113    struct_declaration |
114    group_declaration |
115    checksum_declaration |
116    custom_field_declaration |
117    test_declaration
118}
119
120file = {
121    SOI ~
122    endianness_declaration ~
123    declaration* ~
124    EOI
125}
126