Edit this page Backlinks This page is read only. You can view the source, but not change it. Ask your administrator if you think this is wrong. ====== 4. Regular expressions ====== ===== 4.1. Formation rules (concatenation, reunion, Kleene star) ===== **4.1.1.** $math[A=\{ 0^{2k} \mid k \geq 1 \}] $ B = \{0, \epsilon \}$ \\ $ AB = ? $ \\ **4.1.2.** $math[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 ... \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: {{:lfa:graf1.png?200|}} **4.2.5.** Simplify the regular expression you found. **4.2.6.** Describe as precisely as possible the language generated by $math[(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'': <code python> 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") </code> **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: <code Python> # 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" </code> 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. <hidden More hints> The following table illustrates the string parsing and stack contents (ADT style) for the last example. ^ String contents ^ Stack ^ | ''CONCAT STAR UNION a b STAR c'' | Void | | ''STAR UNION a b STAR c'' | Push(Concat(?,?),Void) | | ''UNION a b STAR c'' | Push(Star(?), Push(Concat(?,?),Void)) | | ''a b STAR c'' | Push(Union(?,?), Push(Star(?), Push(Concat(?,?),Void))) | | ''b STAR c'' | Push(a, Push(Union(?,?), Push(Star(?), Push(Concat(?,?),Void)))) | | ''b STAR c'' | Push(Union(a,?), Push(Star(?), Push(Concat(?,?),Void))) | | ''STAR c'' | Push(b, Push(Union(a,?), Push(Star(?), Push(Concat(?,?),Void)))) | | ''STAR c'' | Push(Union(a,b), Push(Star(?), Push(Concat(?,?),Void))) | | ''STAR c'' | Push(Star(Union(a,b)), Push(Concat(?,?),Void))) | | ''STAR c'' | Push(Concat(Star(Union(a,b)),?),Void))) | | ''c'' | Push(Star(?),Push(Concat(Star(Union(a,b)),?),Void)))) | | | Push(c, Push(Star(?),Push(Concat(Star(Union(a,b)),?),Void))))) | | | Push(Star(c),Push(Concat(Star(Union(a,b)),?),Void)))) | | | Push(Concat(Star(Union(a,b)),Star(c)),Void)))) | The string has been consumed and the stack holds one expression, thus the result is: ''Concat(Star(Union(a,b)),Star(c))''. </hidden> ===== 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.