You are on page 1of 30

Cse321, Programming Languages and Compilers

Lecture #4, Jan. 24, 2007


• Homework 3
• Representing sets as lists
• the cross product of two sets
• epsilon transitions
• epsilon - closure
•Interpreting an NFA
•NFA to DFA

Labs scheduled: Thursday 4:00 pm,


Friday at 9:00 am

08/01/21 1
Cse321, Programming Languages and Compilers

Assignments
• Read Chapter 2, pages 27-72
– There will be a 5 minute quiz next lecture

• Programming exercise 4 is listed on the web page. It is due


next Monday.
– exercise writing accumulating parameter functions
– a guided exercise to write the e-closure in 10 easy steps

08/01/21 2
Cse321, Programming Languages and Compilers

Homework 3
fun reverse [] = []
| reverse (x::xs) = reverse xs @ [x];

fun reverse2 xs =
let fun revonto [] ans = ans
| revonto (x::xs) ans = revonto xs (x::ans)
in revonto xs [] end;

fun count n [] = 0
| count n (x::xs) =
if n=x then 1 + count n xs else count n xs;

fun concatenate [] = []
| concatenate (xs::xss) = xs @ concatenate xss;

08/01/21 3
Cse321, Programming Languages and Compilers

Fully Parenthesized
fun toStr Empty = "#"
| toStr (C c) = implode [c]
| toStr (Concat(x,y)) = toStrP x ^ toStrP y
| toStr (Union(x,y)) = toStrP x ^"+"^toStrP y
| toStr (Star x) = toStrP x ^ "*"
and toStrP x = "("^toStr x^")";

- toStr re1;
val it = "((+)+((-)+(#)))((D)((D)*))" : string

08/01/21 4
Cse321, Programming Languages and Compilers

Not parenthesizing leaf REs


fun toStr2 Empty = "#"
| toStr2 (C c) = implode [c]
| toStr2 (Concat(x,y)) = toStr2P x ^ toStr2P y
| toStr2 (Union(x,y)) = toStr2P x ^"+"^toStr2P y
| toStr2 (Star x) = toStr2P x ^ "*"
and toStr2P (x as (C _)) = toStr2 x
| toStr2P (x as Empty) = toStr2 x
| toStr2P x = "("^toStr2 x^")";

- toStr2 re1;
val it = "(++(-+#))(D(D*))" : string

08/01/21 5
Cse321, Programming Languages and Compilers

Escaping special characters


fun escape #"+" = "\\+"
| escape #"*" = "\\*"
| escape #"(" = "\\("
| escape #")" = "\\)"
| escape c = implode [c];

fun toStr3 Empty = "#"


| toStr3 (C c) = escape c
| toStr3 (Concat(x,y)) = toStr3P x ^ toStr3P y
| toStr3 (Union(x,y)) = toStr3P x ^"+"^toStr3P y
| toStr3 (Star x) = toStr3P x ^ "*"
and toStr3P (x as (C _)) = toStr3 x
| toStr3P (x as Empty) = toStr3 x
| toStr3P x = "("^toStr3 x^")";

- toStr3 re1;
val it = "(\\++(-+#))(D(D*))" : string

08/01/21 6
Cse321, Programming Languages and Compilers

A separate rule for each sub-RE


fun toStr4 Empty = "#"
| toStr4 (C c) = escape c
| toStr4 (Concat(x,y)) = toStrC x ^ toStrC y
| toStr4 (Union(x,y)) = toStrU x ^"+"^toStrU y
| toStr4 (Star x) = toStrS x ^ "*"
and toStrC (x as (C _)) = toStr4 x
| toStrC (x as Empty) = toStr4 x
| toStrC (x as (Concat _)) = toStr4 x
| toStrC (x as (Star _)) = toStr4 x
| toStrC x = "("^toStr4 x^")"
and toStrU (x as (C _)) = toStr4 x
| toStrU (x as Empty) = toStr4 x
| toStrU (x as (Union _)) = toStr4 x
| toStrU x = "("^toStr4 x^")"
and toStrS (x as (C _)) = toStr4 x
| toStrS (x as Empty) = toStr4 x
| toStrS x = "("^toStr4 x^")";

