(empty is used as the symbol for the empty string.)start -> list eof list -> expr ; list | empty expr -> expr + term { print('+') } | expr - term { print('-') } | term term -> term * factor { print('*') } | term / factor { print('/') } | term div factor { print('DIV') } | term mod factor { print('MOD') } | factor factor -> ( expr ) | id { print(id.lexeme) } | num { print(num.value) }
The grammar is left-recursive. We use the standard method (see the lecture notes from lecture 3) to eliminate left-recursion. We get this syntax-directed translation scheme (ASU-86 Fig 2.38):
start -> list eof list -> expr ; list | empty expr -> term moreterms moreterms -> + term { print('+') } moreterms | - term { print('-') } moreterms | empty term -> factor morefactors morefactors -> * factor { print('*') } morefactors | / factor { print('/') } morefactors | div factor { print('DIV') } morefactors | mod factor { print('MOD') } morefactors | empty factor -> ( expr ) | id { print(id.lexeme) } | num { print(num.value) }
In the program in section 2.9 of the course book (ASU-86), the parser in parser.c has been hand-optimized to eliminate tail recursion, using the methods described on page 52-53 in ASU-86. For example, the non-terminals term and morefactors are handled by the function term, which contains a while loop. Modern C compilers will perform these optimizations automatically. Since they are unnecessary and make the program harder to understand, they have been removed in the version of the program available on these web pages.
The postfix representation of an assignment variable = value is is variable value =. For example, the postfix representation of fum = 10 * 3 + foo is fum 10 3 * foo + =.
We add a production for a new non-terminal called assignment, and also change the definition of list from a list of expressions to a list of assignments. The grammar now starts like this:
Assume that we want to handle both assignments and expressions. Write a grammar for that.start -> list eof list -> assignment ; list | empty assignment -> id = expr expr -> term moreterms ...
Would it be possible to write a predictive recursive-descent parser for your grammar? (Hints: Is it ambiguous? Is it left-recursive? Are FIRST sets disjoint?)
Also print the assigned value after each assignment.
Just use integer operations in your calculations. The result of 10 / 3 should be 3, and the result of 1 / 3 should be 0.
Examples of input and output:
Input | Postfix | Value |
---|---|---|
2 ^ 3 | 2 3 ^ | 8 |
2 ^ 3 * 4 | 2 3 ^ 4 * | 32 |
2 * 3 ^ 4 | 2 3 4 ^ * | 162 |
2 ^ 3 ^ 4 | 2 3 ^ 4 ^ | 4096 |
For the report, include and explain any changes you made to the grammar and to the program.
Even if you don't send a report by e-mail, we advise that you write down your answers, to facilitate communication and for your own later use.