These are some of the questions from the final I gave in FQ89. This subset reflects material that has been covered so far in FQ97 CSE401.

Q: Bill claims that compiler writers no longer need to care about the size of object code their compilers produce. Al argues that code size is still important. Which arguer is the most believable, and why?

A: It is true that high speed memories have gotten larger, so that object code space isn't the obsession it used to be. However, producing large object files takes more time to generate, more time to load, more disk space, more cache flushing, more system level paging activity. Although lager object files are probably faster to execute, the overall savings after you consider system's issues, may be negligible. However, the balance of power changes every decade or so.

Q: What is the purpose of a compiler compiler?

A: A compiler writer automatically converts a formal specification of a compiler into a compiler.

Q: Gerald ahs the choice of implementing a language requirement (such as a requirement that expressions can not be passed by reference to procedures) by using syntactic checks or by using semantic checks. Describe why one technique is better than the other.

A: You can only do so much using syntax. For example, you can't test context sensitive dependencies, such as dependencies before use. Some things you can test entirely syntactically, but to do so may require many additional productions in the grammar, thus increasing the grammar's complexity.

Q: Richard is tryin to name two advantages that a one pass compiler for language X has over a two pass compiler for language X, since his boss, being a military man, likes to do things several times. Help Richard out.

A: A one pass compiler will be much faster than a two pass compiler, since it is not constantly revisiting and reworking the same part of the program. A one pass compiler is suitable for compile/load/go models of execution, such as you need in a student environment.

Q: A famous computer scientist once quipped: "It is easier to change the specification to fit the program than vice versa" Describe how this saying is relevant/irrelevant to writing compilers?

A: The specification is an iron clad contract between the language designer and the language user. The compiler writer is bound by the contract, and does not have the liberty to change the contract, even though eliminating seemingly innocuous thins from the specification might considerably simplify the implementation. If the implementor wants to renegotiate the contract, then she is welcome to try.

Q: Here are some error messages that "production" compilers on UNIX generate. If want two answers from each message. First, tell me which part of the overall compiler system (from scanner through runtime and debugger) is probably responsible for generating the error message. Second, tell me if the message is fatal and should preclude continued execution in the compiler system.

Q&A:


illegal combination of pointer and integer; attributer; probably not source file "test.c" not compiled for debugging; debugger; probably not expression causes compiler loop; try simplifying; code generator; clearly inserted keyword "then"; parser; probably not no more processes; multi pass compiler driver (such as gcc); yes out of tree space: try simplifying; AST builder; yes undefined: _sin ; linker; yes expression type clashed with type of value parameter; attributer; probably floating exception (core dumped); run time system; yes (clearly) variable x is neither used or set; code improver; no undefined variable; attributer; yes intermediate file format error; any pass (multi pass compiler); yes illegal character: 001 (octal); scanner; probably not eliminated 247 instructions; improver; no

Q: Write the regular expression matched by the following piece of C/C++ code. You can use the symbol X to stand for the set of all characters. Be sure to show intermediate work.

if ch == 'a' then {
  ch = getnext();
  while (ch == 'a' || ch == 'b') {
    ch = getnext();
    do {
      ch = getnext();
    } while (ch != 'c');
  }
  accept();
} else {
  accept();
}

A: (e means epsilon): (a ((a | b) X c *) *) | e