Commit | Line | Data |
---|---|---|
e63124bc MW |
1 | #! /usr/bin/python |
2 | ||
3 | import os as OS | |
4 | import re as RX | |
5 | import sys as SYS | |
6 | if SYS.version_info >= (3,): | |
7 | from io import StringIO | |
8 | xrange = range | |
9 | else: | |
10 | from cStringIO import StringIO | |
11 | ||
12 | PROG = OS.path.basename(SYS.argv[0]) | |
13 | USAGE = "usage: %s TEMPLATE INPUT TPLOUT OUTPUT" % PROG | |
14 | ## | |
15 | ## The TEMPLATE contains text containing placeholders of the form | |
16 | ## | |
17 | ## ={TAG:PAT} | |
18 | ## | |
19 | ## TAG is some string, and PAT is a Python regular expression. The TEMPLATE | |
20 | ## matches the INPUT if there is some way to replace each placeholder by a | |
21 | ## string matching its PAT such that the two are equal. | |
22 | ## | |
23 | ## The TPLOUT file is a copy of the TEMPLATE file, with each placeholder | |
24 | ## replaced by ={TAG}. If the TEMPLATE matches the INPUT, then the OUTPUT | |
25 | ## equals TPLOUT; otherwise, the program tries to replace as many portions of | |
26 | ## the INPUT which match placeholder PATs as it can, but it doesn't currently | |
27 | ## do an especially good job. | |
28 | ||
29 | if len(SYS.argv) != 5: | |
30 | SYS.stderr.write("%s\n" % USAGE) | |
31 | SYS.exit(2) | |
32 | _, tplfn, infn, toutfn, outfn = SYS.argv | |
33 | ||
34 | tfin = open(tplfn, "r"); tfout = open(toutfn, "w") | |
35 | fin = open(infn, "r"); fout = open(outfn, "w") | |
36 | ||
37 | R_PLCH = RX.compile(r""" | |
38 | = \{ ([^}:]+) : ((?: [^\\}]+ | \\.)*) \} | |
39 | """, RX.S | RX.X) | |
40 | ||
41 | while True: | |
42 | t = tfin.readline(); l = fin.readline() | |
43 | if not (t or l): break | |
44 | ||
45 | lit = []; tag = []; pat = []; pos = 0 | |
46 | for m in R_PLCH.finditer(t): | |
47 | lit.append(t[pos:m.start()]) | |
48 | tag.append(m.group(1)) | |
49 | pat.append(m.group(2)) | |
50 | pos = m.end() | |
51 | lit.append(t[pos:]) | |
52 | n = len(pat) | |
53 | ||
54 | skelsio = StringIO(); gensio = StringIO(); xctsio = StringIO() | |
55 | gensio.write("^"); xctsio.write("^") | |
56 | for i in xrange(n): | |
57 | q = RX.escape(lit[i]) | |
58 | skelsio.write("%s={%s}" % (lit[i], tag[i])) | |
59 | xctsio.write(q + pat[i]) | |
60 | gensio.write(q + "(.*)") | |
c81c35df | 61 | q = RX.escape(lit[n]) |
e63124bc MW |
62 | skelsio.write(lit[n]); skel = skelsio.getvalue() |
63 | xctsio.write(q); xctsio.write("$"); xct = xctsio.getvalue() | |
64 | gensio.write(q); gensio.write("$"); gen = gensio.getvalue() | |
65 | ||
66 | tfout.write(skel) | |
67 | if not l: continue | |
68 | ||
69 | if RX.match(xct, l): fout.write(skel); continue | |
70 | ||
71 | m = RX.match(gen, l) | |
72 | if not m: fout.write(l); continue | |
73 | sio = StringIO() | |
74 | for i in xrange(n): | |
75 | sio.write(lit[i]) | |
76 | if RX.match("^%s$" % pat[i], m.group(i + 1)): sio.write("={%s}" % tag[i]) | |
77 | else: sio.write("!{%s:%s}" % (tag[i], m.group(i + 1))) | |
78 | sio.write(lit[n]) | |
79 | fout.write(sio.getvalue()) | |
80 | ||
81 | tfin.close(); tfout.close() | |
82 | fin.close(); fout.close() |