/* BD file grammar in BNF form */
command_file ::= pre_section_block section_block

pre_section_block ::= pre_section_block options_block
| pre_section_block constants_block
| pre_section_block sources_block
| pre_section_block keyblob_block
| empty

options_block ::= OPTIONS '{' option_def '}'

option_def ::= option_def IDENT '=' const_expr ';'
| empty

constants_block ::= CONSTANTS '{' constant_def '}'

constant_def ::= constant_def IDENT '=' bool_expr ';'
| empty

sources_block ::= SOURCES '{' source_def '}'

source_def ::= source_def IDENT '=' source_value ';'
| source_def IDENT '=' source_value '(' source_attr_list ')' ';'
| empty

source_value ::= STRING_LITERAL
| EXTERN '(' int_const_expr ')'

source_attr_list ::= option_list
| empty

option_list ::= IDENT '=' const_expr ',' option_list
| IDENT '=' const_expr

keyblob_block ::= KEYBLOB '(' int_const_expr ')' '{' keyblob_contents '}'

# ----------------------------- Original keyblob grammar -------------
# keyblob_contents ::= keyblob_contents '(' keyblob_options_list ')'
# | empty

# keyblob_options_list ::= keyblob_options
# | empty

# keyblob_options ::= IDENT '=' const_expr ',' keyblob_options
# | IDENT '=' const_expr

# ----------------------------- New keyblob grammar ------------------
keyblob_contents ::= '(' keyblob_options ')'

keyblob_options ::= IDENT '=' const_expr ',' keyblob_options
| IDENT '=' const_expr

section_block ::= section_block SECTION '(' int_const_expr section_options ')' section_contents
| empty

section_options ::= ';' option_list
| ';'
| empty

section_contents ::= '{' statement '}'
| '<=' source_name ';'

statement ::= statement basic_stmt ';'
| statement from_stmt
| statement if_stmt
| statement encrypt_block
| statement keywrap_block
| empty

basic_stmt ::= load_stmt
| load_ifr_stmt
| call_stmt
| jump_sp_stmt
| mode_stmt
| message_stmt
| erase_stmt
| enable_stmt
| reset_stmt
| keystore_stmt

load_stmt ::= LOAD load_opt load_data load_target

load_opt ::= IDENT
| int_const_expr
| empty

load_data ::= int_const_expr
| STRING_LITERAL
| SOURCE_NAME
| section_list
| section_list FROM SOURCE_NAME
| BINARY_BLOB

load_target ::= '>' '.'
| '>' address_or_range
| empty

section_list ::= section_list ',' section_ref
| section_ref

section_ref ::= '~' SECTION_NAME
| SECTION_NAME

erase_stmt ::= ERASE address_or_range
| ERASE ALL

address_or_range ::= int_const_expr
| int_const_expr '..' int_const_expr

symbol_ref ::= SOURCE_NAME'?' ':' IDENT

load_ifr_stmt ::= LOAD IFR int_const_expr '>' int_const_expr

call_stmt ::= call_type call_target call_arg

call_type ::= CALL
| JUMP

call_target ::= int_const_expr
| symbol_ref
| IDENT

call_arg ::= '(' ')'
| '(' int_const_expr ')'
| empty

jump_sp_stmt ::= JUMP_SP int_const_expr call_target call_arg

from_stmt ::= FROM IDENT '{' in_from_stmt '}'

in_from_stmt ::= in_from_stmt basic_stmt ';'
| in_from_stmt if_stmt
| empty

mode_stmt ::= MODE int_const_expr

message_stmt ::= message_type STRING_LITERAL

message_type ::= INFO
| WARNING
| ERROR

keystore_stmt ::= KEYSTORE_TO_NV mem_opt address_or_range
| KEYSTORE_FROM_NV mem_opt address_or_range

mem_opt ::= IDENT
| '@' int_const_expr
| empty

if_stmt ::= IF bool_expr '{' statement '}' else_stmt

else_stmt ::= ELSE '(' statement ')'
| ELSE if_stmt
| empty

keywrap_block ::= KEYWRAP '(' int_const_expr ')' '{' LOAD BINARY_BLOB GT int_const_expr SEMICOLON '}'

encrypt_block ::= ENCRYPT '(' int_const_expr ')' '{' load_stmt '}'

enable_stmt ::= ENABLE AT_INT_LITERAL int_const_expr

reset_stmt ::= RESET

ver_check_stmt ::= VERSION_CHECK sec_or_nsec int_const_expr

sec_or_nsec ::= SEC
| NSEC

const_expr ::= STRING_LITERAL
| bool_expr

int_const_expr ::= expr

bool_expr ::= bool_expr '<' bool_expr
| bool_expr '<=' bool_expr
| bool_expr '>' bool_expr
| bool_expr '>=' bool_expr
| bool_expr '==' bool_expr
| bool_expr '!=' bool_expr
| bool_expr '&&' bool_expr
| bool_expr '||' bool_expr
| '(' bool_expr ')'
| int_const_expr
| '!' bool_expr
| DEFINED '(' IDENT ')'
| IDENT '(' source_name ')'

expr ::= expr '+' expr
| expr '-' expr
| expr '*' expr
| expr '/' expr
| expr '%' expr
| expr '<<' expr
| expr '>>' expr
| expr '&' expr
| expr '|' expr
| expr '^' expr
| expr '.' INT_SIZE
| '(' expr ')'
| INT_LITERAL
| IDENT
| SYMBOL_REF
| unary_expr
| SIZEOF '(' SYMBOL_REF ')'
| SIZEOF '(' IDENT ')'

unary_expr ::= '+' expr
| '-' expr

empty ::=
