]> rtime.felk.cvut.cz Git - opencv.git/blob - opencv/doc/latex2sphinx/latexparser.py
Doctests. Parsed-file cache to speed up incremental work
[opencv.git] / opencv / doc / latex2sphinx / latexparser.py
1 import sys
2 import hashlib
3 import cPickle as pickle
4 import os
5
6 from pyparsing import Word, CharsNotIn, Optional, OneOrMore, ZeroOrMore, Group, Forward, ParseException, Literal, Suppress, replaceWith, StringEnd, lineno, QuotedString, White, NotAny, ParserElement, MatchFirst
7
8 class Argument:
9     def __init__(self, s, loc, toks):
10         self.str = toks[1]
11     def __repr__(self):
12         return "[%s]" % self.str
13     def __str__(self):
14         return self.str
15 def argfun(s, loc, toks):
16     return Argument(s, loc, toks)
17
18 class Parameter:
19     def __init__(self, s, loc, toks):
20         self.str = toks[0].asList()
21     def __repr__(self):
22         return '{' + "".join([str(s) for s in self.str]) + '}'
23         return "{%s}" % self.str
24     def __str__(self):
25         return "".join([str(s) for s in self.str])
26 def paramfun(s, loc, toks):
27     return Parameter(s, loc, toks)
28
29 class TexCmd:
30     def __init__(self, s, loc, toks):
31         self.cmd = str(toks[0])[1:]
32         #print 'cmd', self.cmd
33         self.args = toks[1].asList()
34         self.params = toks[2].asList()
35         self.lineno = lineno(loc, s)
36         self.filename = None
37     def __repr__(self):
38         return '\\' + self.cmd + "".join([repr(a) for a in self.args]) + "".join([repr(p) for p in self.params])
39
40 class ZeroOrMoreAsList(ZeroOrMore):
41     def __init__(self, *args):
42         ZeroOrMore.__init__(self, *args)
43         def listify(s, loc, toks):
44             return [toks]
45         self.setParseAction(listify)
46
47 ParserElement.setDefaultWhitespaceChars("\n\t")
48 backslash = chr(92)
49
50 texcmd = Forward()
51 filler = CharsNotIn(backslash + '$')
52 filler2 = CharsNotIn(backslash + '$' + '{}')
53
54 arg = '[' + CharsNotIn("]") + ']'
55 arg.setParseAction(argfun)
56
57 dollarmath = QuotedString('$',  multiline=True, unquoteResults=False)
58 param = Suppress(Literal('{')) + ZeroOrMoreAsList(dollarmath | filler2 | QuotedString('{', endQuoteChar='}', unquoteResults=False) | texcmd) + Suppress(Literal('}'))
59 param.setParseAction(paramfun)
60 def bs(c): return Literal("\\" + c)
61 singles = bs("[") | bs("]") | bs("{") | bs("}") | bs("\\") | bs("&") | bs("_") | bs(",") | bs("#") | bs("\n") | bs(";") | bs("|") | bs("%") | bs("*")
62 texcmd << (singles | Word("\\", "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", min = 2)) + ZeroOrMoreAsList(arg) + ZeroOrMoreAsList(param)
63 def texcmdfun(s, loc, toks):
64     return TexCmd(s, loc, toks)
65 texcmd.setParseAction(texcmdfun)
66
67 #legal = "".join([chr(x) for x in set(range(32, 127)) - set(backslash)])
68 #filler = Word(legal)
69 document = ZeroOrMore(dollarmath | texcmd | filler) + StringEnd().suppress()
70
71 if 0:
72     s = "This is \\\\ test"
73     print s
74     for t in document.parseString(s):
75         if isinstance(t, TexCmd):
76             print '====> cmd=[%s]' % t.cmd, t
77         else:
78             print '====>', t
79     sys.exit(-1)
80
81 selfstr = open( __file__).read()        # Own source as a string.  Used as part of hash.
82 hashbase = hashlib.md5(selfstr)
83
84 def tokenize(filename):
85     f = open(filename, "rt")
86
87     def uncomment(s):
88         if '%' in s and not '\\%' in s:
89             return s[:s.index('%')] + '\n'
90         else:
91             return s
92
93     docstr = "".join([uncomment(l) for l in f])
94     hash = hashbase.copy()
95     hash.update(docstr)
96     cache_filename = os.path.join("parse-cache", hash.hexdigest())
97     try:
98         return pickle.load(open(cache_filename))
99     except IOError:
100         print "parsing"
101         try:
102             r = document.parseString(docstr)
103             for x in r:
104                 if isinstance(x, TexCmd) and not x.filename:
105                     x.filename = filename
106             pickle.dump(r, open(cache_filename, 'w'))
107             return r
108         except ParseException, pe:
109             print 'Fatal problem at %s line %d col %d' % (filename, pe.lineno, pe.col)
110             print pe.line
111             sys.exit(1)
112
113 def latexparser(filename):
114     tokens = tokenize(filename)
115     def expand(t):
116         if isinstance(t, TexCmd) and t.cmd == "input":
117             filename = "../" + str(t.params[0].str[0]) + ".tex"
118             print filename
119             return latexparser(filename)
120         else:
121             return [t]
122     return sum([expand(t) for t in tokens], [])