diff --git a/latex/devuldertex2latex.py b/latex/devuldertex2latex.py new file mode 100644 index 0000000..4edca10 --- /dev/null +++ b/latex/devuldertex2latex.py @@ -0,0 +1,192 @@ +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() \ No newline at end of file