- toStr4 re1;
val it = "(\\++-+#)DD*" : string
08/01/21 7
Cse321, Programming Languages and Compilers

Representing Sets in ML
• We do it for ‘int’ others would be similar
• Key – Represent a set as an ordered list without duplicates

fun mem x [] = false


| mem x (y::ys) =
if x=y then true datatype order
= EQUAL
else mem x ys; | LESS
| GREATER;

fun setAdd x [] = [x] Note the use of the Int library


compare function.
| setAdd x (y::ys) =
case Int.compare (x,y) of
EQUAL => (y::ys)
| LESS => x::y::ys
| GREATER => y :: setAdd x ys;

08/01/21 8
Cse321, Programming Languages and Compilers

Union of two sets


• Take advantage of the fact that the lists are ordered, this allows union
with time proportional to what?

fun setUnion [] [] = []
| setUnion [] ys = ys
| setUnion xs [] = xs
| setUnion (x::xs) (y::ys) =
case Int.compare (x,y) of
EQUAL => setUnion xs (y::ys)
| LESS => x:: setUnion xs (y::ys)
| GREATER => y :: setUnion (x::xs) ys;

fun setConcat [] = []
| setConcat (x::xs) = setUnion x (setConcat xs);

08/01/21 9
Cse321, Programming Languages and Compilers

Can we turn a normal list into a set?


(* Turn a list into a set *)
(* sort and remove duplicates. *)

fun sort [] = []
| sort (x::xs) = setAdd x (sort xs);

fun remDupFromOrdered [] = []
| remDupFromOrdered [x] = [x]
| remDupFromOrdered (x::y::zs) =
if x=y then remDupFromOrdered (y::zs)
else x:: remDupFromOrdered (y::zs);

fun norm xs = remDupFromOrdered(sort xs);

08/01/21 10
Cse321, Programming Languages and Compilers

Cross Product
• Consider the two sets
– [1,2,6]
– [3,5]
• The cross product is a set of pairs
– all possible pairs (x,y) where x comes from [1,2,6] and y comes from [3,5]
– [(1,3),(1,5),(2,3),(2,5),(6,3),(6,5)]

• How could we compute this? In pseudo code


( ans := [ ]
; while not (null xs) do
let val x = hd xs This has the
pattern of a nested
val ptr = y set of accumulating
in while not (null ptr) do parameter
let val y = hd ptr functions!
in ans := (x,y)::ans
ptr := tl ptr
end;
xs := tl xs
end)
08/01/21 11
Cse321, Programming Languages and Compilers

ML code
fun innerWhile x [] ans = ans
| innerWhile x (y::ys) ans =
innerWhile x ys ((x,y)::ans) ;
fun outerWhile ys [] ans = ans
| outerWhile ys (x::xs) ans =
outerWhile ys xs (innerWhile x ys ans);

fun cross xs ys = outerWhile ys xs [];

( ans := [ ]
; while not (null xs) do
let val x = hd xs
in while not (null ys) do
let val y = hd ys
in ans := (x,y)::ans
xs := tl xs
ys := tl ys
end
end)
08/01/21 12
Cse321, Programming Languages and Compilers

The power of a set of strings


if A = [“x”, “y”]
what is AA, or AAA, or AAAA

fun power 0 x = [""]


| power n x =
map (op ^) (cross x (power (n-1) x));

power 3 ["a","xy"];
Val it = ["xyaxy","xyaa","xyxyxy","xyxya“
,"aaxy","aaa","axyxy","axya"]

