source: proto/PDF/pdf.py @ 5143

Last change on this file since 5143 was 2910, checked in by cameron, 6 years ago

Parallel prescanning in Parse_CommentsLiteralStrings

File size: 14.0 KB
RevLine 
[2667]1# pdf.py
2#
3# (c) 2012 Robert D. Cameron, Ken Herdy, Ben Hull
4# All rights reserved.
5# Licensed to International Characters, Inc. under Academic Free License 3.0
6#
7import sys
8import pablo
9
10class Basis_bits():     
11        bit_0 = 0
12        bit_1 = 0
13        bit_2 = 0
14        bit_3 = 0
15        bit_4 = 0
16        bit_5 = 0
17        bit_6 = 0
18        bit_7 = 0
19
20class Parity():
21        odd = 0
22        even = 0
23
24class Lex ():
25        LParen = 0
26        RParen = 0
27        Backslash = 0
28        Percent = 0
29        Slash = 0
30        Regular = 0
31        LAngle = 0
32        RAngle = 0
33        Hex = 0
34        WS = 0
35        Digit = 0
36        Sign = 0
37        Period = 0
38        EOL = 0
39        RBracket = 0
40        LBracket = 0
41        Hash = 0
42        CR = 0
43        LF = 0
44        Special = 0
45
46
47       
48class Escaped_Callouts ():
49        UELParen = 0
50        UERParen = 0
51        escapes = 0
52        escaped = 0
53
54class Comments_Callouts() :
55        mask = 0
56
57class LiteralStrings_Callouts() :
58        starts = 0
59        ends = 0
60        escapes = 0
61        carriage_returns = 0
62        mask = 0
63        error = 0
64
65class Marker() :
66        mask = 0
67        starts = 0
68        others = 0
69
70class Names_Callouts() :
71        starts = 0
72        follows = 0
73        escapes = 0
74
75class HexStrings_Callouts() :
76        starts = 0
77        ends = 0
78        error = 0
79        hex = 0
80
81class Numeric_Callouts() :
82        starts = 0
83        follows = 0
84        error = 0
85
86class Keywords_Callouts() :
87        starts = 0
88        follows = 0
89       
90class SpecialChars_Callouts() :
91        starts = 0
92        follows = 0
93
94def Classify_bytes(basis_bits, lex): 
95        temp1 = (basis_bits.bit_0 | basis_bits.bit_1)
96        temp2 = (basis_bits.bit_2 &~ basis_bits.bit_3)
97        temp3 = (temp2 &~ temp1)
98        temp4 = (basis_bits.bit_4 &~ basis_bits.bit_5)
99        temp5 = (basis_bits.bit_6 | basis_bits.bit_7)
100        temp6 = (temp4 &~ temp5)
101        lex.LParen = (temp3 & temp6)
102        temp7 = (basis_bits.bit_7 &~ basis_bits.bit_6)
103        temp8 = (temp4 & temp7)
104        lex.RParen = (temp3 & temp8)
105        temp9 = (basis_bits.bit_1 &~ basis_bits.bit_0)
106        temp10 = (basis_bits.bit_3 &~ basis_bits.bit_2)
107        temp11 = (temp9 & temp10)
108        temp12 = (basis_bits.bit_4 & basis_bits.bit_5)
109        temp13 = (temp12 &~ temp5)
110        lex.Backslash = (temp11 & temp13)
111        temp14 = (temp5 &~ temp7)
112        temp15 = (temp4 &~ temp14)
113        temp16 = (temp3 & temp15)
114        temp17 = (basis_bits.bit_2 & basis_bits.bit_3)
115        temp18 = (temp17 &~ temp1)
116        temp19 = (temp18 & temp13)
117        temp20 = (temp16 | temp19)
118        temp21 = (basis_bits.bit_6 &~ basis_bits.bit_7)
119        temp22 = (temp12 & temp21)
120        temp23 = (temp18 & temp22)
121        temp24 = (temp20 | temp23)
122        temp25 = (basis_bits.bit_6 & basis_bits.bit_7)
123        temp26 = (temp4 & temp25)
124        temp27 = (temp11 & temp26)
125        temp28 = (temp24 | temp27)
126        temp29 = (temp12 & temp7)
127        temp30 = (temp11 & temp29)
128        temp31 = (temp28 | temp30)
129        temp32 = (temp9 & temp17)
130        temp33 = (temp32 & temp26)
131        temp34 = (temp31 | temp33)
132        temp35 = (temp32 & temp29)
133        temp36 = (temp34 | temp35)
134        temp37 = (basis_bits.bit_5 &~ basis_bits.bit_4)
135        temp38 = (temp37 & temp7)
136        temp39 = (temp3 & temp38)
137        temp40 = (temp36 | temp39)
138        temp41 = (temp12 & temp25)
139        temp42 = (temp3 & temp41)
140        lex.Special = (temp40 | temp42)
141        lex.Percent = (temp3 & temp38)
142        lex.Period = (temp3 & temp22)
143        lex.LAngle = (temp18 & temp13)
144        lex.RAngle = (temp18 & temp22)
145        lex.LBracket = (temp11 & temp26)
146        lex.RBracket = (temp11 & temp29)
147        lex.Slash = (temp3 & temp41)
148        temp43 = (basis_bits.bit_2 | basis_bits.bit_3)
149        temp44 = (temp1 | temp43)
150        temp45 = (temp4 & temp21)
151        temp46 = (temp29 | temp45)
152        lex.EOL = (temp46 &~ temp44)
153        temp47 = (basis_bits.bit_4 | basis_bits.bit_5)
154        temp48 = (temp47 | temp5)
155        temp49 = (temp44 | temp48)
156        temp50 = (temp13 &~ temp44)
157        temp51 = (temp49 &~ temp50)
158        temp52 = (temp29 &~ temp44)
159        temp53 = (temp51 &~ temp52)
160        temp54 = (temp45 &~ temp44)
161        temp55 = (temp53 &~ temp54)
162        temp56 = (temp8 &~ temp44)
163        temp57 = (temp55 &~ temp56)
164        temp58 = (temp3 &~ temp48)
165        temp59 = (temp57 &~ temp58)
166        lex.WS = (~temp59)
167        temp60 = (basis_bits.bit_5 | basis_bits.bit_6)
168        temp61 = (basis_bits.bit_4 & temp60)
169        lex.Digit = (temp18 &~ temp61)
170        temp62 = (temp29 | temp26)
171        lex.Sign = (temp3 & temp62)
172        temp63 = (temp9 &~ temp43)
173        temp64 = (temp63 &~ basis_bits.bit_4)
174        temp65 = (~temp25)
175        temp66 = ((basis_bits.bit_5 & temp65)|(~(basis_bits.bit_5) & temp5))
176        temp67 = (temp64 & temp66)
177        temp68 = (lex.Digit | temp67)
178        temp69 = (temp9 & temp2)
179        temp70 = (temp69 &~ basis_bits.bit_4)
180        temp71 = (temp70 & temp66)
181        lex.Hex = (temp68 | temp71)
182        temp72 = (temp25 &~ temp47)
183        lex.Hash = (temp3 & temp72)
184        lex.CR = (temp29 &~ temp44)
185        lex.LF = (temp45 &~ temp44)
186        lex.Regular = ~lex.Special&~lex.WS
187
188
189def Parse_Escaped(lex, parity, escaped_Callouts):
190
191  #odd = simd_const_4('a',pablo.EOF_mask) 
192        #even = simd_const_4('5',pablo.EOF_mask)
193
194        odd = parity.odd
195        even = parity.even
196
197        start = lex.Backslash &~ pablo.Advance(lex.Backslash)
198        even_start = start & even
199       
200        even_final = pablo.ScanThru(even_start, lex.Backslash) 
201        escape = even_final & odd
[2910]202        escaped_Char = even & pablo.SpanUpTo(even_start, even_final)
[2667]203       
204        odd_start = start & odd
205        odd_final = pablo.ScanThru(odd_start, lex.Backslash)
206        odd_sut =pablo.SpanUpTo(odd_start, odd_final)
207
208        escape = escape | (odd_final & even)
[2910]209        escaped_Char |= odd & odd_sut
[2667]210       
[2910]211        escaped_Callouts.escapes = escaped_Char
[2667]212        escaped_Callouts.UELParen = lex.LParen &~ escape
213        escaped_Callouts.UERParen = lex.RParen &~ escape
214        escaped_Callouts.escaped = escape
215               
216# Parallel version
217# def Parse_LiteralStrings(LParen, RParen, LiteralStrings_Callouts):
218        # unmatched = RParen
219        # pscan = {}
220        # qscan = {}
221        # LiteralStrings_Callouts.closed={}
222        # i = 0
223        # pscan[0] = pablo.ScanTo(pablo.Advance(LParen), LParen | RParen)
224        # qscan[0] = pablo.ScanTo(pablo.Advance(RParen), LParen | RParen)
225        # LiteralStrings_Callouts.mask = (pscan[0] - (LParen)) | pscan[0]
226       
227        # LiteralStrings_Callouts.closed[i] = pscan[i] & RParen
228        # unclosed = pscan[i] & LParen | qscan[i] & RParen
229        # LiteralStrings_Callouts.error = pscan[i] &~ pablo.EOF_mask
230        # all_closed = LiteralStrings_Callouts.closed[i]
231        # while unclosed:
232                # i += 1
233                # pscan[i] = pablo.ScanTo(pablo.Advance(unclosed & LParen), unclosed)
234                # qscan[i] = pablo.ScanTo(pablo.Advance(unclosed & RParen), unclosed)
235                # LiteralStrings_Callouts.mask|=(pscan[i]-(unclosed & LParen)) | pscan[i]
236                # LiteralStrings_Callouts.closed[i] = pscan[i] & RParen #| qscan[i] & LParen
237                # unclosed = pscan[i] & LParen | qscan[i] & RParen
238                # all_closed |= LiteralStrings_Callouts.closed[i]
239                # LiteralStrings_Callouts.error |= pscan[i] &~ pablo.EOF_mask #| ~pablo.atEOF(qscan[i])
240       
241        # LiteralStrings_Callouts.error |= RParen &~ all_closed
242# def Parse_Comments(Percent, lex, Comments_Callouts) :
243        # end = Pablo.ScanTo(Percent, lex.EOL)
244        # Comments_Callouts.mask = end-Percent
245# def Parse_CommentsLiteralStrings(lex, Escaped_Callouts, Marker, Comments_Callouts, LiteralStrings_Callouts) :
246        # Parse_LiteralStrings(Escaped_Callouts.UELParen, Escaped_Callouts.UERParen, LiteralStrings_Callouts)
247        # while (lex.Percent &~ (LiteralStrings_Callouts.mask | Comments_Callouts.mask)) :
248                # Parse_Comments(lex.Percent&~LiteralStrings_Callouts.mask, lex, Comments_Callouts)
249                # if (LiteralStrings_Callouts.mask & Comments_Callouts.mask) :
250                        # Parse_LiteralStrings(Escaped_Callouts.UELP &~ Comments_Callouts.mask, Escaped_Callouts.UERP &~ Comments_Callouts.mask, LiteralStrings_Callouts)
251                # else :
252                        # break
253        # Marker.mask = Comments_Callouts.mask | LiteralStrings_Callouts.mask
254
255
256def Parse_CommentsLiteralStrings(lex, escaped_Callouts, marker, comments_Callouts, literalStrings_Callouts) :
257        #not entirely sure this code is correct once compiled
258        depth = 0
259        comment_starts=0
260        comment_ends=0
261        marker.starts = 0
262        marker.others = 0
263        literalStrings_Callouts.starts = 0
264        literalStrings_Callouts.ends = 0
265
[2910]266        parens = escaped_Callouts.UELParen | escaped_Callouts.UERParen
267
268        #
269        # Try parallel methods first, to handle normal cases.
270        #
271       
272        # Comments begin with lex.Percent (%) and extend to end of line,
273        # except that % marks in strings do not mark comments.
274        # Observation: no % mark found within the scope of a left paren can
275        # be a comment start delimiter: it is either a % within a string or
276        # an interior % mark within the comment.
277        pscan = pablo.AdvanceThenScanTo(escaped_Callouts.UELParen, parens)
278        instring = pablo.ExclusiveSpan(escaped_Callouts.UELParen, pscan)
279        CtCand = lex.Percent &~ instring
280        qscan = pablo.AdvanceThenScanTo(escaped_Callouts.UERParen & knownNonCtReg, parens & knownNonCtReg)             
281        unmatched = pscan & escaped_Callouts.UELParen | qscan & escaped_Callouts.UERParen
282        if CtCand:
283                line_start = ~pablo.Advance(~lex.EOL)
284                comment1 = pablo.ScanTo(line_start, lex.EOL | CtCand)
285                knownNonCtReg = pablo.SpanUpTo(line_start, comment1)
286                pscan = pscan & knownNonCtReg
287                instring = instring & knownNonCtReg
288        #
289
290        scan_characters = unmatched | CtCand
291
292        #scan_characters = escaped_Callouts.UELParen | escaped_Callouts.UERParen | lex.Percent
[2667]293        cursor = pablo.ScanToFirst(scan_characters)
294        while pablo.inFile(cursor) :
295                comment_cursor = cursor & lex.Percent
[2910]296                string_cursor = cursor & parens
[2667]297                if comment_cursor :
298                        comment_starts |=comment_cursor
299                        comment_cursor = pablo.ScanTo(comment_cursor, lex.EOL)
300                        comment_ends |=comment_cursor
[2910]301                        cursor = pablo.AdvanceThenScanTo(comment_cursor, scan_characters)
[2667]302               
303                if string_cursor :
304                        #There should be a better way to do this
305                        if (string_cursor & escaped_Callouts.UELParen) :
306
307                                inc()
308                        if (string_cursor & escaped_Callouts.UELParen) :
[2910]309                                cursor = pablo.AdvanceThenScanTo(string_cursor, parens)
310                                instring |= pablo.SpanUpTo(string_cursor, parens)
311
[2667]312                        if (string_cursor & escaped_Callouts.UERParen) :
313                                dec()
314                        if (string_cursor & escaped_Callouts.UERParen) :
315                                if is_zero():
[2910]316                                        cursor = pablo.AdvanceThenScanTo(string_cursor, scan_characters)
[2667]317                                if lt_zero():
318                                        literalStrings_Callouts.error|=string_cursor
[2910]319                                        cursor = pablo.AdvanceThenScanTo(string_cursor, scan_characters)
[2667]320                                if ~(is_zero() | lt_zero()):
[2910]321                                        cursor = pablo.AdvanceThenScanTo(string_cursor, parens)
[2667]322                                       
323
324        comments_Callouts.mask = pablo.SpanUpTo(comment_starts, comment_ends)
[2910]325        outerParens = parens &~ instring &~ comments_Callouts.mask
326        literalStrings_Callouts.starts = outerParens & escaped_Callouts.UELParen
327        literalStrings_Callouts.ends = outerParens & escaped_Callouts.UERParen
[2667]328        literalStrings_Callouts.mask = pablo.InclusiveSpan(literalStrings_Callouts.starts,literalStrings_Callouts.ends)
329        literalStrings_Callouts.escapes = escaped_Callouts.escapes & literalStrings_Callouts.mask
330        literalStrings_Callouts.carriage_returns = lex.CR & literalStrings_Callouts.mask &~ escaped_Callouts.escaped
331        marker.mask = comments_Callouts.mask | literalStrings_Callouts.mask
332        marker.starts |= literalStrings_Callouts.starts
333        marker.others |= literalStrings_Callouts.ends | literalStrings_Callouts.escapes | literalStrings_Callouts.carriage_returns
334
335def Parse_Names(lex, marker, names_Callouts) :
336        names_Callouts.starts =lex.Slash&~marker.mask
337        firstCharacter = pablo.Advance(names_Callouts.starts)
338        names_Callouts.follows = pablo.ScanThru(firstCharacter, lex.Regular)
339        names_Callouts.escapes = (pablo.Advance(pablo.Advance(lex.Hash))&pablo.Advance(lex.Hex)&lex.Hex)&pablo.SpanUpTo(names_Callouts.starts, names_Callouts.follows)
340        marker.mask |=names_Callouts.starts|(firstCharacter&~names_Callouts.follows)
341        marker.starts |= names_Callouts.starts
342        marker.others |= names_Callouts.follows | names_Callouts.escapes
343
344
345def Parse_HexStrings(lex, marker, hexStrings_Callouts) :
346        hexStrings_Callouts.starts = lex.LAngle &~marker.mask
347        hexStrings_Callouts.ends = pablo.ScanThru(pablo.Advance(hexStrings_Callouts.starts),lex.Hex|lex.WS)
348        hexStrings_Callouts.error = hexStrings_Callouts.ends &~ lex.RAngle
349        mask = pablo.InclusiveSpan(hexStrings_Callouts.starts,hexStrings_Callouts.ends)
350        hexStrings_Callouts.hex = lex.Hex & mask
351        marker.mask |= mask
352        marker.starts |= hexStrings_Callouts.starts
353        marker.others |= hexStrings_Callouts.ends | hexStrings_Callouts.hex
354
355def Parse_Numeric(lex, marker, numeric_Callouts) :
356        numeric_characters = (lex.Digit | lex.Period | lex.Sign)
357        numeric_Callouts.starts =(numeric_characters &~ pablo.Advance(lex.Regular)) &~ marker.mask
358        numeric_Callouts.follows =pablo.ScanThru(numeric_Callouts.starts, lex.Regular)
359        marker.mask |= numeric_Callouts.starts
360        marker.starts |= numeric_Callouts.starts
361        marker.others |= numeric_Callouts.follows
362        # aftersign = pablo.Advance(numeric_Callouts.starts & lex.Sign) | (numeric_Callouts.starts &~ lex.Sign)
363        # temp = pablo.ScanThru(aftersign, lex.Digit)
364        # afterperiod = pablo.Advance(temp & lex.Period) | (temp &~ lex.Period)
365        # numeric_Callouts.follows = pablo.ScanThru(afterperiod, lex.Digit)
366        # numeric_Callouts.error = numeric_Callouts.follows &~ (lex.WS | lex.Delimiter)
367        # marker.mask |= numeric_Callouts.starts
368
369def Parse_Keywords(lex, marker, keywords_Callouts) :
370        keywords_Callouts.starts = (lex.Regular &~ pablo.Advance(lex.Regular)) &~ marker.mask
371        keywords_Callouts.follows = pablo.ScanThru(keywords_Callouts.starts, lex.Regular)
372        marker.starts |= keywords_Callouts.starts
373        marker.others |= keywords_Callouts.follows
374       
375def Parse_SpecialChars(lex, marker, specialChars_Callouts) :
376        specialChars_Callouts.starts =  (lex.Special) &~ marker.mask
377        specialChars_Callouts.follows = pablo.Advance(specialChars_Callouts.starts)
378        marker.starts |= specialChars_Callouts.starts
379        marker.others |= specialChars_Callouts.follows
380
381def Main(basis_bits, lex, parity, escaped_Callouts):
382                Classify_bytes(basis_bits, lex)
383                # Generate parity odd/even streams
384                Parse_Escaped(lex, parity, escaped_Callouts)
385                Parse_CommentsLiteralStrings(lex, escaped_Callouts, marker, comments_Callouts, literalStrings_Callouts)
386                Parse_Names(lex, marker, names_Callouts)
387                Parse_HexStrings(lex, marker, hexStrings_Callouts)
388                Parse_Numeric(lex, marker, numeric_Callouts)
389                Parse_Keywords(lex, marker, keywords_Callouts)
390                Parse_SpecialChars(lex, marker, specialChars_Callouts)
[2910]391       
Note: See TracBrowser for help on using the repository browser.