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