Add a Hardware description chapter, that describes the language.
[matthijs/master-project/report.git] / pret-trans.lua
1 -- filename : type-trans.lua
2 -- comment  : Pretty printing of core transformations. Parses a specific
3 --            syntax, consisting of a before / after with a dashed lined in
4 --            between, and some extra conditions to the right of the line.
5 --            Recreates this layout using frames and line commands.
6 -- author   : Matthijs Kooijman, Universiteit Twente, NL
7 -- copyright: Matthijs Kooijman
8 -- license  : None
9
10 local utf = unicode.utf8
11
12 if not buffers                 then buffers                 = { } end
13 if not buffers.visualizers     then buffers.visualizers     = { } end
14 if not buffers.visualizers.trans then buffers.visualizers.trans = { } end
15
16 local commands = {}
17 -- A command to create a horizontal rule.
18 commands.rule = "\\blackrule[height=0.5pt,depth=0pt,width=.45\\textwidth]"
19 -- Pretty printer to use for the stuff before and after the line
20 commands.before_pret = "lam"
21 commands.after_pret = "lam"
22 -- Frame commands to use for the left (before + line + after) and right
23 -- (conditions) parts. Should include an opening {, which will be closed
24 -- automatically.
25 commands.leftframe = "\\framed[offset=0mm,location=middle,strut=no,align=right,frame=off,width=.5\\textwidth]{\\sans"
26 commands.rightframe = "\\framed[offset=0mm,location=middle,strut=no,align=right,frame=off,width=.5\\textwidth]{"
27
28 -- A table to keep the lines in this buffer, so we can process them all at
29 -- once at the end.
30 local lines
31
32 -- Some helper functions
33 local function ltrim(s)
34     return (string.gsub(s, "^%s*", ""))
35 end
36
37 local function rtrim(s)
38     return (string.gsub(s, "%s*$", ""))
39 end
40
41 -- Insert n blank lines
42 local function blanks(n)
43     print("Inserting " .. n .. " blanks")
44     for i = 1,n do
45         buffers.visualizers.default.empty_line()
46     end
47 end
48
49 -- Prettyprint the given lines using the given pretty printer
50 local function prettyprint(ppr, lines)
51     -- Change the current visualizer
52     oldvisualizer = buffers.currentvisualizer
53     buffers.currentvisualizer = 'lam'
54
55     -- Output the lines
56     buffers.hooks.begin_of_buffer('buffer', 'pret-trans-internal')
57     line = 0
58     for i = 1,#lines do
59         _, line = buffers.typeline(lines[i], i, #lines, line)
60     end
61     buffers.hooks.end_of_buffer('buffer', 'pret-trans-internal')
62
63     -- Change the visualizer back
64     buffers.currentvisualizer = oldvisualizer
65 end
66
67 -- Capture all lines, without generating any output
68 function buffers.visualizers.trans.begin_of_buffer(type, name)
69     lines = {}
70 end
71 function buffers.visualizers.trans.begin_of_line(n)
72     -- Don't generate output here
73 end
74 function buffers.visualizers.trans.flush_line(str, nested)
75     table.insert(lines, str)
76     -- Don't generate output here
77 end
78 function buffers.visualizers.trans.end_of_line(n)
79     -- Don't generate output here
80 end
81 function buffers.visualizers.empty_line()
82     table.insert(lines, '')
83     -- Don't generate output here
84 end
85
86 -- We do the actual work here. Process all the lines in the buffer and
87 -- generate output for them.
88 function buffers.visualizers.trans.end_of_buffer()
89     -- Find the horizontal rule, and see how long it is.
90     len = nil
91     for i = 1,#lines do
92         match = utf.match(lines[i], "^%-%-%-*")
93         if match then
94             len = utf.len(match)
95             break
96         end
97     end
98     print("Rule length: " .. len)
99    
100     -- Split the input in three parts. Stuff before the line, stuff
101     -- after the line, stuff to the right of the line.
102     before, after, rights = {}, {}, {}
103     found_line = false
104     for i = 1,#lines do
105         line = lines[i]
106         -- Split the line into a left and right part
107         left = rtrim(utf.sub(line, 1, len))
108         right = ltrim(utf.sub(line, len + 1))
109         if utf.match(left, "^%-%-%-*") then
110             found_line = true
111         else
112             print("Looking at " .. line .. "('" .. left .. "', '" .. right .. "')")
113             if utf.len(left) > 0 then
114                 if not found_line then
115                     table.insert(before, left)
116                 else
117                     table.insert(after, left)
118                 end
119             end
120         end
121         if utf.len(right) > 0 then
122             table.insert(rights, right)
123         end
124     end
125
126     --
127     -- Real output starts here
128     --
129
130     -- Ensure the left and right frames end up next to each other.
131     tex.sprint("\\dontleavehmode")
132
133     -- Open and fill the left frame
134     tex.sprint(commands.leftframe)
135
136     prettyprint('lam', before)
137
138     tex.sprint(commands.rule)
139
140     prettyprint('lam', after)
141
142     -- Close the left frame
143     tex.sprint("}")
144
145     -- Open and fill the right frame
146     tex.sprint(commands.rightframe)
147
148     -- Insert spacer blank lines to align the middle condition with the
149     -- conclusion rule
150     n_blanks = #before - math.ceil((#rights - 1) / 2)
151     n_blanks = math.max(0, n_blanks)
152     blanks(n_blanks)
153
154     -- Print the conditions
155     for i = 1,#rights do
156         tex.sprint(rights[i])
157         buffers.visualizers.default.end_of_line()
158     end
159
160     -- Fill up the remaining space with blanks
161     n_blanks = (#before + 1 + #after) - (n_blanks + #rights)
162     n_blanks = math.max(0, n_blanks)
163     blanks(n_blanks)
164
165     -- Close the right frame 
166     tex.sprint("}")
167     
168     -- Clean up
169     lines = {}
170 end
171
172 -- vim: set sw=4 sts=4 expandtab ai: