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) # letstate etats = {} def do_letstate(s, l, toks) : id, x, y = toks nonlocal etats etats[id] = {"id": id, "posx": x, "posy": y, "initial": False, "accepting": False, "label": ""} 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 if "curved" in nature : bend = True else : bend = False 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 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 + "}") | ("\\setstatediam"+"{"+integer+"}") statement = letstate | drawstate | trans | loop | 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()