210 lignes
		
	
	
		
			7.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			210 lignes
		
	
	
		
			7.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import pyparsing as pyp
 | |
| import io
 | |
| 
 | |
| def automate(s) :
 | |
| 
 | |
|     conversion = lambda v : str(v*4) + "pt"   ## valeur de l'unité de letstate
 | |
| 
 | |
|     pyp.ParserElement.inlineLiteralsUsing(pyp.Suppress)
 | |
|     ident = (pyp.Combine(pyp.Word(pyp.alphas)+pyp.Optional(pyp.Word(pyp.nums)))).setName("ident")
 | |
|     integer = (pyp.Optional(pyp.oneOf(["+", "-"]), default="+")+pyp.Word(pyp.nums)).setParseAction(lambda toks: int(toks[0]+toks[1])).setName("integer")
 | |
|     real = pyp.Combine(pyp.Optional(pyp.oneOf("+ -")) + pyp.Word(pyp.nums) + "." +
 | |
|                pyp.Optional(pyp.Word(pyp.nums))).setName("real").setParseAction(lambda toks: float(toks[0]))
 | |
|     number = real | integer
 | |
| 
 | |
|     maybelabel = "{" + pyp.Optional(pyp.QuotedString(quoteChar="$", escChar="\\", unquoteResults=False) | ident, default=None) + "}"
 | |
| 
 | |
|     # intro
 | |
|     intro = r"\begin{picture}("+ integer + "," + integer + ")"
 | |
|     bounding_box = None
 | |
|     def assign_bb(s, l, toks) :
 | |
|         x, y = toks
 | |
|         nonlocal bounding_box
 | |
|         bounding_box = (x, y)
 | |
|     intro.setParseAction(assign_bb)
 | |
| 
 | |
|     # parfois, le double cercle des états acceptants est réalisé en superposant deux états de diamètres différents
 | |
|     curstatediam = None
 | |
|     def do_setstatediam(toks) :
 | |
|         nonlocal curstatediam
 | |
|         curstatediam = toks[0]
 | |
|     statediam = ("\\setstatediam"+"{"+integer+"}").setParseAction(do_setstatediam)
 | |
| 
 | |
|     # letstate
 | |
|     etats = {}
 | |
|     etats_alias = {}
 | |
|     def do_letstate(s, l, toks) :
 | |
|         id, x, y = toks
 | |
|         nonlocal etats, curstatediam, etats_alias
 | |
|         for ancien in [e for e in etats.values() if e["posx"] == x and e["posy"] == y and e["statediam"] != curstatediam] :
 | |
|             ancien["accepting"] = True
 | |
|             etats_alias[id] = ancien["id"]
 | |
|             return
 | |
|         etats[id] = {"id": id, "posx": x, "posy": y, "initial": False, "accepting": False, "label": "", "statediam" : curstatediam}
 | |
|     letstate = (r"\letstate " + ident + "=(" + integer + "," + integer + ")").setParseAction(do_letstate)
 | |
| 
 | |
|     # catégories d'états
 | |
|     def do_catetat(s, l, toks) :
 | |
|         statut, id, label = toks
 | |
|         nonlocal etats
 | |
|         if "initial" in statut :
 | |
|             etats[id]["initial"] = True
 | |
|         elif "final" in statut :
 | |
|             etats[id]["accepting"] = True
 | |
|         if label is not None :
 | |
|             etats[id]["label"] = label
 | |
|     drawstate = (pyp.oneOf(["\\drawstate","\\drawinitialstate", "\\drawfinalstate"]) + pyp.Optional("["+ident+"]").suppress() + "(" + ident + ")" + maybelabel ).setParseAction(do_catetat)
 | |
| 
 | |
|     # transitions
 | |
|     transitions = []
 | |
|     def do_trans(toks) :
 | |
|         nature, indication, orig, dest, label = toks
 | |
|         nonlocal transitions, etats_alias
 | |
|         if "curved" in nature :
 | |
|             bend = True
 | |
|         else :
 | |
|             bend = False
 | |
|         orig = etats_alias.get(orig, orig)
 | |
|         dest = etats_alias.get(dest, dest)
 | |
|         transitions.append({"orig": orig, "dest": dest, "label": label, "bend": bend, "indication":indication})
 | |
|     trans = (pyp.oneOf(["\\drawcurvedtrans", "\\drawtrans", "\\drawedge"]) + pyp.Optional("["+ident+"]", default=None) + "(" + ident + "," + ident + ")" + maybelabel).setParseAction(do_trans)
 | |
| 
 | |
|     boucles = []
 | |
|     def do_loop(toks) :
 | |
|         indication, etat, label = toks
 | |
|         nonlocal boucles, etats_alias
 | |
|         etat = etats_alias.get(etat, etat)
 | |
|         boucles.append({"indication":indication, "orig":etat, "label":label})
 | |
|     loop = ("\\drawloop" + pyp.Optional("[" + ident + "]", default=None) + "(" + ident + ")" + maybelabel).setParseAction(do_loop)
 | |
| 
 | |
| 
 | |
| 
 | |
|     ignorer = ("\\setprofcurve" + "{" + integer + "}") | ("\\setloopdiam" + "{" + integer + "}")
 | |
| 
 | |
| 
 | |
|     statement = letstate | drawstate | trans | loop | statediam | ignorer.suppress()
 | |
| 
 | |
|     outro = pyp.Suppress(r"\end{picture}")
 | |
| 
 | |
|     corps = pyp.Forward()
 | |
