Homework 1 Solutions

    1. Distinction between Compilation and Interpretation: Compilation takes the source program as an input and produces a target program. The target program, not the compiler, ultimately executes the input. Interpretation takes the source program and an input file as input and directly executes the source program on the input file.
    2. Advantages of Interpretation
      1. Greater flexibility. This greater flexibility comes in a number of forms:
        1. The types and sizes of variables do not have to be determined until runtime and can depend on the types of the input values. For example, the label for a command button in a user interface might either be a string or an image. The size of the label will depend on whether the type is a string or an image.
        2. A program can dynamically write new pieces of itself and execute them on the fly (e.g., a spreadsheet can take new formulas and execute them on the fly).
        3. A user can often provide a new definition for a single function and keep running the program, without shutting it down. This can help with debugging.
      2. Better diagnostic error messages
      3. Easier to debug programs because interpreter can often provide a better debugger
    3. Advantages of a Compiler
      1. Better runtime performance: The target program generated by a compiler will typically execute much more quickly on the input than an interpreter.
      2. Can catch many type errors and undeclared variable errors at compile-time. Because the compiler requires that the types of variables be declared statically, it can catch many mismatches between the declaration and use of a variable at compile time, rather than having to wait until run time, like an interpreter must.
    4. The disadvantages of an interpreter are the advantages of a compiler, and vice versa.

  1. Principal phases of compilation, and the work performed by each phase:
    1. Scanner: Identifies the tokens in a program and outputs them to the parser as a stream.

    2. Parser: Verifies the syntactic correctness of a program and organizes the tokens into a parse tree that represents higher level language constructs in terms of their constituents.

    3. Semantic Analyzer: Discovers the meaning in a program. Builds a symbol table that represents information about the names declared in a program (functions, variables, classes, etc.) and their associated information. Ensures that names in a program are used consistently. For example, it ensures that functions return the correct types, that function calls have the right number of arguments and that the argument types match the types of the parameters, and that uses of variables match their declared types. The semantic analyzer typically outputs either an abstract syntax tree or intermediate code.

    4. Machine-independent Code Improvement: Converts the intermediate code into a more efficient form, for example, by eliminating unnecessary loads and stores of variables to and from registers.

    5. Target Code Generation: Converts the intermediate code into the target language, such as assembly code.

    6. Machine-specific Code Improvement: Converts the target program into a more efficient form, based on the target machine architecture. This code improvement may utilize different levels of cache, different numbers of registers, and pipelined operations.

    1. date -> Jan [1-9][0-9]? 20[0-9][0-9]
    2. date -> month [1-9][0-9]? 20[0-9][0-9]
      month -> Jan | Feb | Mar | Apr | May | Jun
    3. address -> streetNumber \s streetName \s streetSuffix
      streetNumber -> [1-9][0-9]?[0-9]?[0-9]?[0-9]?
      streetName -> [A-Z][a-z]*(\s [A-Z][a-z]*)*
      streetSuffix -> Rd | Ln | Ave | St
    4. number -> [+-]?(integer | float)
      integer -> [1-9][0-9]*
      float -> (0 | integer).[0-9]+
    1. command -> moveCmd | rotateCmd | zoomCmd | scaleCmd
      moveCmd -> move direction number
      direction -> up | down | left | right
      rotateCmd -> rotate number (degrees | radians)
      zoomCmd -> zoom number
      scaleCmd -> scale number number number
    2. relExp -> operand operator operand
      operand -> number | id
      operator -> < | <= | > | >= | == | !=
    3. boolExp -> boolExp and boolExp
              |  boolExp or boolExp
              |  not boolExp 
              |  ( boolExp )
              |  relExp
    4. whileLoop -> while ( boolExp ) do loopBody end
      loopBody -> (assignStmt | whileLoop)+
      assignStmt -> id = exp ;
  2. It is also a regular expression because it involves no recursion.

  3. There are a number of similar looking state machines you might have drawn. I have drawn two--one that just recognizes strings of the form:
    letter (letter | digit)*
    and gets "stuck" if it sees anything that would cause an error (such as a string that starts with a digit), and one that goes to an error state if it sees anything other than a letter or a digit: