






Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
The implementation of a binary search tree in ocaml and optimization techniques for a recursive descent parser. It covers topics such as ocaml polymorphic types, parser shortcuts, grammar descriptions, and derivations. The document also includes examples of grammar productions and parse trees.
Typology: Quizzes
1 / 10
This page cannot be seen from the preview
Don't miss anything!







CMSC 330, Spring 2009, Quiz 3 Practice Problem Solutions
module Bst = struct type bst = Empty | Node of int * bst * bst
let empty = Empty (* empty binary search tree *)
let is_empty = function (* return true for empty bst *) Empty -> true | Node (_, _, _) -> false
let rec insert n = function (* insert n into binary search tree *) Empty -> Node (n, Empty, Empty) | Node (m, left, right) -> if m = n then Node (m, left, right) else if n < m then Node(m, (insert n left), right) else Node(m, left, (insert n right))
(* Implement the following functions val min : bst -> int val remove : int -> bst -> bst val fold : ('a -> int -> 'a) -> 'a -> bst -> 'a val size : bst -> int ) let rec min = ( return smallest value in bst ) let rec remove n t = ( tree with n removed ) let rec fold f a t = ( apply f to nodes of t in inorder ) let size t = ( # of non-empty nodes in t *) end
a. Is insert tail recursive? Explain why or why not. No, since the return value for recursive call to insert cannot be used as the return value of the original call to insert. The return value is used to create a Node data type first, and the Node value is returned. b. Implement min as a tail-recursive function. Raise an exception for an empty bst. Any reasonable exception is fine. let rec min = function Empty -> (raise (Failure "min")) | Node (m, left, right) -> if (is_empty left) then m else min left
c. Implement remove. The result should still be a binary search tree. let rec remove n = function Empty -> Empty | Node (m, left, right) -> if m = n then ( if (is_empty left) then right else if (is_empty right) then left else let x = min right in Node(x, left, remove x right) // OR // else let x = max left in // Node(x, remove x left, right) ) else if n < m then Node(m, (remove n left), right) else Node(m, left, (remove n right)) d. Implement fold as an inorder traversal of the tree so that the code List.rev (fold (fun a m -> m::a) [] t) will produce an (ordered) list of values in the binary search tree. let rec fold f a n = match n with Empty -> a | Node (m, left, right) -> fold f (f (fold f a left) m) right e. Implement size using fold. let size t = fold (fun a m -> a+1) 0 t
S (^) and S
true
true true
S (^) or S
S (^) or S
true
true true
S (^) and S
Tree 1 Tree 2 S
S (^) and S
true
true true
S (^) or S
S (^) or S
true
true true
S (^) and S
Tree 1 Tree 2
f. What is implied about the precedence/associativity of “and” and “or” for each parse tree? Tree 1 => or has higher precedence than and Tree 2 => and has higher precedence than or g. Rewrite the grammar so that “and” has higher precedence than “or” and is right associative S S or S | L // op closer to Start = lower precedence op L true and L | true // right recursive = right associative
e. S a b c | a b b S a b L L c | b f. S a b c | a b S a b L L c | g. S a a | a b | a c S a L L a | b | c h. S a a | a b | a S a L L a | b | i. S a a | a b | S a L | L a | b j. S a S c | a S b | b S a S L | b L c | b k. S a S c | a S b | a S a L L S c | S b | S a L L S M | M c | b l. S a S c | a S | a S a L L S c | S | S a L L S M | M c |
if (lookahead == “c”) { match(“c”); // S cL parse_L( ); } else error( ); } parse_L( ) { if (lookahead == “a”) { match(“a”); // L aL parse_L( ); } else if (lookahead == “c”) { match(“c”); // L cL parse_L( ); } else ; // L } d. Describe an abstract syntax tree (AST) Compact representations of parse trees with only essential parts