| Assignment 3 solution
    
     Part of 
      
      the homework for 22C:50, Summer 2004
      
     
      | 
     1             |; demo of types of expressions (<operand>)
     2             |
     3             |IDENT = 1     ; an identifier for demo purposes
     4             |
     5             |; forms of terms, note that <operand> ::= <term>
     6 0000: 0001  |      W IDENT            ; <term> ::= <identifier>
     7 0002: 0063  |      W 99               ; <term> ::= <number>
     8 0004: 0004  |      W .                ; <term> ::= .
     9             |
    10             |; forms of expressions, note that <term> ::= IDENT
    11 0006: 0001  |      W IDENT            ; <operand> ::= <term>
    12 0008: 0002  |      W IDENT + IDENT    ; <operand> ::= <term> { + <term> }
    13 000A: 0003  |      W IDENT + IDENT + IDENT
    14 000C: 0004  |      W IDENT + IDENT + IDENT + IDENT
    15             |
    16             |; permissible operators
    17 000E: 0002  |      W IDENT + IDENT   ; ::= <term> { (+|-|&||) <term> }
    18 0010: 0000  |      W IDENT - IDENT
    19 0012: 0001  |      W 99 & IDENT      ; note, 99 and 1 is 1
    20 0014: 0063  |      W 99 | IDENT      ; note, 99 or 1 is 99
    21             |
    22             |; parentheses (not in the BNF, but in parse_operand)!
    23 0016: 0001  |      W (IDENT)
    24 0018: 0002  |      W IDENT + (IDENT)
    25 001A: 0002  |      W (IDENT) + IDENT
    26 001C: 0002  |      W (IDENT + IDENT)
    27             |
    28             |; some illustrations of operator precidence and parens
    29 001E: 0005  |      W    1 + 2 - 3 & 4 | 5    ; = 5
    30 0020: 0005  |      W (((1 + 2)- 3)& 4)| 5    ; = 5
    31 0022: 0002  |      W    1 +(2 -(3 &(4 | 5))) ; = 2
    32 0024: 0002  |      W   (1 + 2)-(3 &(4 | 5))  ; = 2
    33 0026: 0000  |      W  ((1 + 2)- 3)&(4 | 5)   ; = 0
    34             |
    35             |; contexts for expressions
    36 0028: 02    |      B IDENT + 1
    37 0029: 0003  |      W IDENT + 2
    38             |IDENT = IDENT + 3
a) Modified EBNF grammar from Figure 2.9
We need to change only one rule of this grammar, from
<statement> ::= [ <identifier> : ] [ ( B | W ) <operand> ]
to
<statement> ::= { <identifier> : } [ ( B | W ) <operand> ]
b) Modified parser from Figure 2.16
Again, the change required is very small; we replace an if statement with a while loop:
          /* parse optional label */
          while (!strcmp(lex.next,":")) {
               lex_scan(); /* skip over identifier */
               lex_scan(); /* skip over colon */
          }
c) Modified parser with graceful error handling:
          /* parse optional label */
          while (!strcmp(lex.next,":")) {
               if (!is_identifier(lex.this)) {
                    error("label must be identifier");
               }
               lex_scan(); /* skip over identifier or error */
               lex_scan(); /* skip over colon */
          }
Here is an alternate solution that will force malformed labels to be reported as "unexpected opcode" errors.
          /* parse optional label */
          while (is_identifier(lex.this)
          &&     !strcmp(lex.next,":")      ) {
               lex_scan(); /* skip over identifier */
               lex_scan(); /* skip over colon */
          }
There are two fairly obvious ways to do this, one using arithmetic, and the other using logic and bit manipulation. Both of these work identically in Java, C and C++. The solutions given here work for unsigned integers. If negative values are to be held, there is more work required in both cases.
first_byte = value / 256 second_byte = value % 256 first_byte = value >> 8 second_byte = value & 255