Midterm Exam 5 Questions - Programming Languages and Compilers | CS 421, Exams of Computer Science

Material Type: Exam; Professor: Kamin; Class: Progrmg Languages & Compilers; Subject: Computer Science; University: University of Illinois - Urbana-Champaign; Term: Spring 2010;

Typology: Exams

Pre 2010

Uploaded on 12/08/2010

agarwa15
agarwa15 🇺🇸

2 documents

1 / 17

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
CS 421 Spring 2010 Midterm 1
Wednesday, February 24, 2010
Name
NetID
You have 75 minutes to complete this exam
This is a closed bo ok exam.
Do not share anything with other students. Do not talk to other students. Do not look
at another student’s exam. Do not expose your exam to easy viewing by other students.
Violation of any of these rules will count as cheating.
If you believe there is an error, or an ambiguous question, seek clarification from one of the
TAs. You must use a whisper, or write your question out.
Including this cover sheet, there are 17 pages to the exam. Please verify that you have all 17
pages.
Please write your name and NetID in the spaces above, and at the top of every page.
Question Value Score
1 10
2 10
3 10
4 10
5 10
6 10
7 10
8 10 + 5 XC
9 10
10 10
11 10 XC
Total 100 + 15
1
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff

Partial preview of the text

Download Midterm Exam 5 Questions - Programming Languages and Compilers | CS 421 and more Exams Computer Science in PDF only on Docsity!

CS 421 Spring 2010 Midterm 1

Wednesday, February 24, 2010

Name

NetID

  • You have 75 minutes to complete this exam
  • This is a closed book exam.
  • Do not share anything with other students. Do not talk to other students. Do not look at another student’s exam. Do not expose your exam to easy viewing by other students. Violation of any of these rules will count as cheating.
  • If you believe there is an error, or an ambiguous question, seek clarification from one of the TAs. You must use a whisper, or write your question out.
  • Including this cover sheet, there are 17 pages to the exam. Please verify that you have all 17 pages.
  • Please write your name and NetID in the spaces above, and at the top of every page.

Question Value Score

8 10 + 5 XC

11 10 XC

Total 100 + 15

  1. (10pts) Immediately after each of the following declarations, what is the most general type of f (use type variables where necessary)?

(a) (1pt) let f = 3.

float

(b) (1pt) let f x = x + 2

int → int

(c) (1pt) let f x y = if x then y else y *. 2.

bool → float → float

(d) (1pt) let f (x, y) z = (x, y, z)

‘a * ‘b → ‘c → ‘a * ‘b * ‘c

(e) (1pt) let f (x, y) (a, b) = if x = a then y else b

‘a * ‘b → ‘a * ‘b → ‘b

(f) (2pt) let rec f x y = match x with [] -> y | a::b -> a::f b y ‘a list → ‘a list → ‘a list

(g) (3pt) let f (x, y) = match x with [] -> [x; y] | :: -> [y; x] ‘a list * ‘a list → ‘a list list

(b) (6pts) Write a function rev : ’a list -> int -> ’a list such that rev xl n re- turns a list of the first n elements of xl in reverse order, followed by the remaining elements in their original positions. You can assume that n is between 0 and the length of xl.

Examples:

rev [1; 2; 3; 4] 2;;

  • : int list = [2; 1; 3; 4]

rev [1; 2; 4] 0;;

  • : int list = [1; 2; 4]

rev [3; 5; 7] 3;;

  • : int list = [7; 5; 3]

rev [3; 8; 9; 2] 3;;

  • : int list = [9; 8; 3; 2]

let rec rev_aux xl rl n = if n <= 0 then rl@xl else match xl with [] -> rl | x::xs -> rev_aux xs (x::rl) (n - 1)

let rev xl n = rev_aux xl [] n

  1. (10pts) Write is_square: int -> bool such that is_square n returns true if and only if n is a square number, that is, there exists an integer m such that n = m ∗ m. Hint: do not worry about efficiency; only correctness counts. You can search for m among all of the integers from 1 to n.

let rec is_square_aux n m = if m > n then false else if m * m = n then true else is_square_aux n (m + 1)

let is_square n = is_square_aux n 0

  1. (10pts) In this question, you will write separate DFAs for lexing integer, hexadecimal, and octal constants, and then combine them. In each case, you should give a DFA with a start state, and with every other state labeled either “Error” or the type of the particular token the DFA is recognizing.

(a) An int is a either the digit ‘0’ by itself, or a digit ‘1’ - ‘9’ followed by zero or more digits ‘0’ - ‘9’. Your states should be labeled Start, Error, or Int.

Start

Int

Int

(b) A hexadecimal constant, or hex, is “0x” followed by a sequence of one or more hexadec- imal digits (‘0’ - ‘9’, ‘A’ - ‘F’, ‘a’ - ‘f’). Your states should be labeled Start, Error, or Hex.

Start Error Hex

0-9, A-F, a-f

0-9, A-F, a-f

Error

x

(c) An octal constant is ‘0’ followed by a sequence of one or more octal digits (‘0’ - ‘7’). (Note that a single ‘0’ is not a valid octal constant.) Your states should be labeled Start, Error, or Octal.

