chiark / gitweb /
@@@ tvec doc wip
[mLib] / t / template-canonify
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 + "(.*)")
61   q = RX.escape(lit[n])
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()