<program> ::= <statement>* <statement> ::= <label> | <directive> | <instruction> <label> ::= <identifier> <colon> <directive> ::= <dot> <section_directive> <section_directive> ::= "section" <identifier> <instruction> ::= <identifier> <operands> <operands> ::= <operand> ( <comma> <operand> )* <operand> ::= <register> | <immediate> | <memory> <immediate> ::= <number> | <label_reference> <number> ::= <octal> | <binary> | <decimal> | <hexadecimal> <label_reference> ::= <identifier> <memory> ::= <lbracket> <memory_expression> <rbracket> <memory_expression> ::= <label_reference> | <register_expression> <register_expression> ::= <register> <register_index>? <register_offset>? <register_index> ::= <plus> <register> <asterisk> <number> <register_offset> ::= <plus_or_minus> <number> <plus_or_minus> ::= <plus> | <minus> /* These are lexer identifiers with the correct string value */ <section> ::= "section" <register> ::= "rax" | "rbx" | "rcx" | "rdx" | "rsi" | "rdi" | "rbp" | "rsp" | "r8" | "r9" | "r10" | "r11" | "r12" | "r13" | "r14" | "r15"