08/01/21 13
Cse321, Programming Languages and Compilers
Concat(Union(C #”+”,Union(C #”-”,Empty))
,Concat(C #”D”,Star (C #”D”)))
(+|-| ε)DD*
0 + 1
ε
ε
8
val ex6 = 9 ε 10
(8,15, ε -
[Edge (9,Epsilon,10)
ε 2 3 ε D
,Edge (8,Epsilon,0) 6 7
,Edge (8,Epsilon,6) ε ε 11
,Edge (1,Epsilon,9) 4 ε 5
,Edge (7,Epsilon,9) ε
,Edge (0,Char #"+",1)
14
,Edge (6,Epsilon,2)
,Edge (6,Epsilon,4) ε
,Edge (3,Epsilon,7)
,Edge (5,Epsilon,7) ε 12
,Edge (2,Char #"-",3)
,Edge (4,Epsilon,5) D ε
,Edge (11,Epsilon,14)
,Edge (10,Char #"D",11)
13
,Edge (14,Epsilon,12) ε
,Edge (13,Epsilon,15)
,Edge (14,Epsilon,15) 15
,Edge (15,Epsilon,14)
,Edge (12,Char #"D",13)]) : Nfa
08/01/21 14
Cse321, Programming Languages and Compilers

Epsilon transitions
0 + 1
ε
ε
8
9 ε 10
ε -
ε 2 3 ε D
6 7
ε ε 11
4 ε 5
ε
• Note that in state 8, one can get to 14
{0,6,2,4,5,7,9,10} by not consuming any ε
characters.
ε 12
• We need only take epsilon transitions
D ε
• This set is called the epsilon-closure 13
– eclosure [8] = {0,6,2,4,5,7,9,10} ε
• How do we compute this? 15

08/01/21 15
Cse321, Programming Languages and Compilers

1-step epsilon
0 + 1
ε
ε
8
9 ε 10
ε -
ε 2 3 ε D
6 7
ε ε 11
4 ε 5
ε
• Note that every state has a 1-step epsilon 14
set. ε
many states
• oneStep 8 = [0,6] have empty 12
epsilon sets ε
• oneStep 0 = [ ] D ε
• oneStep 4 = [5] 13
ε
• oneStep 6 = [2,4]
15
• ...
08/01/21 16
Cse321, Programming Languages and Compilers

Recall how an NFA is represented


val ex6 = fun oneStep n (Edge(s,Epsilon,f)) =
(8,15, if n=s then [f] else []
[Edge (9,Epsilon,10)
,Edge (8,Epsilon,0) | oneStep n (Edge(s,Char _,f)) = []
,Edge (8,Epsilon,6)
,Edge (1,Epsilon,9)
,Edge (7,Epsilon,9) • Given a list of edges we apply this
,Edge (0,Char #"+",1)
,Edge (6,Epsilon,2) function to every edge.
,Edge (6,Epsilon,4)
,Edge (3,Epsilon,7)
,Edge (5,Epsilon,7)
,Edge (2,Char #"-",3)
fun oneStepFromEdges es n =
,Edge (4,Epsilon,5) setConcat(map (oneStep n) es);
,Edge (11,Epsilon,14)
,Edge (10,Char #"D",11)
,Edge (14,Epsilon,12)
,Edge (13,Epsilon,15)
,Edge (14,Epsilon,15)
• How does this work?
,Edge (15,Epsilon,14)
,Edge (12,Char #"D",13)])

08/01/21 17
Cse321, Programming Languages and Compilers

Step – by - step
val edges = - oneStep 8 (Edge(5,Epsilon,6));
[Edge (9,Epsilon,10)
,Edge (8,Epsilon,0) val it = [ ]
,Edge (8,Epsilon,6)
,Edge (1,Epsilon,9)
,Edge (7,Epsilon,9)
,Edge (0,Char #"+",1) - oneStep 8 (Edge(8,Epsilon,6));
,Edge (6,Epsilon,2)
,Edge (6,Epsilon,4)] val it = [6] we only get output if
the start state
matches n
fun oneStepFromEdges n es =
List.concat - map (oneStep 8) edges;
(map (oneStep n) es);
val it = [[],[0],[6],[],[],[],[],[]]

- setConcat [[],[0],[6],[],[],[],[],[]];
val it = [0,6] : int list

08/01/21 18
Cse321, Programming Languages and Compilers

One step from a set of states


• Note oneStepFromEdge only gives the e-states from a
single starting state.
• What if I wanted all the reachable states on epsilon from
both 8 or 9? 10
D
0 + 1 ε 11
ε
ε ε
8 14
9
ε -
ε 2 3 ε
ε
6 7 12
ε
ε ε
4 ε 5 D ε
13
fun oneStepFromSet es states = ε
setConcat (map (oneStepFromEdges es) states); 15

08/01/21 19
Cse321, Programming Languages and Compilers

Iterate
fun oneStepFromSet es states =
setConcat (map (oneStepFromEdges es) states);

- oneStepFromSet edges [8];


val it = [0,6] : int list
- oneStepFromSet edges (setUnion [8] [0,6]);
val it = [0,2,4,6] : int list
- oneStepFromSet edges (setUnion [0,6,8] [0,2,4,6]);
val it = [0,2,4,5,6] : int list
- oneStepFromSet edges (setUnion [0,2,4,6,8] [0,2,4,5,6]);
val it = [0,2,4,5,6,7] : int list
- oneStepFromSet edges (setUnion [0,2,4,5,6,8] [0,2,4,5,6,7]);
val it = [0,2,4,5,6,7,9] : int list
- oneStepFromSet edges (setUnion [0,2,4,5,6,7,8] [0,2,4,5,6,7,9]);
val it = [0,2,4,5,6,7,9,10] : int list
- oneStepFromSet edges (setUnion [0,2,4,5,6,7,8,9] [0,2,4,5,6,7,9,10]);
val it = [0,2,4,5,6,7,9,10] : int list

08/01/21 20
Cse321, Programming Languages and Compilers

eclose
- eclose edges [8];
[8]
[0,6]
[0,6,8]
fun eclose edges states =
-----------------------
let val new = oneStepFromSet edges states [0,6,8]
val union = setUnion new states [0,2,4,6]
[0,2,4,6,8]
in if union = states -----------------------
then states [0,2,4,6,8]
else ( print (setToString states) [0,2,4,5,6]
[0,2,4,5,6,8]
; print (setToString new) -----------------------
; print (setToString union) [0,2,4,5,6,8]
[0,2,4,5,6,7]
; print "-------------\n" [0,2,4,5,6,7,8]
; eclose edges union ) -----------------------
end; [0,2,4,5,6,7,8]
[0,2,4,5,6,7,9]
[0,2,4,5,6,7,8,9]
-----------------------
[0,2,4,5,6,7,8,9]
[0,2,4,5,6,7,9,10]
[0,2,4,5,6,7,8,9,10]
-----------------------
val it = [0,2,4,5,6,7,8,9,10]
08/01/21 21
Cse321, Programming Languages and Compilers

Fixed-point functions
fun fix f init =
let val new = f init
in if new=init then new else fix f new end;

fun eclose2 edges xs =


let fun step x = setUnion x (oneStepFromSet edges x)
in fix step xs end;

- eclose2 edges [8];


val it = [0,2,4,5,6,7,8,9,10] : int list

08/01/21 22
Cse321, Programming Languages and Compilers

Simulating an NFA
ε

a ε
2 3
ε
ε 6 ε a b b
0 1
b
7 8 9 10
ε 4 5 ε
ε

• Givena string, say “ababb” use the NFA to


determine if the NFA “accepts” the string.
•ε -closure , All those states reachable from a given
set on transitions via ε transitions only
•Initial state is ε-closure of {0}
•For character in the input string keep track of what
set-of-states the machine could possibly be in.

08/01/21 23
Cse321, Programming Languages and Compilers

Example: “ababb”
ε

a ε
2 3
ε
ε 6 ε a b b
0 1
b
7 8 9 10
ε 4 5 ε
ε
Accepting Algorithm
state input S := S0;
{0;1,2,4,7} “ababb” C := nextchar();
{3,8;6,7,0,1,2,4} “babb” while C <> eof do
{9,5;6,7,0,1,2,4} “abb” { S := move(S,C);
{3,8;6,7,0,1,2,4} “bb” C := nextchar()
{9,5;6,7,0,1,2,4} “b” };
{10,5;6,7,0,1,2,4} ““ if S is in F
then return “yes”
Final state includes the accepting state,
else return “no”
10, so the string is accepted.
08/01/21 24
Cse321, Programming Languages and Compilers

fun transitionOn c states edges =


let fun good (Edge(s,Char x,f)) =
(c=x) andalso (mem s states)
| good _ = false
fun finish (Edge(s,_,f)) = f
in map finish (List.filter good edges) end;

fun nfa edges final states [] = mem final states


| nfa edges final states (c::cs) =
let val _ = print ("State = "^setToString states)
val _ = print ("Input = "^implode(c::cs)^"\n")
val new = eclose2 edges
(transitionOn c states edges)
val _ = print ("On '"^implode [c]^
"' we can get to "^
setToString new)
in if new = []
then false
else nfa edges final new cs
end;

08/01/21 25
Cse321, Programming Languages and Compilers

Code
fun accept (start,final,edges) input =
nfa edges final
(eclose2 edges [start])
(explode input)

- accept ex6 "+DDD";


State = [0,2,4,5,6,7,8,9,10]
Input = +DDD
On '+' we can get to [1,9,10]
State = [1,9,10]
Input = DDD
On 'D' we can get to [11,12,14,15]
State = [11,12,14,15]
Input = DD
On 'D' we can get to [12,13,14,15]
State = [12,13,14,15]
Input = D
On 'D' we can get to [12,13,14,15]
val it = true : bool

08/01/21 26
Cse321, Programming Languages and Compilers

A failing examples
- accept ex6 "+DaD“;
State = [0,2,4,5,6,7,8,9,10]
Input = +DaD
On '+' we can get to [1,9,10]
State = [1,9,10]
Input = DaD
On 'D' we can get to [11,12,14,15]
State = [11,12,14,15]
Input = aD
On 'a' we can get to []
val it = false : bool

- accept ex6 "+";


State = [0,2,4,5,6,7,8,9,10]
Input = +
On '+' we can get to [1,9,10]
val it = false : bool

08/01/21 27
Cse321, Programming Languages and Compilers

Making a DFA
ε

a ε
2 3
ε
ε 6 ε a b b
0 1
b
7 8 9 10
ε 4 5 ε
ε

To turn an NFA into a DFA Simulate all possible transitions


simultaneously. Algorithm is a famous one and is called
“the subset construction”.
DStates := { (e-clos(S0),unmarked) };
while exists (T,unmarked) in DStates do
{ mark T;
for-each input symbol a do
{ U := e-clos(move(T,a));
if U is not in DStates
then add (U,unmarked) to Dstates
Dtran[T,a] := U
} }
08/01/21 28
Cse321, Programming Languages and Compilers
ε

a ε
2 3
ε
ε 6 ε a b b
0 1
b
7 8 9 10
ε 4 5 ε
ε

• Initial state is 0
• ε –closure of 0 is {0;1,2,4,7}
• From any of {0;1,2,4,7}
– We can make a transition on “a” to {3,8}
– We can make a transition on “b” to {5}
• ε –closure of {3,8} is {3,8;6,7,0,1,2,4}
• ε –closure of {5} is {5;6,7,0,1,2,4}
• From any of {3,8;6,7,0,1,2,4}
– We can make a transition on “a” to {3,8} -- which we’ve seen before
– We can make a transition on “b” to {9,5} -- which is new
• From any of {4;6,7,0,1,2,4}
– We can make a transition on “a” to {3,8} -- which we’ve seen before
– We can make a transition on “b” to {5} – which we’ve seen before
ε –closure of {9,5} is {9;6,7,0,1,2,4}
• From any of {9;6,7,0,1,2,4}
– We can make a transition on “a” to {3,8} -- which we’ve seen before
– We can make a transition on “b” to {10,5} – which is new
08/01/21 29
Cse321, Programming Languages and Compilers

Example Algorithm use


ε

a ε
2 3
ε
ε 6 ε a b b
0 1
b
7 8 9 10
ε 4 5 ε
ε
Dstates Dtran on a Dtran on b
A{0;1,2,4,7} B {3,8;1,2,4,6,7} C{5;1,2,4,6,7}
B{1,2,3,4,6,7,8} B{3,8;1,2,4,6,7} D{5,9;6,7,1,2,4}
C{1,2,4,5,6,7} B{3,8;1,2,4,6,7} C{5;1,2,4,6,7}
D{1,2,4,5,6,7,9} B{3,8;1,2,4,6,7} E{5,10;1,2,4,6,7}
E{1,2,4,5,6,7,10} B{3,8;1,2,4,6,7} C{5;1,2,4,6,7}
b
C
b
b
A a b b
B D
a E
a a
08/01/21 30

You might also like