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