source: proto/Xerces/parabix2_xerces.py @ 1454

Last change on this file since 1454 was 1454, checked in by ksherdy, 8 years ago

nigel: hack fix for missing end tag symbols in symbol stream

File size: 15.9 KB
Line 
1# -*- coding: utf-8 -*-
2#
3# Parallel XML Parsing with Bitstream Addition
4#
5# Version for Xerces XML Reader
6#   - assumes:  input transcoded to UTF-16,
7#               line break normalization applied,
8#               pseudo-ASCII bit streams
9#
10# Robert D. Cameron
11
12class Basis_bits():     
13        bit_0 = 0
14        bit_1 = 0
15        bit_2 = 0
16        bit_3 = 0
17        bit_4 = 0
18        bit_5 = 0
19        bit_6 = 0
20        bit_7 = 0
21
22
23class u8 ():
24  unibyte = 0
25  prefix = 0
26  prefix2 = 0
27  prefix3 = 0
28  prefix4 = 0
29  suffix = 0
30  badprefix = 0
31  xE0 = 0
32  xED = 0
33  xF0 = 0
34  xF4 = 0
35  xA0_xBF = 0
36  x80_x9F = 0
37  x90_xBF = 0
38  x80_x8F = 0
39  xEF = 0
40  xBF = 0
41  xBE = 0
42  scope22 = 0
43  scope32 = 0
44  scope33 = 0
45  scope42 = 0
46  scope43 = 0
47  scope44 = 0
48  xE0_scope = 0
49  xED_scope = 0
50  xF0_scope = 0
51  xF4_scope = 0
52  xEF_scope = 0
53
54class Lex ():
55        CR = 0
56        LF = 0
57        HT = 0
58        SP = 0
59        CRLF = 0
60        RefStart = 0
61        Semicolon = 0 
62        Colon = 0
63        LAngle = 0
64        RAngle = 0
65        LBracket = 0
66        RBracket = 0
67        Exclam = 0
68        QMark = 0
69        Hyphen = 0
70        Equals = 0
71        SQuote = 0
72        DQuote = 0
73        Slash = 0
74        Hash = 0
75        x = 0
76        ASCII_name_start = 0
77        ASCII_name_char = 0
78        NameScan = 0
79        Digit = 0
80        Hex = 0
81        WS = 0
82
83class Marker ():
84        LAngle = 0
85        Tag_opener = 0
86        Ref_opener = 0
87        CD_closer = 0
88
89class Callouts():
90        Symbol_starts = 0
91        Symbol_ends = 0
92        Transition_marks = 0
93        Nonplain = 0
94
95def Classify_bytes_Validate_utf8(basis_bits, lex, u8): 
96        temp1 = (basis_bits.bit_0 | basis_bits.bit_1);
97        temp2 = (basis_bits.bit_2 &~ basis_bits.bit_3);
98        temp3 = (temp2 &~ temp1);
99        temp4 = (basis_bits.bit_5 &~ basis_bits.bit_4);
100        temp5 = (basis_bits.bit_6 &~ basis_bits.bit_7);
101        temp6 = (temp4 & temp5);
102        lex.RefStart = (temp3 & temp6);
103        temp7 = (basis_bits.bit_2 & basis_bits.bit_3);
104        temp8 = (temp7 &~ temp1);
105        temp9 = (basis_bits.bit_4 &~ basis_bits.bit_5);
106        temp10 = (basis_bits.bit_6 & basis_bits.bit_7);
107        temp11 = (temp9 & temp10);
108        lex.Semicolon = (temp8 & temp11);
109        temp12 = (basis_bits.bit_4 & basis_bits.bit_5);
110        temp13 = (basis_bits.bit_6 | basis_bits.bit_7);
111        temp14 = (temp12 &~ temp13);
112        lex.LAngle = (temp8 & temp14);
113        temp15 = (temp12 & temp5);
114        lex.RAngle = (temp8 & temp15);
115        temp16 = (basis_bits.bit_1 &~ basis_bits.bit_0);
116        temp17 = (basis_bits.bit_3 &~ basis_bits.bit_2);
117        temp18 = (temp16 & temp17);
118        lex.LBracket = (temp18 & temp11);
119        temp19 = (basis_bits.bit_7 &~ basis_bits.bit_6);
120        temp20 = (temp12 & temp19);
121        lex.RBracket = (temp18 & temp20);
122        temp21 = (basis_bits.bit_4 | basis_bits.bit_5);
123        temp22 = (temp19 &~ temp21);
124        lex.Exclam = (temp3 & temp22);
125        temp23 = (temp12 & temp10);
126        lex.QMark = (temp8 & temp23);
127        lex.Hyphen = (temp3 & temp20);
128        lex.Equals = (temp8 & temp20);
129        temp24 = (temp4 & temp10);
130        lex.SQuote = (temp3 & temp24);
131        temp25 = (temp5 &~ temp21);
132        lex.DQuote = (temp3 & temp25);
133        lex.Slash = (temp3 & temp23);
134        temp26 = (temp10 &~ temp21);
135        lex.Hash = (temp3 & temp26);
136        temp27 = (temp16 & temp7);
137        temp28 = (temp9 &~ temp13);
138        lex.x = (temp27 & temp28);
139        temp29 = (temp9 & temp5);
140        lex.Colon = (temp8 & temp29);
141        temp30 = (temp18 & temp23);
142        temp31 = (temp30 | lex.Colon);
143        temp32 = (temp16 &~ basis_bits.bit_2);
144        temp33 = (basis_bits.bit_5 | temp10);
145        temp34 = (basis_bits.bit_4 & temp33);
146        temp35 = (~temp34);
147        temp36 = (temp21 | temp13);
148        temp37 = ((basis_bits.bit_3 & temp35)|(~(basis_bits.bit_3) & temp36));
149        temp38 = (temp32 & temp37);
150        temp39 = (temp31 | temp38);
151        temp40 = (temp16 & basis_bits.bit_2);
152        temp41 = (temp40 & temp37);
153        lex.ASCII_name_start = (temp39 | temp41);
154        temp42 = (temp30 | lex.Hyphen);
155        temp43 = (temp3 & temp15);
156        temp44 = (temp42 | temp43);
157        temp45 = (temp8 &~ temp34);
158        temp46 = (temp44 | temp45);
159        temp47 = (temp46 | temp38);
160        lex.ASCII_name_char = (temp47 | temp41);
161        lex.NameScan = (lex.ASCII_name_char | basis_bits.bit_0);
162        temp48 = (temp1 | basis_bits.bit_2);
163        x00_x1F = (~temp48);
164        temp49 = (basis_bits.bit_2 | basis_bits.bit_3);
165        temp50 = (temp1 | temp49);
166        lex.CR = (temp20 &~ temp50);
167        lex.LF = (temp29 &~ temp50);
168        temp51 = (temp9 & temp19);
169        lex.HT = (temp51 &~ temp50);
170        lex.SP = (temp3 &~ temp36);
171        temp52 = (temp20 | temp29);
172        temp53 = (temp52 | temp51);
173        temp54 = (temp53 &~ temp50);
174        lex.WS = (temp54 | lex.SP);
175        temp55 = (basis_bits.bit_5 | basis_bits.bit_6);
176        temp56 = (basis_bits.bit_4 & temp55);
177        lex.Digit = (temp8 &~ temp56);
178        temp57 = (temp16 &~ temp49);
179        temp58 = (temp57 &~ basis_bits.bit_4);
180        temp59 = (~temp10);
181        temp60 = ((basis_bits.bit_5 & temp59)|(~(basis_bits.bit_5) & temp13));
182        temp61 = (temp58 & temp60);
183        temp62 = (lex.Digit | temp61);
184        temp63 = (temp16 & temp2);
185        temp64 = (temp63 &~ basis_bits.bit_4);
186        temp65 = (temp64 & temp60);
187        lex.Hex = (temp62 | temp65);
188        lex_error = x00_x1F &~ lex.WS
189        if pablo.inFile(lex_error):
190                error_tracker_NoteError("Error: illegal character", lex_error)
191               
192       
193        ### Validate_utf8(basis_bits, u8):
194        u8.unibyte = (~basis_bits.bit_0);
195        u8.suffix = 0
196        u8_error = 0
197        u8_FFFE_FFFF = 0
198        u8anyscope = 0 #local
199        if basis_bits.bit_0:
200                u8.prefix = (basis_bits.bit_0 & basis_bits.bit_1);
201                u8.prefix2 = (u8.prefix &~ basis_bits.bit_2);
202                u8.prefix3 = (u8.prefix & temp2);
203                u8.prefix4 = (u8.prefix & temp7);
204                u8.suffix = (basis_bits.bit_0 &~ basis_bits.bit_1);
205                temp66 = (u8.prefix &~ temp49);
206                temp67 = (temp21 | basis_bits.bit_6);
207                temp68 = (temp66 &~ temp67);
208                temp69 = (basis_bits.bit_5 & temp13);
209                temp70 = (basis_bits.bit_4 | temp69);
210                temp71 = (u8.prefix4 & temp70);
211                u8.badprefix = (temp68 | temp71);
212                u8_error = u8.badprefix
213                u8.scope22 = pablo.Advance(u8.prefix2)
214                u8anyscope = u8.scope22
215                if u8.prefix3 | u8.prefix4:
216                        xE0 = (u8.prefix3 &~ temp36);
217                        xED = (u8.prefix3 & temp20);
218                        xF0 = (u8.prefix4 &~ temp36);
219                        temp72 = (temp4 &~ temp13);
220                        xF4 = (u8.prefix4 & temp72);
221                        u8.xA0_xBF = (u8.suffix & basis_bits.bit_2);
222                        u8.x80_x9F = (u8.suffix &~ basis_bits.bit_2);
223                        u8.x90_xBF = (u8.suffix & temp49);
224                        u8.x80_x8F = (u8.suffix &~ temp49);
225                        xEF = (u8.prefix3 & temp23);
226                        temp73 = (u8.suffix & temp7);
227                        u8.xBF = (temp73 & temp23);
228                        u8.xBE = (temp73 & temp15);
229#
230
231#                       scope3_32 = pablo.Advance32(u8.prefix3)
232#                       scope4_32 = pablo.Advance32(u8.prefix4)
233#                       u8.scope32 = interpose32(u8.prefix3, scope3_32, 1)
234#                       u8.scope33 = interpose32(u8.prefix3, scope3_32, 2)
235#                       u8.scope42 = interpose32(u8.prefix4, scope4_32, 1)
236#                       u8.scope43 = interpose32(u8.prefix4, scope4_32, 2)
237#                       u8.scope44 = interpose32(u8.prefix4, scope4_32, 3)
238#
239                        u8.scope32 = pablo.Advance(u8.prefix3)
240                        u8.scope33 = pablo.Advance(u8.scope32)
241                        u8.scope42 = pablo.Advance(u8.prefix4)
242                        u8.scope43 = pablo.Advance(u8.scope42)
243                        u8.scope44 = pablo.Advance(u8.scope43)
244#
245#                       u8.xE0_scope = pablo.Advance(xE0);
246#                       u8.xED_scope = pablo.Advance(xED);
247#                       u8.xF0_scope = pablo.Advance(xF0);
248#                       u8.xF4_scope = pablo.Advance(xF4);
249                        E0_F0_scope = pablo.Advance(xE0 | xF0)
250                        ED_F4_scope = pablo.Advance(xED | xF4)
251                        u8.xE0_scope = u8.scope32 & E0_F0_scope
252                        u8.xED_scope = u8.scope32 & ED_F4_scope
253                        u8.xF0_scope = u8.scope42 & E0_F0_scope
254                        u8.xF4_scope = u8.scope42 & ED_F4_scope
255                        u8.xEF_scope = pablo.Advance(xEF);
256
257                        u8lastscope = u8.scope22 | u8.scope33 | u8.scope44
258                        u8anyscope = u8lastscope | u8.scope32 | u8.scope42 | u8.scope43
259               
260                        u8error1 = u8.xE0_scope & u8.x80_x9F
261                        u8error2 = u8.xED_scope & u8.xA0_xBF
262                        u8error3 = u8.xF0_scope & u8.x80_x8F
263                        u8error4 = u8.xF4_scope & u8.x90_xBF
264       
265                        u8_error |= u8error1 | u8error2 | u8error3 | u8error4
266
267                        EF_BF_pending = pablo.Advance(u8.xEF_scope & u8.xBF)
268
269                        u8_FFFE_FFFF = (EF_BF_pending & (u8.xBE | u8.xBF))
270                u8mismatch = u8anyscope ^ u8.suffix
271                u8_error |= u8mismatch | u8_FFFE_FFFF
272                if u8_error:
273                        error_tracker_NoteError("UTF-8 error found", (u8_error))
274                       
275       
276def Parse_CtCDPI(lex, marker, callouts):
277        callouts.Symbol_starts = 0
278        callouts.Symbol_ends = 0
279
280
281        CtCDPI_starts = 0
282        CtCDPI_ends = 0
283        ctCDPI_mask = 0
284
285        v = lex.LAngle | lex.Hyphen
286        w = lex.Hyphen | lex.QMark
287        v1 = pablo.Advance(v)
288        w1 = pablo.Advance(w)
289       
290        LAngle_scope = v1 &~ w1  #pablo.Advance(lex.LAngle)
291        PI_opener = LAngle_scope & lex.QMark
292        CtCD_opener= LAngle_scope & lex.Exclam
293        CtCDPI_opener = PI_opener | CtCD_opener
294
295        #DoubleHyphen = 0
296        CD_closer = 0
297        #PI_closer = 0
298       
299        #if lex.Hyphen: DoubleHyphen = pablo.Advance(lex.Hyphen) & lex.Hyphen
300        DoubleHyphen = v1 & w1 & lex.Hyphen
301        if lex.RBracket:
302                DoubleRBracket = pablo.Advance(lex.RBracket) & lex.RBracket
303                CD_closer = pablo.Advance(DoubleRBracket) & lex.RAngle
304        #if lex.QMark: PI_closer = pablo.Advance(lex.QMark) & lex.RAngle
305        PI_closer = w1 & ~v1 & lex.RAngle
306
307        #
308        # Initiate the scan
309        CtCDPI_Cursor = pablo.ScanToFirst(CtCDPI_opener)
310        while CtCDPI_Cursor:
311                CtCDPI_starts |= CtCDPI_Cursor
312                PI_Cursor = CtCDPI_Cursor & PI_opener
313                CD_Ct_Cursor = pablo.Advance(CtCDPI_Cursor & ~PI_Cursor)
314                CD_Cursor = CD_Ct_Cursor & lex.LBracket
315                Ct_Cursor = CD_Ct_Cursor & lex.Hyphen
316                # PI processing
317                if PI_Cursor:
318                        callouts.Symbol_starts |= PI_Cursor
319                        PI_Cursor = pablo.Advance(PI_Cursor)
320                        # Check
321                        # ctCDPI_Callouts.PI_name_starts |= PI_Cursor
322                        PI_name_end = pablo.ScanThru(PI_Cursor, lex.NameScan)
323                        PI_error = PI_Cursor & PI_name_end
324                        PI_error |= pablo.Advance(PI_name_end & ~ lex.WS) & ~ PI_closer
325                        if PI_error:
326                                error_tracker_NoteError("Error in PI syntax", PI_name_end)
327                        callouts.Symbol_ends |= PI_name_end
328                        callouts.Transition_marks |= PI_name_end
329                        PI_Cursor = pablo.ScanTo(PI_name_end, PI_closer)
330                        CtCDPI_ends |= PI_Cursor
331
332                # CDATA section processing
333                if CD_Cursor:
334                        CD_Cursor = pablo.ScanTo(CD_Cursor, CD_closer)
335                        CtCDPI_ends |= CD_Cursor
336
337                # Comment processing
338                if Ct_Cursor:
339                        Ct_Cursor = pablo.Advance(Ct_Cursor) 
340                        Ct_error = Ct_Cursor & ~ lex.Hyphen
341                        # Advance twice past <!--, so that we don't treat <!---
342                        # as being a terminated comment.
343                        Ct_Cursor = pablo.Advance(pablo.Advance(Ct_Cursor))
344                        Ct_Cursor = pablo.Advance(pablo.ScanTo(Ct_Cursor, DoubleHyphen))
345                        Ct_error |= Ct_Cursor & ~ lex.RAngle   
346                        CtCDPI_ends |= Ct_Cursor
347                        if Ct_error:
348                                error_tracker_NoteError("Error in comment syntax", Ct_error)
349
350                # Common processing
351                CtCDPI_Cursor = PI_Cursor | CD_Cursor | Ct_Cursor
352                CtCDPI_Cursor = pablo.ScanTo(CtCDPI_Cursor, CtCDPI_opener)     
353                ctCDPI_mask |= (CtCDPI_ends - CtCDPI_starts) | CtCDPI_ends             
354                # If any of the Comment, CDATA or PI markups are unterminated, it is an error.
355                ctCDPI_error = pablo.atEOF(ctCDPI_mask)
356       
357                if ctCDPI_error:
358                        error_tracker_NoteError("Error in comment, CDATA or processing instruction syntax", ctCDPI_error)
359               
360        callouts.Transition_marks = CtCDPI_starts | CtCDPI_ends
361
362        # Identify the remaining significant markers for XML processing.
363        marker.LAngle = lex.LAngle &~ ctCDPI_mask
364        marker.Tag_opener = LAngle_scope &~ ctCDPI_mask
365        marker.Ref_opener = lex.RefStart &~ ctCDPI_mask
366        marker.CD_closer = CD_closer &~ ctCDPI_mask
367
368def Parse_tags(lex, marker, callouts):
369       
370        # Delimiters for scans.
371        DQuoteDelim = lex.DQuote | lex.LAngle
372        SQuoteDelim = lex.SQuote | lex.LAngle
373        AttListDelim = lex.Slash | lex.RAngle
374
375        # Marks 2nd character of start, empty and end tags
376        callouts.Transition_marks = marker.Tag_opener
377       
378        # Start the parallel parsing by inspecting the character
379        # after the opening "<" of a tag.
380        ElemName_starts = marker.Tag_opener & ~lex.Slash
381        EndTag_marks = marker.Tag_opener & lex.Slash
382       
383        # Start Tag/Empty Element Tag Parsing
384
385        # Advance all cursors by scanning through the tag name.
386        callouts.Symbol_starts |= ElemName_starts
387        elem_name_ends = pablo.ScanThru(ElemName_starts, lex.NameScan)
388        callouts.Symbol_ends = elem_name_ends
389        callouts.Transition_marks |= elem_name_ends
390        # Must have at least one name character for a legal start tag.
391        # Mark any occurrences of null names as errors.
392        ParseError = ElemName_starts & elem_name_ends
393       
394        # After the element name, there may or may not be an attlist.
395        if elem_name_ends & lex.WS:
396                AfterWS = pablo.ScanThru(elem_name_ends, lex.WS)
397                AttListEnd = AfterWS & AttListDelim
398                AttNameStart = AfterWS & ~AttListDelim
399                #
400                # The following loop iterates through attributes within a start tag.
401                # Because all start tags are processed in parallel, the number of
402                # iterations is the maximum number of attributes found in any one
403                # start tag, plus one.
404                while AttNameStart:
405                        ParseError |= AttNameStart &~ lex.NameScan
406                        callouts.Symbol_starts |= AttNameStart
407                        AttNameFollow = pablo.ScanThru(AttNameStart, lex.NameScan)
408                        callouts.Symbol_ends |= AttNameFollow
409                        # Mark the position from which the AttName may be retrieved.
410                        callouts.Transition_marks |= AttNameFollow
411                        # Scan through WS to the expected '=' delimiter.
412                        # EqExpected = pablo.ScanThru(AttNameFollow, lex.WS)
413                        # But use if test to optimize.
414                        if AttNameFollow & lex.WS: 
415                                EqExpected = pablo.ScanThru(AttNameFollow, lex.WS)
416                        else: EqExpected = AttNameFollow
417                        ParseError |= EqExpected &~ lex.Equals
418                        AttValPos = pablo.ScanThru(EqExpected, EqExpected | lex.WS)
419                        callouts.Transition_marks |= AttValPos
420                        DQuoteAttVal = AttValPos & lex.DQuote
421                        SQuoteAttVal = AttValPos & lex.SQuote
422                        DQuoteAttEnd = pablo.ScanTo(DQuoteAttVal, DQuoteDelim &~ DQuoteAttVal)
423                        SQuoteAttEnd = pablo.ScanTo(SQuoteAttVal, SQuoteDelim &~ SQuoteAttVal)
424                        AttValEnd = DQuoteAttEnd | SQuoteAttEnd
425                        ParseError |= (AttValPos | AttValEnd) &~ (lex.DQuote | lex.SQuote)
426                        AttValFollow = pablo.Advance(AttValEnd)
427                        callouts.Transition_marks |= AttValEnd
428                        #  AfterWS = pablo.ScanThru(AttValFollow, lex.WS)
429                        if AttValFollow & lex.WS: 
430                                AfterWS = pablo.ScanThru(AttValFollow, lex.WS)
431                                AttListEnd |= AfterWS & AttListDelim
432                                AttNameStart = AfterWS & ~AttListDelim
433                        else: 
434                                AttListEnd |= AttValFollow & AttListDelim       
435                                AttNameStart = 0
436                                ParseError |= AttValFollow & ~AttListDelim
437        else:
438                # No WS character after ElemName; must be at the end
439                AttListEnd = elem_name_ends & AttListDelim
440                ParseError |= elem_name_ends & ~AttListDelim
441
442        STagEnds = AttListEnd & lex.RAngle
443        # Mark any "/" characters found as the ends of empty element tags.
444        EmptyTag_marks = pablo.Advance(AttListEnd & lex.Slash)
445
446        #  TODO - Check         
447        # ParseError |= tag_Callouts.EmptyTag_marks & ~lex.RAngle
448       
449        ParseError |= EmptyTag_marks & ~lex.RAngle
450
451        # End Tag Parsing
452       
453        #  TODO - Check
454        # EndTagEnds = pablo.ScanThru(tag_Callouts.EndTag_marks, tag_Callouts.EndTag_marks | lex.NameScan)
455        EndTagEnds = pablo.ScanThru(EndTag_marks, EndTag_marks | lex.NameScan)
456        if EndTagEnds & lex.WS:
457                EndTagEnds = pablo.ScanThru(EndTagEnds, lex.WS)
458        ParseError |= EndTagEnds & ~lex.RAngle
459        if ParseError:
460                error_tracker_NoteError("Tag parsing error found", (ParseError))
461
462        callouts.Transition_marks |= STagEnds | EmptyTag_marks | EndTagEnds
463        callouts.Symbol_ends |= pablo.Advance(EndTag_marks) | EndTagEnds
464
465       
466        # "]]>" within tags (in attribute values) is legal
467        marker.CD_closer = marker.CD_closer &~ ((STagEnds | EmptyTag_marks) - ElemName_starts)
468
469def Parse_refs(lex, marker, callouts):
470        # All remaining "&" must be reference start characters; parse them.
471        if marker.Ref_opener:
472                callouts.Symbol_starts |= marker.Ref_opener
473                # ScanThru from next including all Name characters as well as # for
474                # either general or numeric references.   Symbol table will validate.
475                ref_ends = pablo.ScanThru(marker.Ref_opener, lex.NameScan | marker.Ref_opener | lex.Hash)
476                ref_error = ref_ends &~ lex.Semicolon
477                if ref_error:
478                        error_tracker_NoteError("Reference error found", ref_error)
479                callouts.Symbol_ends |= ref_ends
480
481   
482def Prepare_text(lex, u8, marker, callouts):
483        CD_end_error = marker.CD_closer
484        if CD_end_error: 
485                error_tracker_NoteError("Error: ]]> in text", CD_end_error)
486        callouts.Nonplain = u8.prefix | u8.suffix | lex.CR | marker.Ref_opener | marker.LAngle
487     
488   
489def Main(basis_bits, lex, u8, marker, callouts):       
490       
491        # Classify bytes for UTF-8 processing, whitespace and control
492        # processing and XML lexical analysis.
493        # Classify_bytes(basis_bits, lex)
494
495        # Validate UTF-8 multibyte sequences and determine the UTF-8 scope streams
496        # Validate_utf8(basis_bits, u8)
497                               
498        Classify_bytes_Validate_utf8(basis_bits, lex, u8)
499
500        # Parse all comments, CDATA sections and processing instructions.
501        Parse_CtCDPI(lex, marker, callouts)
502               
503        # All remaining '<' must be tag start characters; parse tags.
504        Parse_tags(lex, marker, callouts) 
505
506        # All remaining '&' must be reference start characters; parse them.
507        Parse_refs(lex, marker, callouts)
508       
509        #
510        Prepare_text(lex, u8, marker, callouts)
511
512
Note: See TracBrowser for help on using the repository browser.