4. Regular expressions
4.1. Formation rules (concatenation, reunion, Kleene star)
4.1.1.
$ A=\{ 0^{2k} \mid k \geq 1 \}$
$ B = \{0, \epsilon \}$
$ AB = ? $
4.1.2.
$ A = \{ 0^n 1^n \mid n \geq 1 \}$
$ B = \{ 1^n \mid n \geq 1 \} $
$ AB = ? $
$ BA = ? $
4.1.3.
$ A = \emptyset $
$ B = \{ 1^n \mid n \geq 1 \} $
$ AB = ? $
$ A^* = ? $
$ B^* = ? $
4.2. Writing Regular Expressions
4.2.1. Write a regular expression for the language of arithmetic expressions containing +, * and numbers. Hint: you can abbreviate $ 0 \cup 1 \cup \ldots \cup 9 $ by $ [0-9] $
4.2.2. Write a regular expression for $ L = \{ \omega \text{ in } \text{{0,1}} ^* \text{ | EVERY sequence of two or more consecutive zeros appears before ANY sequence of two or more consecutive ones} \} $
4.2.3. Write a DFA for $ L(( 10 \cup 0) ^* ( 1 \cup \epsilon )) $
4.2.4. Write a regular expression which generates the accepted language of A:
4.2.5. Simplify the regular expression you found.
4.2.6. Describe as precisely as possible the language generated by $ (1 \cup 1(01^*0)1)^*$
4.3. Regex implementation (Python)
Inheritance and isinstance
Python supports multiple class inheritance, however, in the spirit of it's dynamical typing strategy, it does not enforce method implementation. Hence - interfaces or abstract classes do not exist per se.
The following example illustrates class inheritance, as well as isinstance
:
class Point2D: # the class constructor. def __init__(self,x,y): self.x = x self.y = y def fun(self,a): return a+1 # class Point3D inherits Point2D class Point3D(Point2D): def __init__(self,x,y,z): # using super, we call the parent class constructor super().__init__(x,y) # an alternative syntax with the same effects: # super(Point3D,self).__init__(x,y) self.z = z def fun(self,a): return a + 2 p = Point3D(1,2,3) print(p.fun(1)) # another illustration of super - we use it to call fun from the parent class. # super(X,O).f() will call function f from the __parent__ of type X, of object O. print(super(Point3D,p).fun(1)) # usage of isinstance to see if an object is an instance of a class (or it's parent) if isinstance(p,Point3D): print("Point3D") if isinstance(p,Point2D): print("Point2D")
4.3.1. Write a class hierarchy for Regular Expressions, and add the str
function for each of them. Implement a constructor which reads a Regular Expression in Prenex form, from a string. The prenex form is illustrated below via examples:
# a* s = "STAR a" # ab s = "CONCAT a b" # a U b s = "UNION a b" # (a U b)*c* s = "CONCAT STAR UNION a b STAR c"
Hints:
- To properly read a regular expression, you need a state of the parsing process, as well as information about what was parsed. What kind of data-structure is necessary for this step? This data-structure will be widely-used later, when we discuss Push-down Automata.
4.4. Regex implementation (Haskell)
4.4.1. Implement the ADT Regex
.
4.4.2. Enrol the type in class Show
.
4.4.3. Write a function which takes a string containing a regex in prenex form (see the Python exercises) and returns a Regex
. *Hint: use two mutually recursive functions and see the hints regarding the stack from the Python implementation section.