├── FSM_to_RegEx.py ├── README.md ├── _input ├── input_eqn.py └── reEnter_eqns.py ├── driver_funcs ├── ardens.py ├── companion.py └── eqn_mask.py ├── globals └── global.py ├── main.py └── utils ├── arr_to_string.py ├── eqnSyntax_check.py ├── remove_extra_spaces.py └── syntax_check.py /FSM_to_RegEx.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Mon Aug 4 17:44:57 2022 4 | @author: Kushal Kumar 5 | """ 6 | 7 | # ============================================================================= 8 | """ 9 | user pre-cautions: 10 | 1.enter only distinct state and transition names 11 | 2.enter integer values when asked how many states or transitions 12 | the code takes care of: 13 | 1.proper RE syntax was inserted 14 | 2.no foreign transitions or states are there in local FSM 15 | 3.user receives and stores their own states and transitions variables, making code robust 16 | """ 17 | 18 | # ============================================================================= 19 | # ======>> PER DEVELOPMENT PROGRESS: 20 | # 4 aug: ardens method 21 | # method to return rest of eqn of a particular state 22 | # 6 aug: state/transition/initial,final state inputs 23 | # regular expression equation inputs 24 | # masking of user defined equations to code executable eqns 25 | # 7 aug: code to check proper RE syntax is maintained on the fly 26 | # user driven dynamicness of updation and changing FSM variables even after inputting 27 | # 28 | # ============================================================================= 29 | # ======>> NEXT DEVELOPMENT PHASE WORKS: 30 | # - no state is left unvisited by any state in state graph of RE eqns 31 | # ============================================================================= 32 | 33 | 34 | null_state = chr(198) #the lambda of RE 35 | #the next 5 variables store values of RE given by User 36 | state=[] 37 | transition=[] 38 | initial_state="" 39 | final_state="" 40 | eqns={} 41 | #program uses states of a,b,c,.... and 0,1,2,... transitions to be used 42 | states='abcdefghijklmnopqrstuvwxyz' 43 | transitions='0123456789' 44 | #code object stores the same things but masked variations that is used by program 45 | code={ 46 | "eqns":{}, 47 | "state":[], 48 | "transition":[], 49 | "initial_state":"", 50 | "final_state":"" 51 | } 52 | 53 | 54 | # ============================================================================= 55 | 56 | def arrToStr(array): 57 | if len(array)==0: 58 | return "" 59 | return array[0]+(arrToStr(array[1:]) if len(array)>1 else "") 60 | 61 | # ============================================================================= 62 | 63 | def formalities(str): 64 | if " " in str: 65 | str=str.replace(" ","") 66 | return str 67 | 68 | # ============================================================================= 69 | 70 | def getCompanion(str,index,mode=True,nextPart=False): 71 | #mode:True get companion only, False get state attached to it also 72 | #nextPart:False-return companion, True-return expression ahead of companion 73 | formalities(str) 74 | totalBracesCount=0 75 | pos=index 76 | companion="" 77 | if str[index] in states and mode is True: 78 | index+=1 79 | for x in str[index:]: 80 | if x=="(": 81 | totalBracesCount+=1 82 | elif x==")": 83 | totalBracesCount-=1 84 | pos+=1 85 | if totalBracesCount==0 and x=="+": 86 | if nextPart is False: 87 | return companion 88 | else: 89 | return str[pos:] 90 | else: 91 | companion+=x 92 | if nextPart is False: 93 | return companion 94 | else: 95 | return "" 96 | 97 | #===================[ ARDENS METHOD ]================================ 98 | 99 | def ardens(x,mode=False): 100 | formalities(x) 101 | str=x #work with a copy 102 | P=str[0] 103 | R=Q="" 104 | if str[2]==P: 105 | R+=getCompanion(str,2) 106 | else: 107 | Q+=getCompanion(str,2,mode=False) 108 | str=getCompanion(str, 2,nextPart=True) 109 | while str!="": 110 | if str[0]==P: 111 | R+=getCompanion(str,0) if R=="" else "+"+getCompanion(str,0) 112 | else: 113 | Q+=getCompanion(str,0,mode=False) if Q=="" else "+"+getCompanion(str,0,mode=False) 114 | str=getCompanion(str, 0,nextPart=True) 115 | 116 | #somehow R gets a dual "++" in its expression at times so correcting it: 117 | while "++" in Q: 118 | Q=Q.replace("++","+") 119 | if Q[0]=="+": 120 | Q=Q[1:] 121 | if Q[len(Q)-1]=="+": 122 | Q=Q[:len(Q)-1] 123 | 124 | # print("P: "+P) 125 | # print("R: "+R) 126 | # print("Q: "+Q) 127 | 128 | #-----[ P=Q+PR => P=QR* ]------------------ 129 | 130 | if mode is True: 131 | return {"P":P,"Q":Q,"R":R} 132 | 133 | if "+" in Q and len(R)>0: 134 | Q="("+Q+")" 135 | if len(R)>1: 136 | R="("+R+")*" 137 | elif len(R)==1: 138 | R+="*" 139 | 140 | 141 | print("RE:"+x) 142 | print("=> "+P+"="+Q+R) 143 | if Q==null_state: 144 | print("=> "+P+"="+R) 145 | 146 | return P+"="+Q+R if Q!=null_state else P+"="+R 147 | 148 | #================================================================ 149 | 150 | # ============================================================================= 151 | # ======= Convert user input equations to code understanding equations ======== 152 | # ============================================================================= 153 | 154 | def convertToOurEqns(): 155 | #IMPORTANT CAUTION !!!: only convert to code eqns in base state(so it has a state at left for each sub-machine part) 156 | for i in range(0,len(state)): 157 | code["state"].append(states[i]) 158 | for i in range(0,len(transition)): 159 | code["transition"].append(transitions[i]) 160 | code["initial_state"]=states[state.index(initial_state)] 161 | code["final_state"]=states[state.index(final_state)] 162 | # Convert equations now 163 | for i in range(0,len(state)): 164 | code['eqns'].update({code['state'][i]:maskEqns(i)}) 165 | 166 | 167 | def maskEqns(index): 168 | #the equations we will work with throughout 169 | #makes the program user input constraint independent 170 | str="="+eqns[state[index]] 171 | for v in range(0,len(state)): 172 | str=str.replace(state[v],states[v]) 173 | flag=False 174 | temp_str="" 175 | for v in range(0,len(str)): 176 | if flag is True: 177 | temp_str+=str[v] 178 | flag=False 179 | continue 180 | if str[v]=='=' or str[v]=='+': 181 | temp_str+=str[v] 182 | flag=True 183 | continue 184 | temp_str+=transitions[transition.index(str[v])] 185 | return temp_str[1:] 186 | 187 | 188 | # ============================================================================= 189 | # #================================= ALL INPUTS =============================== 190 | # ============================================================================= 191 | 192 | #------------------ State Transition Inputs --------------- 193 | def stateInput(): 194 | global state 195 | state=[] 196 | totalStates=int(input("=> How many total distinct states? (max 26) ")) 197 | if totalStates>26 or totalStates<=0: 198 | print("[!]Max limit:26 ...enter again...") if totalStates>26 else print("[!]Atleast one state has to exist in the FSM") 199 | stateInput() 200 | anotherChoice = input("=> Do you want to name the states?\n (by default, states are named = {"+states[:totalStates]+"}) \n Y/N(y/n): ") 201 | for i in range(0,totalStates): 202 | state.append(input("=> State #"+"%s"%(i+1)+": ") if anotherChoice.lower()=="y" else states[i]) 203 | 204 | 205 | 206 | def transitionInput(): 207 | global transition 208 | transition=[] 209 | totalTrans=int(input("=> How many total distinct transitions? (max 9) ")) 210 | if totalTrans>9 or totalTrans<=0: 211 | print("[!]Max limit:9 ...enter again...") if totalTrans>9 else print("[!]Atleast one transition has to exist in the FSM") 212 | transitionInput() 213 | anotherChoice = input("=> Do you want to name the transitions?\n (by default, transitions are named = {"+transitions[:totalTrans]+"}) \n Y/N(y/n): ") 214 | if anotherChoice.lower()=="y": 215 | print("=> Please enter single letter transitions only...") if anotherChoice.lower() == "y" else print("=>") 216 | i=0 217 | while i Transition #"+"%s"%(i+1)+": ") 219 | if(len(temp_var)!=1): 220 | print("[!]Only single digit transitions are to be input.") 221 | i-=1 222 | continue 223 | transition.append(temp_var) 224 | i+=1 225 | else: 226 | for i in range(0,totalTrans): 227 | transition.append(transitions[i]) 228 | #transition.append(input("=> Transition #"+"%s"%(i+1)+": ") if anotherChoice.lower()=="y" else transitions[i]) 229 | 230 | 231 | #------------------ Initial Final States Input ---------------------- 232 | 233 | def initialFinalStateInput(ph,flag=False): 234 | print("=> Which one is "+ph+"?") 235 | print("=>",state) if flag is False else print("=>",state,"(previously: "+(initial_state if ph=="initial state" else final_state)+")") 236 | x=input("=> ") 237 | if x not in state: 238 | print("[!]"+ph+" does not exist in state set...") 239 | return ""+initialFinalStateInput(ph,flag) 240 | else: 241 | return x 242 | 243 | #------------------ RE Eqns Input ------------------------------- 244 | 245 | def eqnInput(): 246 | print("=> Enter state equations:") 247 | for x in state: 248 | eqns.update({x:input(x+"=") if x!=initial_state else null_state+"+"+input(x+"="+null_state+"+")}) 249 | for y in eqns[x]: 250 | if y not in final_state+initial_state+null_state+"+" and y not in arrToStr(state) and y not in arrToStr(transition): 251 | print("[!]Improper equation inserted, re-enter correct one: ("+y+" should not exist in equation)") 252 | reEnterEqn(x) 253 | break 254 | #equation syntax must be: "+..." 255 | if checkEqnSyntax(eqns[x]) is False: 256 | print("[!]Incorrect Regular Expression Syntax, re-enter correct one.") 257 | reEnterEqn(x) 258 | 259 | 260 | 261 | #============================================================================= 262 | 263 | #---------------- User navigation and choices input -------------------------- 264 | 265 | def choiceInput(): 266 | choice=int(input("=> \n=> We now enter equations\n=> Select an option: \n 1: Enter state transition table, or \n 2: Enter state equations manually \n Whats the choice? ")) 267 | if choice not in [1,2]: 268 | print("[!]Incorrect choice, choose correctly now...") 269 | choiceInput() 270 | else: 271 | return choice 272 | 273 | 274 | def changeSomething(flag=True): 275 | global initial_state,final_state 276 | if flag is True: 277 | print("=>\n=> ==============[ The FSM looks like this ]==============") 278 | print("=> States = ",state) 279 | print("=> Transitions = ",transition) 280 | print("=> Initial state = ",initial_state) 281 | print("=> Final state = ",final_state) 282 | 283 | choice=input("=>\n=> Do you want to change something to this? Y/N(y/n): ") 284 | if choice.lower()=='y': 285 | choice=int(input("=> What to change?\n=> 1:Initial State 2:Final State 3:Total states \n=> 4:Total transitions 5:State names 6:Transition names\n=> ")) 286 | if str(choice) in "123456": 287 | if choice==1: 288 | initial_state=initialFinalStateInput("initial state",flag=True) 289 | elif choice==2: 290 | final_state=initialFinalStateInput("final state",flag=True) 291 | elif choice==3: 292 | stateInput() 293 | print("=> States have changed so initial and final state need to be re-entered too...") 294 | initial_state=initialFinalStateInput("initial state",flag=True) 295 | final_state=initialFinalStateInput("final state",flag=True) 296 | elif choice==4: 297 | transitionInput() 298 | elif choice==5: 299 | initial_state=state.index(initial_state) 300 | final_state=state.index(final_state) 301 | for i in range(0,len(state)): 302 | state[i]=input("=> State #"+"%s"%(i+1)+" (originally '"+state[i]+"'): ") 303 | 304 | initial_state=state[initial_state] 305 | final_state=state[final_state] 306 | print("=> \n\n\n=> Change: initial state = "+initial_state) 307 | print("=> Change: final state = "+final_state) 308 | else: 309 | for i in range(0,len(transition)): 310 | transition[i]=input("=> Transition #"+"%s"%(i+1)+" (originally '"+transition[i]+"'): ") 311 | return changeSomething() 312 | else: 313 | print("[!]Improper choice....") 314 | return changeSomething(flag=False) 315 | return "" 316 | 317 | 318 | 319 | # ============================================================================= 320 | # ==================== VALIDATE RE EXPRESSIONS USER HAS ENTERED =============== 321 | # ============================================================================= 322 | 323 | def reEnterEqn(x): 324 | eqns.update({x:input(x+"=") if x!=initial_state else null_state+"+"+input(x+"="+null_state+"+")}) 325 | for y in eqns[x]: 326 | if y not in final_state+initial_state+null_state+"+" and y not in arrToStr(state) and y not in arrToStr(transition): 327 | print("[!]AGAIN INCORRECT: ("+y+" should not exist in equation)") 328 | return reEnterEqn(x) 329 | if checkEqnSyntax(eqns[x]) is False: 330 | print("[!]AGAIN INCORRECT RE Syntax, re-enter correct one.") 331 | return reEnterEqn(x) 332 | return "" 333 | 334 | 335 | def syntaxChecker(arr,substr): 336 | count=0 337 | for t in arr: 338 | if t in substr: 339 | count+=1 340 | if count>1 or substr.count(t)>1: 341 | return [substr,False] 342 | substr=substr.replace(t,"") 343 | if count==0: 344 | return [substr,False] 345 | return [substr,True] 346 | 347 | 348 | def checkEqnSyntax(eqn): 349 | eqn="+"+eqn+"+" 350 | #equation syntax must be: "+..." 351 | i=0 352 | substr="" 353 | while i!=len(eqn)-1: 354 | substr=eqn[(i+1):eqn.index("+",i+1)] 355 | i=eqn.index("+",i+1) 356 | # check first element is state itself only 357 | for v in state: 358 | if v in substr and substr.index(v)!=0: 359 | return False 360 | # check no multiple transition/state exist 361 | if substr==null_state: 362 | continue 363 | if syntaxChecker(state,substr)[1] is False: 364 | return False 365 | substr=syntaxChecker(state,substr)[0] 366 | if syntaxChecker(transition,substr)[1] is False: 367 | return False 368 | if syntaxChecker(transition,substr)[0]!="": 369 | return False 370 | return True 371 | 372 | # ============================================================================= 373 | # ============================== THE MAIN ===================================== 374 | # ============================================================================= 375 | 376 | def main(): 377 | global initial_state,final_state 378 | print("\n========================[ FSM to RE ]========================\n") 379 | 380 | stateInput() 381 | initial_state=initialFinalStateInput("initial state") 382 | final_state=initialFinalStateInput("final state") 383 | transitionInput() 384 | changeSomething() 385 | if choiceInput()==1: 386 | print("In development...\nRight now, enter equations manually...") 387 | eqnInput() 388 | else: 389 | eqnInput() 390 | convertToOurEqns() 391 | # ============================================================================= 392 | 393 | if __name__=='__main__': 394 | main() 395 | 396 | # print("q0q00".index("q0")) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RegEx_Generator_for_FSM 2 | 3 | Program to generate Regular Expressions for some user input finite state machine states and transitions. 4 | 5 | Field of interest - Theory of Computation (TOC) 6 | 7 | ### Aim 8 | 9 | Return back RE equations of all final states of a user provided FSM 10 | 11 | ### User pre-cautions: 12 | 13 | 1.enter only distinct state and transition names 14 | ('q0','q1','q0' -> invalid and error in result) 15 | 2.enter integer values when asked how many states or transitions 16 | (self explanatory, will be fixed later) 17 | 18 | ### The code takes care of: 19 | 20 | 1.proper RE syntax was inserted 21 | 2.no foreign transitions or states are there in local FSM 22 | 3.user receives and stores their own states and transitions variables, making code robust 23 | -------------------------------------------------------------------------------- /_input/input_eqn.py: -------------------------------------------------------------------------------- 1 | #------------------ Initial Final States Input ---------------------- 2 | 3 | def initialFinalStateInput(ph,flag=False): 4 | print("=> Which one is "+ph+"?") 5 | print("=>",state) if flag is False else print("=>",state,"(previously: "+(initial_state if ph=="initial state" else final_state)+")") 6 | x=input("=> ") 7 | if x not in state: 8 | print("[!]"+ph+" does not exist in state set...") 9 | return ""+initialFinalStateInput(ph,flag) 10 | else: 11 | return x 12 | 13 | 14 | 15 | #------------------ RE Eqns Input ------------------------------- 16 | 17 | def eqnInput(): 18 | print("=> Enter state equations:") 19 | for x in state: 20 | eqns.update({x:input(x+"=") if x!=initial_state else null_state+"+"+input(x+"="+null_state+"+")}) 21 | for y in eqns[x]: 22 | if y not in final_state+initial_state+null_state+"+" and y not in arrToStr(state) and y not in arrToStr(transition): 23 | print("[!]Improper equation inserted, re-enter correct one: ("+y+" should not exist in equation)") 24 | reEnterEqn(x) 25 | break 26 | #equation syntax must be: "+..." 27 | if checkEqnSyntax(eqns[x]) is False: 28 | print("[!]Incorrect Regular Expression Syntax, re-enter correct one.") 29 | reEnterEqn(x) 30 | 31 | -------------------------------------------------------------------------------- /_input/reEnter_eqns.py: -------------------------------------------------------------------------------- 1 | 2 | def reEnterEqn(x): 3 | eqns.update({x:input(x+"=") if x!=initial_state else null_state+"+"+input(x+"="+null_state+"+")}) 4 | for y in eqns[x]: 5 | if y not in final_state+initial_state+null_state+"+" and y not in arrToStr(state) and y not in arrToStr(transition): 6 | print("[!]AGAIN INCORRECT: ("+y+" should not exist in equation)") 7 | return reEnterEqn(x) 8 | if checkEqnSyntax(eqns[x]) is False: 9 | print("[!]AGAIN INCORRECT RE Syntax, re-enter correct one.") 10 | return reEnterEqn(x) 11 | return "" 12 | 13 | -------------------------------------------------------------------------------- /driver_funcs/ardens.py: -------------------------------------------------------------------------------- 1 | #===================[ ARDENS METHOD ]================================ 2 | 3 | 4 | def ardens(x,mode=False): 5 | formalities(x) 6 | str=x #work with a copy 7 | P=str[0] 8 | R=Q="" 9 | if str[2]==P: 10 | R+=getCompanion(str,2) 11 | else: 12 | Q+=getCompanion(str,2,mode=False) 13 | str=getCompanion(str, 2,nextPart=True) 14 | while str!="": 15 | if str[0]==P: 16 | R+=getCompanion(str,0) if R=="" else "+"+getCompanion(str,0) 17 | else: 18 | Q+=getCompanion(str,0,mode=False) if Q=="" else "+"+getCompanion(str,0,mode=False) 19 | str=getCompanion(str, 0,nextPart=True) 20 | 21 | #somehow R gets a dual "++" in its expression at times so correcting it: 22 | while "++" in Q: 23 | Q=Q.replace("++","+") 24 | if Q[0]=="+": 25 | Q=Q[1:] 26 | if Q[len(Q)-1]=="+": 27 | Q=Q[:len(Q)-1] 28 | 29 | # print("P: "+P) 30 | # print("R: "+R) 31 | # print("Q: "+Q) 32 | 33 | #-----[ P=Q+PR => P=QR* ]------------------ 34 | 35 | if mode is True: 36 | return {"P":P,"Q":Q,"R":R} 37 | 38 | if "+" in Q and len(R)>0: 39 | Q="("+Q+")" 40 | if len(R)>1: 41 | R="("+R+")*" 42 | elif len(R)==1: 43 | R+="*" 44 | 45 | 46 | print("RE:"+x) 47 | print("=> "+P+"="+Q+R) 48 | if Q==null_state: 49 | print("=> "+P+"="+R) 50 | 51 | return P+"="+Q+R if Q!=null_state else P+"="+R 52 | -------------------------------------------------------------------------------- /driver_funcs/companion.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from main import stateInput 4 | from utils.remove_extra_spaces import formalities 5 | 6 | 7 | def getCompanion(str,index,mode=True,nextPart=False): 8 | #mode:True get companion only, False get state attached to it also 9 | #nextPart:False-return companion, True-return expression ahead of companion 10 | formalities(str) 11 | totalBracesCount=0 12 | pos=index 13 | companion="" 14 | if str[index] in stateInput and mode is True: 15 | index+=1 16 | for x in str[index:]: 17 | if x=="(": 18 | totalBracesCount+=1 19 | elif x==")": 20 | totalBracesCount-=1 21 | pos+=1 22 | if totalBracesCount==0 and x=="+": 23 | if nextPart is False: 24 | return companion 25 | else: 26 | return str[pos:] 27 | else: 28 | companion+=x 29 | if nextPart is False: 30 | return companion 31 | else: 32 | return "" 33 | -------------------------------------------------------------------------------- /driver_funcs/eqn_mask.py: -------------------------------------------------------------------------------- 1 | 2 | from main import stateInput 3 | 4 | 5 | def convertToOurEqns(): 6 | #IMPORTANT CAUTION !!!: only convert to code eqns in base state(so it has a state at left for each sub-machine part) 7 | for i in range(0,len(stateInput)): 8 | code["state"].append(states[i]) 9 | for i in range(0,len(transition)): 10 | code["transition"].append(transitions[i]) 11 | code["initial_state"]=states[state.index(initial_state)] 12 | code["final_state"]=states[state.index(final_state)] 13 | # Convert equations now 14 | for i in range(0,len(state)): 15 | code['eqns'].update({code['state'][i]:maskEqns(i)}) 16 | 17 | 18 | 19 | 20 | def maskEqns(index): 21 | #the equations we will work with throughout 22 | #makes the program user input constraint independent 23 | str="="+eqns[state[index]] 24 | for v in range(0,len(state)): 25 | str=str.replace(state[v],states[v]) 26 | flag=False 27 | temp_str="" 28 | for v in range(0,len(str)): 29 | if flag is True: 30 | temp_str+=str[v] 31 | flag=False 32 | continue 33 | if str[v]=='=' or str[v]=='+': 34 | temp_str+=str[v] 35 | flag=True 36 | continue 37 | temp_str+=transitions[transition.index(str[v])] 38 | return temp_str[1:] 39 | 40 | -------------------------------------------------------------------------------- /globals/global.py: -------------------------------------------------------------------------------- 1 | 2 | null_state = chr(198) 3 | #the lambda of RE 4 | 5 | 6 | #the next 5 variables store values of RE given by User 7 | state=[] 8 | transition=[] 9 | initial_state="" 10 | final_state="" 11 | eqns={} 12 | 13 | 14 | #program uses states of a,b,c,.... and 0,1,2,... transitions to be used 15 | states='abcdefghijklmnopqrstuvwxyz' 16 | transitions='0123456789' 17 | 18 | 19 | #code object stores the same things but masked variations that is used by program 20 | code={ 21 | "eqns":{}, 22 | "state":[], 23 | "transition":[], 24 | "initial_state":"", 25 | "final_state":"" 26 | } 27 | 28 | 29 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Mon Aug 4 17:44:57 2022 4 | @author: Kushal Kumar 5 | """ 6 | 7 | # ============================================================================= 8 | """ 9 | user pre-cautions: 10 | 1.enter only distinct state and transition names 11 | 2.enter integer values when asked how many states or transitions 12 | the code takes care of: 13 | 1.proper RE syntax was inserted 14 | 2.no foreign transitions or states are there in local FSM 15 | 3.user receives and stores their own states and transitions variables, making code robust 16 | """ 17 | 18 | # ============================================================================= 19 | # ======>> PER DEVELOPMENT PROGRESS: 20 | # 4 aug: ardens method 21 | # method to return rest of eqn of a particular state 22 | # 6 aug: state/transition/initial,final state inputs 23 | # regular expression equation inputs 24 | # masking of user defined equations to code executable eqns 25 | # 7 aug: code to check proper RE syntax is maintained on the fly 26 | # user driven dynamicness of updation and changing FSM variables even after inputting 27 | # 28 | # ============================================================================= 29 | # ======>> NEXT DEVELOPMENT PHASE WORKS: 30 | # - no state is left unvisited by any state in state graph of RE eqns 31 | # ============================================================================= 32 | 33 | 34 | 35 | 36 | 37 | from utils import arr_to_string.arrToStr, remove_extra_spaces.formalities 38 | from driver_funcs import ardens.ardens, eqn_mask.convertToOurEqns 39 | from globals.global import null_state, 40 | 41 | 42 | 43 | 44 | 45 | 46 | #================================================================ 47 | 48 | # ============================================================================= 49 | # ======= Convert user input equations to code understanding equations ======== 50 | # ============================================================================= 51 | 52 | 53 | # ============================================================================= 54 | # #================================= ALL INPUTS =============================== 55 | # ============================================================================= 56 | 57 | #------------------ State Transition Inputs --------------- 58 | def stateInput(): 59 | global state 60 | state=[] 61 | totalStates=int(input("=> How many total distinct states? (max 26) ")) 62 | if totalStates>26 or totalStates<=0: 63 | print("[!]Max limit:26 ...enter again...") if totalStates>26 else print("[!]Atleast one state has to exist in the FSM") 64 | stateInput() 65 | anotherChoice = input("=> Do you want to name the states?\n (by default, states are named = {"+states[:totalStates]+"}) \n Y/N(y/n): ") 66 | for i in range(0,totalStates): 67 | state.append(input("=> State #"+"%s"%(i+1)+": ") if anotherChoice.lower()=="y" else states[i]) 68 | 69 | 70 | 71 | def transitionInput(): 72 | global transition 73 | transition=[] 74 | totalTrans=int(input("=> How many total distinct transitions? (max 9) ")) 75 | if totalTrans>9 or totalTrans<=0: 76 | print("[!]Max limit:9 ...enter again...") if totalTrans>9 else print("[!]Atleast one transition has to exist in the FSM") 77 | transitionInput() 78 | anotherChoice = input("=> Do you want to name the transitions?\n (by default, transitions are named = {"+transitions[:totalTrans]+"}) \n Y/N(y/n): ") 79 | if anotherChoice.lower()=="y": 80 | print("=> Please enter single letter transitions only...") if anotherChoice.lower() == "y" else print("=>") 81 | i=0 82 | while i Transition #"+"%s"%(i+1)+": ") 84 | if(len(temp_var)!=1): 85 | print("[!]Only single digit transitions are to be input.") 86 | i-=1 87 | continue 88 | transition.append(temp_var) 89 | i+=1 90 | else: 91 | for i in range(0,totalTrans): 92 | transition.append(transitions[i]) 93 | #transition.append(input("=> Transition #"+"%s"%(i+1)+": ") if anotherChoice.lower()=="y" else transitions[i]) 94 | 95 | 96 | 97 | #============================================================================= 98 | 99 | #---------------- User navigation and choices input -------------------------- 100 | 101 | def choiceInput(): 102 | choice=int(input("=> \n=> We now enter equations\n=> Select an option: \n 1: Enter state transition table, or \n 2: Enter state equations manually \n Whats the choice? ")) 103 | if choice not in [1,2]: 104 | print("[!]Incorrect choice, choose correctly now...") 105 | choiceInput() 106 | else: 107 | return choice 108 | 109 | 110 | def changeSomething(flag=True): 111 | global initial_state,final_state 112 | if flag is True: 113 | print("=>\n=> ==============[ The FSM looks like this ]==============") 114 | print("=> States = ",state) 115 | print("=> Transitions = ",transition) 116 | print("=> Initial state = ",initial_state) 117 | print("=> Final state = ",final_state) 118 | 119 | choice=input("=>\n=> Do you want to change something to this? Y/N(y/n): ") 120 | if choice.lower()=='y': 121 | choice=int(input("=> What to change?\n=> 1:Initial State 2:Final State 3:Total states \n=> 4:Total transitions 5:State names 6:Transition names\n=> ")) 122 | if str(choice) in "123456": 123 | if choice==1: 124 | initial_state=initialFinalStateInput("initial state",flag=True) 125 | elif choice==2: 126 | final_state=initialFinalStateInput("final state",flag=True) 127 | elif choice==3: 128 | stateInput() 129 | print("=> States have changed so initial and final state need to be re-entered too...") 130 | initial_state=initialFinalStateInput("initial state",flag=True) 131 | final_state=initialFinalStateInput("final state",flag=True) 132 | elif choice==4: 133 | transitionInput() 134 | elif choice==5: 135 | initial_state=state.index(initial_state) 136 | final_state=state.index(final_state) 137 | for i in range(0,len(state)): 138 | state[i]=input("=> State #"+"%s"%(i+1)+" (originally '"+state[i]+"'): ") 139 | 140 | initial_state=state[initial_state] 141 | final_state=state[final_state] 142 | print("=> \n\n\n=> Change: initial state = "+initial_state) 143 | print("=> Change: final state = "+final_state) 144 | else: 145 | for i in range(0,len(transition)): 146 | transition[i]=input("=> Transition #"+"%s"%(i+1)+" (originally '"+transition[i]+"'): ") 147 | return changeSomething() 148 | else: 149 | print("[!]Improper choice....") 150 | return changeSomething(flag=False) 151 | return "" 152 | 153 | 154 | 155 | # ============================================================================= 156 | # ============================== THE MAIN ===================================== 157 | # ============================================================================= 158 | 159 | def main(): 160 | global initial_state,final_state 161 | print("\n========================[ FSM to RE ]========================\n") 162 | 163 | stateInput() 164 | initial_state=initialFinalStateInput("initial state") 165 | final_state=initialFinalStateInput("final state") 166 | transitionInput() 167 | changeSomething() 168 | if choiceInput()==1: 169 | print("In development...\nRight now, enter equations manually...") 170 | eqnInput() 171 | else: 172 | eqnInput() 173 | convertToOurEqns() 174 | # ============================================================================= 175 | 176 | if __name__=='__main__': 177 | main() 178 | 179 | # print("q0q00".index("q0")) -------------------------------------------------------------------------------- /utils/arr_to_string.py: -------------------------------------------------------------------------------- 1 | def arrToStr(array): 2 | if len(array)==0: 3 | return "" 4 | return array[0]+(arrToStr(array[1:]) if len(array)>1 else "") 5 | 6 | -------------------------------------------------------------------------------- /utils/eqnSyntax_check.py: -------------------------------------------------------------------------------- 1 | from utils.syntax_check import syntaxChecker 2 | 3 | 4 | def checkEqnSyntax(eqn): 5 | eqn="+"+eqn+"+" 6 | #equation syntax must be: "+..." 7 | i=0 8 | substr="" 9 | while i!=len(eqn)-1: 10 | substr=eqn[(i+1):eqn.index("+",i+1)] 11 | i=eqn.index("+",i+1) 12 | # check first element is state itself only 13 | for v in state: 14 | if v in substr and substr.index(v)!=0: 15 | return False 16 | # check no multiple transition/state exist 17 | if substr==null_state: 18 | continue 19 | if syntaxChecker(state,substr)[1] is False: 20 | return False 21 | substr=syntaxChecker(state,substr)[0] 22 | if syntaxChecker(transition,substr)[1] is False: 23 | return False 24 | if syntaxChecker(transition,substr)[0]!="": 25 | return False 26 | return True 27 | -------------------------------------------------------------------------------- /utils/remove_extra_spaces.py: -------------------------------------------------------------------------------- 1 | 2 | def formalities(str): 3 | if " " in str: 4 | str=str.replace(" ","") 5 | return str 6 | -------------------------------------------------------------------------------- /utils/syntax_check.py: -------------------------------------------------------------------------------- 1 | def syntaxChecker(arr,substr): 2 | count=0 3 | for t in arr: 4 | if t in substr: 5 | count+=1 6 | if count>1 or substr.count(t)>1: 7 | return [substr,False] 8 | substr=substr.replace(t,"") 9 | if count==0: 10 | return [substr,False] 11 | return [substr,True] 12 | --------------------------------------------------------------------------------