Start Octal

Error

(d) Give a DFA that recognizes ints, hexes and octals. Your states should be labeled Start, Error, Int, Hex, or Octal.

Int

1-

0-

Start Error Hex 0 0-9, A-F, a-f

0-9, A-F, a-f

Int x

Octal

0- 0-

Please write your solution to the problem from the previous page here:

let digit = [’0’ - ’9’] let hexdigit = [’0’ - ’9’, ’A’ - ’F’, ’a’ - ’f’] let octdigit = [’0’ - ’7’]

rule tokenize = parse

(* add your rules below *)

| ’+’ { PLUS } | ’’ { TIMES } | (’0’ | [’1’-’9’] digit) as s { INT (int_of_string s) } | ’0’ octdigit+ as s { OCTAL (octal_of_string s) } | "0x" hexdigit+ as s { HEX (hex_of_string s) }

  1. (10pts) Consider the following ambiguous grammar:

S → | S + S | S * S

(a) (1pt) Give a sentence that has two parse trees.

(b) (1pt) Show the two parse trees.

S

S

  • S

1.0 + 1.

S

S

1.0 + 1.

(c) (3pts) Based on those parse trees, show a stack/lookahead configuration where there are two different actions - either a shift and a reduce, or two different reduces - that would lead to the two parse trees shown, and say which action leads to which tree.

S + 1.0. + 1.

Here the central. separates the stack from the remaining input. Shifting results in the first parse tree; reducing results in the second.

  1. (10pts + 5pts XC) Consider the following definitions:

exception Parse_failure type token = LBRACKET | RBRACKET | LPAREN | RPAREN | COMMA | SEMICOLON | INT of int

We want to write a recursive descent parser recognizing the language of lists of pairs of integers (e.g. [], [(1, 2)], [(1, 2); (3, 4); (0, 1)].) Note that pair items are separated by a comma and list items are separately by semicolons. Your parser should have the following signature:

parse : token list -> bool

parse takes in a list of tokens and returns true if the corresponding string is in the language. If the string is not in the language, parse raises the exception Parse_failure.

(a) (5 pts.) Write a grammar for this language. Make sure it is not left-recursive and does not require an “obvious” left-factoring (i.e. there are no two productions for any non-terminal that begin exactly the same).

S → [ T ]

T →  | P U

P → ( , ) U →  | ; P U

Note: Alternatively, you can use tokens (LBRACKET, etc...) in the above grammar.

(b) (5 pts XC) Argue that your grammar is LL(1) by showing that the FIRST sets of right- hand sides do not overlap. (You can ignore FOLLOW sets, even if your grammar has -productions.)

In regards to T: First() = {•}, whereas First(P U ) =First(P ) = {(}, so there is no intersection

In regards to U: First() = {•}, whereas First(; P U ) = {; }, so there is no intersection.

(c) (5 pts) Write a recursive-descent parser based on this grammar.

let rec parse_S toks = match toks with LBRACKET::toks’ -> ( match parse_T toks’ with RBRACKET::toks’’ -> toks’’ | _ -> raise Parse_failure ) | _ -> raise Parse_failure and parse_T toks = match toks with LPAREN::_ -> parse_U (parse_P toks) | _ -> toks and parse_P toks = match toks with LPAREN::INT _::COMMA::INT _::RPAREN::toks’ -> toks’ | _ -> raise Parse_failure and parse_U toks = match toks with SEMICOLON::toks’ -> parse_U (parse_P toks’) | _ -> toks

let parse toks = match parse_S toks with [] -> true | _ -> raise Parse_failure

  1. (10pts) True or False

(a) True False OCaml is a statically typed language

(b) True False OCaml employs automatic memory management

(c) True False Any program written in OCaml is guaranteed to terminate, due to OCaml’s strong type system

(d) True False In OCaml, every element of a tuple must have the same type

(e) True False Every LL(1) grammar is unambiguous

(f) True False Every unambiguous grammar is LL(1)

(g) True False Nested comments can be recognized by a regular expression

(h) True False LR(1) parsers are capable of recognizing any context-free language

(i) True False LR(1) (bottom-up) parsers cannot handle left recursion.

(j) True False The use of let rec instead of let provides a note to the programmer that a function is recursive, but has no significance to the OCaml compiler.

  1. (10pts) Extra Credit

Write a function counts : ’a list -> (’a * int) list.

counts xl returns a list of n pairs, where n is the number of distinct elements in xl. The ith pair is (x, j) where x is the ith distinct element of xl (ordering distinct elements of xl by first occurrence in xl), and j is the total number of times x occurs in xl. Example:

counts [1; 2; 3; 1; 3; 2; 1; 4];;

  • : (int * int) list = [(1, 3); (2, 2); (3, 2); (4, 1)]

let rec count_instance a xl = match xl with [] -> [(a, 1)] | (b, n)::xs -> if b=a then (a, n + 1)::xs else (b, n)::count_instance a xs

let rec counts_aux xl rl = match xl with [] -> rl | x::xs -> counts_aux xs (count_instance x rl)

let counts xl = counts_aux xl []