|     corps << pyp.Optional(statement + corps)
 | |
| 
 | |
|     parser = intro + corps + outro
 | |
|     try :
 | |
|         parser.parseString(s)
 | |
|     except pyp.ParseException as e :
 | |
|         print(e)
 | |
|         print(s)
 | |
|         print(e.line)
 | |
|         raise e
 | |
| 
 | |
|     os = io.StringIO()
 | |
|     print(r"\begin{tikzpicture}[shorten >=1pt,node distance=2cm,auto, ->, initial text={}]", file=os)
 | |
|     for id in etats :
 | |
|         state = etats[id]
 | |
|         print(r"\node[state", end="", file=os)
 | |
|         if state["initial"] :
 | |
|             print(", initial", end="", file=os)
 | |
|         if state["accepting"] :
 | |
|             print(", accepting", end="", file=os)
 | |
|         print("] (", state["id"], ") at (", conversion(state["posx"]), ",", conversion(state["posy"]), ") {", state["label"], "};", sep="", file=os)
 | |
|     for t in transitions :
 | |
|         if t["indication"] == "r" :
 | |
|             benddir = " right"
 | |
|         elif t["indication"] == "l" :
 | |
|             benddir = " left"
 | |
|         else :
 | |
|             benddir = " left"
 | |
|         if t["bend"] :
 | |
|             bend = "[bend" + benddir + "]"
 | |
|         else :
 | |
|             bend = ""
 | |
|         print(r"\path (", t["orig"], ") edge", bend, " node {", t["label"], "} (", t["dest"], ");", sep="", file=os)
 | |
|     for t in boucles :
 | |
|         if t["indication"] == "b" :
 | |
|             dir = "below"
 | |
|         else :
 | |
|             dir = "above"
 | |
|         print(r"\path (", t["orig"], ") edge[loop ", dir, "] node {", t["label"], "} (", t["orig"], ");", sep="", file=os)
 | |
|     print(r"\end{tikzpicture}", file=os)
 | |
|     return os.getvalue()
 | |
| 
 | |
| 
 | |
| def traiter_automates(nf_i, nf_o) :
 | |
|     inst = open(nf_i)
 | |
|     outst = open(nf_o, "w")
 | |
|     in_auto = False
 | |
|     while True :
 | |
|         line = inst.readline()
 | |
|         if line is None or line == "" :
 | |
|             break
 | |
|         if line.startswith(r"\begin{picture}") :
 | |
|             auto = line
 | |
|             in_auto = True
 | |
|         elif line.startswith(r"\end{picture}") :
 | |
|             auto += line
 | |
|             outst.write(automate(auto))
 | |
|             auto = ""
 | |
|             in_auto = False
 | |
|         elif in_auto :
 | |
|             auto += line
 | |
|         else :
 | |
|             outst.write(line)
 | |
|     inst.close()
 | |
|     outst.close()
 | |
| 
 | |
| def recup_comment(s) :
 | |
|     spl = s.split("%", 1)
 | |
|     if len(spl) == 1 :
 | |
|         return ""
 | |
|     else :
 | |
|         return "%" + spl[1]
 | |
| 
 | |
| def exsol(nf_i, nf_o) :
 | |
|     inst = open(nf_i)
 | |
|     outst = open(nf_o, "w")
 | |
|     while True :
 | |
|         line = inst.readline()
 | |
|         if line is None or line == "" :
 | |
|             break
 | |
|         elif line.startswith(r"\begin{ex}") :
 | |
|             print(r"\begin{question}" + recup_comment(line), file=outst)
 | |
|         elif line.startswith(r"\begin{sol}") :
 | |
|             print(r"\end{question}", file=outst)
 | |
|             print(r"\begin{corrige}" + recup_comment(line), file=outst)
 | |
|         elif line.startswith(r"\end{sol}") :
 | |
|             print(r"\end{corrige}", file=outst)
 | |
|             inst.readline()  # ignorer la ligne suivante
 | |
|         else :
 | |
|             print(line, end="", file=outst)
 | |
|     inst.close()
 | |
|     outst.close()
 | |
| 
 | |
| def resume(nf_i, nf_o) :
 | |
|     inst = open(nf_i)
 | |
|     outst = open(nf_o, "w")
 | |
|     texte = inst.readlines()
 | |
|     inst.close()
 | |
|     imbrication = 0
 | |
|     for k in range(len(texte)) :
 | |
|         if texte[k].startswith(r"\begin{enumerate}") :
 | |
|             if imbrication == 0 :
 | |
|                 texte[k] = texte[k].replace("enumerate", "enumq")
 | |
|             imbrication += 1
 | |
|         elif texte[k].startswith(r"\end{enumerate}") :
 | |
|             imbrication -= 1
 | |
|             if imbrication == 0 :
 | |
|                 texte[k] = texte[k].replace("enumerate", "enumq")
 | |
| 
 | |
|     k = len(texte) - 1
 | |
|     while k >= 0 :
 | |
|         if texte[k].startswith(r"\begin{enumq}[resume]") :
 | |
|             texte[k] = texte[k].replace(r"\begin{enumq}[resume]", r"\resume{enumq}")
 | |
|             k = k - 1
 | |
|             while not texte[k].startswith(r"\end{enumq}") :
 | |
|                 k = k - 1
 | |
|             texte[k] = texte[k].replace(r"\end{enumq}", r"\suspend{enumq}")
 | |
|         k = k - 1
 | |
|     for l in texte :
 | |
|         print(l, end="", file=outst)
 | |
|     outst.close() | 
