source: proto/parabix2/parabix2.py @ 2592

Last change on this file since 2592 was 2022, checked in by cameron, 7 years ago

Eliminating elifs

File size: 33.3 KB
Line 
1# -*- coding: utf-8 -*-
2#
3# parabix2.py
4#
5# Parallel XML Parsing with Bitstream Addition
6#
7# - Complete prototype for all bitstream computations in Parabix2
8# - Optimized for compilation
9# - Separate compilation
10
11# Robert D. Cameron, Dan Lin
12# March 24, 2012
13#
14import sys
15import pablo
16import error_tracker
17
18class Basis_bits():     
19        bit_0 = 0
20        bit_1 = 0
21        bit_2 = 0
22        bit_3 = 0
23        bit_4 = 0
24        bit_5 = 0
25        bit_6 = 0
26        bit_7 = 0
27
28
29class U8 ():
30        suffix = 0
31
32class Lex ():
33        CR = 0
34        LF = 0
35        HT = 0
36        SP = 0
37        CRLF = 0
38        RefStart = 0
39        Semicolon = 0 
40        Colon = 0
41        LAngle = 0
42        RAngle = 0
43        LBracket = 0
44        RBracket = 0
45        Exclam = 0
46        QMark = 0
47        Hyphen = 0
48        Equals = 0
49        SQuote = 0
50        DQuote = 0
51        Slash = 0
52        Hash = 0
53        x = 0
54        ASCII_name_start = 0
55        ASCII_name_char = 0
56        NameScan = 0
57        Digit = 0
58        Hex = 0
59        WS = 0
60
61class Marker ():
62        LAngle_scope = 0
63        Ref_opener = 0
64        CD_closer = 0
65
66class CtCDPI_Callouts():
67        Ct_starts = 0
68        Ct_ends = 0
69        CD_starts = 0
70        CD_ends = 0
71        PI_starts = 0
72        PI_name_starts = 0
73        PI_name_ends = 0
74        PI_ends = 0
75
76class Ref_Callouts():
77        GenRef_starts = 0
78        GenRef_ends = 0
79        DecRef_starts = 0
80        DecRef_ends = 0
81        HexRef_starts = 0
82        HexRef_ends = 0
83
84class Tag_Callouts():
85        ElemName_starts = 0
86        ElemName_ends = 0
87        AttName_starts = 0
88        AttName_ends = 0
89        AttVal_starts = 0
90        AttVal_ends = 0
91        AttVal_spans = 0
92        EmptyTag_marks = 0
93        EndTag_marks = 0
94
95class ID_Callouts():
96        pubid_start = 0
97        pubid_end = 0
98        sysid_start = 0
99        sysid_end = 0
100
101class Check_streams():
102        misc_mask = 0
103        non_ascii_name_starts = 0
104        non_ascii_names = 0
105        tag_marks = 0 
106        name_follows = 0 
107        att_refs = 0 
108
109class DTD_Callouts():
110        root_name_start = 0
111        root_name_follow = 0
112        pubid_start = 0
113        pubid_end = 0
114        sysid_start = 0
115        sysid_end = 0
116        PERef_starts = 0
117        PERef_ends = 0
118        PI_starts = 0
119        PI_name_follows = 0
120        PI_ends = 0
121        notation_name_start = 0
122        notation_name_follow = 0
123        notation_pubid_start = 0
124        notation_pubid_end = 0
125        notation_sysid_start = 0
126        notation_sysid_end = 0
127
128
129def Classify_bytes_Validate_utf8(basis_bits, lex, u8): 
130        temp1 = (basis_bits.bit_0 | basis_bits.bit_1);
131        temp2 = (basis_bits.bit_2 &~ basis_bits.bit_3);
132        temp3 = (temp2 &~ temp1);
133        temp4 = (basis_bits.bit_5 &~ basis_bits.bit_4);
134        temp5 = (basis_bits.bit_6 &~ basis_bits.bit_7);
135        temp6 = (temp4 & temp5);
136        lex.RefStart = (temp3 & temp6);
137        temp7 = (basis_bits.bit_2 & basis_bits.bit_3);
138        temp8 = (temp7 &~ temp1);
139        temp9 = (basis_bits.bit_4 &~ basis_bits.bit_5);
140        temp10 = (basis_bits.bit_6 & basis_bits.bit_7);
141        temp11 = (temp9 & temp10);
142        lex.Semicolon = (temp8 & temp11);
143        temp12 = (basis_bits.bit_4 & basis_bits.bit_5);
144        temp13 = (basis_bits.bit_6 | basis_bits.bit_7);
145        temp14 = (temp12 &~ temp13);
146        lex.LAngle = (temp8 & temp14);
147        temp15 = (temp12 & temp5);
148        lex.RAngle = (temp8 & temp15);
149        temp16 = (basis_bits.bit_1 &~ basis_bits.bit_0);
150        temp17 = (basis_bits.bit_3 &~ basis_bits.bit_2);
151        temp18 = (temp16 & temp17);
152        lex.LBracket = (temp18 & temp11);
153        temp19 = (basis_bits.bit_7 &~ basis_bits.bit_6);
154        temp20 = (temp12 & temp19);
155        lex.RBracket = (temp18 & temp20);
156        temp21 = (basis_bits.bit_4 | basis_bits.bit_5);
157        temp22 = (temp19 &~ temp21);
158        lex.Exclam = (temp3 & temp22);
159        temp23 = (temp12 & temp10);
160        lex.QMark = (temp8 & temp23);
161        lex.Hyphen = (temp3 & temp20);
162        lex.Equals = (temp8 & temp20);
163        temp24 = (temp4 & temp10);
164        lex.SQuote = (temp3 & temp24);
165        temp25 = (temp5 &~ temp21);
166        lex.DQuote = (temp3 & temp25);
167        lex.Slash = (temp3 & temp23);
168        temp26 = (temp10 &~ temp21);
169        lex.Hash = (temp3 & temp26);
170        temp27 = (temp16 & temp7);
171        temp28 = (temp9 &~ temp13);
172        lex.x = (temp27 & temp28);
173        temp29 = (temp9 & temp5);
174        lex.Colon = (temp8 & temp29);
175        temp30 = (temp18 & temp23);
176        temp31 = (temp30 | lex.Colon);
177        temp32 = (temp16 &~ basis_bits.bit_2);
178        temp33 = (basis_bits.bit_5 | temp10);
179        temp34 = (basis_bits.bit_4 & temp33);
180        temp35 = (~temp34);
181        temp36 = (temp21 | temp13);
182        temp37 = ((basis_bits.bit_3 & temp35)|(~(basis_bits.bit_3) & temp36));
183        temp38 = (temp32 & temp37);
184        temp39 = (temp31 | temp38);
185        temp40 = (temp16 & basis_bits.bit_2);
186        temp41 = (temp40 & temp37);
187        lex.ASCII_name_start = (temp39 | temp41);
188        temp42 = (temp30 | lex.Hyphen);
189        temp43 = (temp3 & temp15);
190        temp44 = (temp42 | temp43);
191        temp45 = (temp8 &~ temp34);
192        temp46 = (temp44 | temp45);
193        temp47 = (temp46 | temp38);
194        lex.ASCII_name_char = (temp47 | temp41);
195        lex.NameScan = (lex.ASCII_name_char | basis_bits.bit_0);
196        temp48 = (temp1 | basis_bits.bit_2);
197        x00_x1F = (~temp48);
198        temp49 = (basis_bits.bit_2 | basis_bits.bit_3);
199        temp50 = (temp1 | temp49);
200        lex.CR = (temp20 &~ temp50);
201        lex.LF = (temp29 &~ temp50);
202        temp51 = (temp9 & temp19);
203        lex.HT = (temp51 &~ temp50);
204        lex.SP = (temp3 &~ temp36);
205        temp52 = (temp20 | temp29);
206        temp53 = (temp52 | temp51);
207        temp54 = (temp53 &~ temp50);
208        lex.WS = (temp54 | lex.SP);
209        temp55 = (basis_bits.bit_5 | basis_bits.bit_6);
210        temp56 = (basis_bits.bit_4 & temp55);
211        lex.Digit = (temp8 &~ temp56);
212        temp57 = (temp16 &~ temp49);
213        temp58 = (temp57 &~ basis_bits.bit_4);
214        temp59 = (~temp10);
215        temp60 = ((basis_bits.bit_5 & temp59)|(~(basis_bits.bit_5) & temp13));
216        temp61 = (temp58 & temp60);
217        temp62 = (lex.Digit | temp61);
218        temp63 = (temp16 & temp2);
219        temp64 = (temp63 &~ basis_bits.bit_4);
220        temp65 = (temp64 & temp60);
221        lex.Hex = (temp62 | temp65);
222        lex_error = x00_x1F &~ lex.WS
223        if pablo.inFile(lex_error):
224                error_tracker.NoteError("Error: illegal character", lex_error)
225               
226       
227        ### Validate_utf8(basis_bits, u8):
228        unibyte = (~basis_bits.bit_0);
229        suffix = 0
230        u8_error = 0
231        u8_FFFE_FFFF = 0
232        u8anyscope = 0 #local
233        if basis_bits.bit_0:
234                prefix = (basis_bits.bit_0 & basis_bits.bit_1);
235                prefix2 = (prefix &~ basis_bits.bit_2);
236                prefix3 = (prefix & temp2);
237                prefix4 = (prefix & temp7);
238                suffix = (basis_bits.bit_0 &~ basis_bits.bit_1);
239                temp66 = (prefix &~ temp49);
240                temp67 = (temp21 | basis_bits.bit_6);
241                temp68 = (temp66 &~ temp67);
242                temp69 = (basis_bits.bit_5 & temp13);
243                temp70 = (basis_bits.bit_4 | temp69);
244                temp71 = (prefix4 & temp70);
245                badprefix = (temp68 | temp71);
246                u8_error = badprefix
247                scope22 = pablo.Advance(prefix2)
248                u8anyscope = scope22
249                if prefix3 | prefix4:
250                        xE0 = (prefix3 &~ temp36);
251                        xED = (prefix3 & temp20);
252                        xF0 = (prefix4 &~ temp36);
253                        temp72 = (temp4 &~ temp13);
254                        xF4 = (prefix4 & temp72);
255                        xA0_xBF = (suffix & basis_bits.bit_2);
256                        x80_x9F = (suffix &~ basis_bits.bit_2);
257                        x90_xBF = (suffix & temp49);
258                        x80_x8F = (suffix &~ temp49);
259                        xEF = (prefix3 & temp23);
260                        temp73 = (suffix & temp7);
261                        xBF = (temp73 & temp23);
262                        xBE = (temp73 & temp15);
263
264                        scope32 = pablo.Advance(prefix3)
265                        scope33 = pablo.Advance(scope32)
266                        scope42 = pablo.Advance(prefix4)
267                        scope43 = pablo.Advance(scope42)
268                        scope44 = pablo.Advance(scope43)
269
270                        E0_F0_scope = pablo.Advance(xE0 | xF0)
271                        ED_F4_scope = pablo.Advance(xED | xF4)
272                        xE0_scope = scope32 & E0_F0_scope
273                        xED_scope = scope32 & ED_F4_scope
274                        xF0_scope = scope42 & E0_F0_scope
275                        xF4_scope = scope42 & ED_F4_scope
276                        xEF_scope = pablo.Advance(xEF);
277
278                        u8lastscope = scope22 | scope33 | scope44
279                        u8anyscope = u8lastscope | scope32 | scope42 | scope43
280               
281                        u8error1 = xE0_scope & x80_x9F
282                        u8error2 = xED_scope & xA0_xBF
283                        u8error3 = xF0_scope & x80_x8F
284                        u8error4 = xF4_scope & x90_xBF
285       
286                        u8_error |= u8error1 | u8error2 | u8error3 | u8error4
287
288                        EF_BF_pending = pablo.Advance(xEF_scope & xBF)
289
290                        u8_FFFE_FFFF = (EF_BF_pending & (xBE | xBF))
291                u8mismatch = u8anyscope ^ suffix
292                u8_error |= u8mismatch | u8_FFFE_FFFF
293                if u8_error:
294                        error_tracker.NoteError("UTF-8 error found", (u8_error))
295                       
296       
297def Parse_CtCDPI(lex, marker, ctCDPI_Callouts, check_streams):
298        ctCDPI_Callouts.Ct_starts = 0
299        ctCDPI_Callouts.Ct_ends = 0
300        ctCDPI_Callouts.CD_starts = 0
301        ctCDPI_Callouts.CD_ends = 0
302        ctCDPI_Callouts.PI_starts = 0
303        ctCDPI_Callouts.PI_name_starts = 0
304        ctCDPI_Callouts.PI_name_ends = 0
305        ctCDPI_Callouts.PI_ends = 0
306        CtCDPI_starts = 0
307        CtCDPI_ends = 0
308        ctCDPI_mask = 0
309
310        v = lex.LAngle | lex.Hyphen
311        w = lex.Hyphen | lex.QMark
312        v1 = pablo.Advance(v)
313        w1 = pablo.Advance(w)
314       
315        LAngle_scope = v1 &~ w1  #pablo.Advance(lex.LAngle)
316        PI_opener = LAngle_scope & lex.QMark
317        CtCD_opener= LAngle_scope & lex.Exclam
318        CtCDPI_opener = PI_opener | CtCD_opener
319
320        #DoubleHyphen = 0
321        CD_closer = 0
322        #PI_closer = 0
323       
324        #if lex.Hyphen: DoubleHyphen = pablo.Advance(lex.Hyphen) & lex.Hyphen
325        DoubleHyphen = v1 & w1 & lex.Hyphen
326        if lex.RBracket:
327                DoubleRBracket = pablo.Advance(lex.RBracket) & lex.RBracket
328                CD_closer = pablo.Advance(DoubleRBracket) & lex.RAngle
329        #if lex.QMark: PI_closer = pablo.Advance(lex.QMark) & lex.RAngle
330        PI_closer = w1 & ~v1 & lex.RAngle
331
332        #
333        # Initiate the scan
334        CtCDPI_Cursor = pablo.ScanToFirst(CtCDPI_opener)
335        while CtCDPI_Cursor:
336                CtCDPI_starts |= CtCDPI_Cursor
337                PI_Cursor = CtCDPI_Cursor & PI_opener
338                CD_Ct_Cursor = pablo.Advance(CtCDPI_Cursor & ~PI_Cursor)
339                CD_Cursor = CD_Ct_Cursor & lex.LBracket
340                Ct_Cursor = CD_Ct_Cursor & lex.Hyphen
341                DTD_Cursor = CD_Ct_Cursor & lex.NameScan
342                # PI processing
343                if PI_Cursor:
344                        ctCDPI_Callouts.PI_starts |= PI_Cursor
345                        PI_Cursor = pablo.Advance(PI_Cursor)
346                        ctCDPI_Callouts.PI_name_starts |= PI_Cursor
347                        PI_name_end = pablo.ScanThru(PI_Cursor, lex.NameScan)
348                        PI_error = PI_Cursor & PI_name_end
349                        PI_error |= pablo.Advance(PI_name_end & ~ lex.WS) & ~ PI_closer
350                        if PI_error:
351                                error_tracker.NoteError("Error in PI syntax", PI_name_end)
352                        ctCDPI_Callouts.PI_name_ends |= PI_name_end
353                        PI_Cursor = pablo.ScanTo(PI_name_end, PI_closer)
354                        ctCDPI_Callouts.PI_ends |= PI_Cursor
355                        CtCDPI_ends |= PI_Cursor
356
357                # CDATA section processing
358                if CD_Cursor:
359                        ctCDPI_Callouts.CD_starts |= CD_Cursor
360                        CD_Cursor = pablo.ScanTo(CD_Cursor, CD_closer)
361                        ctCDPI_Callouts.CD_ends |= CD_Cursor
362                        CtCDPI_ends |= CD_Cursor
363
364                # Comment processing
365                if Ct_Cursor:
366                        ctCDPI_Callouts.Ct_starts |= Ct_Cursor
367                        Ct_Cursor = pablo.Advance(Ct_Cursor) 
368                        Ct_error = Ct_Cursor & ~ lex.Hyphen
369                        # Advance twice past <!--, so that we don't treat <!---
370                        # as being a terminated comment.
371                        Ct_Cursor = pablo.Advance(pablo.Advance(Ct_Cursor))
372                        Ct_Cursor = pablo.Advance(pablo.ScanTo(Ct_Cursor, DoubleHyphen))
373                        Ct_error |= Ct_Cursor & ~ lex.RAngle   
374                        ctCDPI_Callouts.Ct_ends |= Ct_Cursor
375                        CtCDPI_ends |= Ct_Cursor
376                        if Ct_error:
377                                error_tracker.NoteError("Error in comment syntax", Ct_error)
378                if DTD_Cursor:
379                        #print "DTD"
380                        DTD_Cursor = ParseDTD(DTD_Cursor, DTD_out)
381                        CtCDPI_ends |= DTD_Cursor
382
383                # Common processing
384                CtCDPI_Cursor = PI_Cursor | CD_Cursor | Ct_Cursor | DTD_Cursor
385                CtCDPI_Cursor = pablo.ScanTo(CtCDPI_Cursor, CtCDPI_opener)
386                ctCDPI_mask |= (CtCDPI_ends - CtCDPI_starts) | CtCDPI_ends
387
388                # If any of the Comment, CDATA or PI markups are unterminated, it is an error.
389                ctCDPI_error = pablo.atEOF(ctCDPI_mask)
390               
391                if ctCDPI_error:
392                        error_tracker.NoteError("Error in comment, CDATA or processing instruction syntax", ctCDPI_error)
393               
394        check_streams.misc_mask = pablo.inFile((lex.WS | lex.LAngle | (pablo.Advance(ctCDPI_Callouts.Ct_ends | ctCDPI_Callouts.PI_ends) - (ctCDPI_Callouts.Ct_starts | ctCDPI_Callouts.PI_starts)) | CtCDPI_starts))
395
396        # Identify the remaining significant markers for XML processing.
397        marker.LAngle_scope = LAngle_scope &~ ctCDPI_mask
398        marker.Ref_opener = lex.RefStart &~ ctCDPI_mask
399        marker.CD_closer = CD_closer &~ ctCDPI_mask
400
401def Parse_tags(lex, marker, tag_Callouts):
402       
403        # Delimiters for scans.
404        DQuoteDelim = lex.DQuote | lex.LAngle
405        SQuoteDelim = lex.SQuote | lex.LAngle
406        AttListDelim = lex.Slash | lex.RAngle
407       
408        # Start the parallel parsing by inspecting the character
409        # after the opening "<" of a tag.
410        tag_Callouts.ElemName_starts = marker.LAngle_scope & ~lex.Slash
411        tag_Callouts.EndTag_marks = marker.LAngle_scope & lex.Slash
412       
413        # Start Tag/Empty Element Tag Parsing
414
415        # Advance all cursors by scanning through the tag name.
416        tag_Callouts.ElemName_ends = pablo.ScanThru(tag_Callouts.ElemName_starts, lex.NameScan)
417        # Must have at least one name character for a legal start tag.
418        # Mark any occurrences of null names as errors.
419        ParseError = tag_Callouts.ElemName_starts & tag_Callouts.ElemName_ends
420       
421        # Initialize the accumulators for attribute name and value positions.
422        tag_Callouts.AttName_starts = 0 
423        tag_Callouts.AttName_ends = 0
424        tag_Callouts.AttVal_starts = 0
425        tag_Callouts.AttVal_ends = 0
426
427        # After the element name, there may or may not be an attlist.
428        if tag_Callouts.ElemName_ends & lex.WS:
429                AfterWS = pablo.ScanThru(tag_Callouts.ElemName_ends, lex.WS)
430                AttListEnd = AfterWS & AttListDelim
431                AttNameStart = AfterWS & ~AttListDelim
432                #
433                # The following loop iterates through attributes within a start tag.
434                # Because all start tags are processed in parallel, the number of
435                # iterations is the maximum number of attributes found in any one
436                # start tag, plus one.
437                while AttNameStart:
438                        ParseError |= AttNameStart &~ lex.NameScan
439                        tag_Callouts.AttName_starts |= AttNameStart
440                        AttNameFollow = pablo.ScanThru(AttNameStart, lex.NameScan)
441                        tag_Callouts.AttName_ends |= AttNameFollow
442                        # Scan through WS to the expected '=' delimiter.
443                        # EqExpected = pablo.ScanThru(AttNameFollow, lex.WS)
444                        # But use if test to optimize.
445                        if AttNameFollow & lex.WS: 
446                                EqExpected = pablo.ScanThru(AttNameFollow, lex.WS)
447                        else: EqExpected = AttNameFollow
448                        ParseError |= EqExpected &~ lex.Equals
449                        AttValPos = pablo.ScanThru(EqExpected, EqExpected | lex.WS)
450                        tag_Callouts.AttVal_starts |= AttValPos
451                        DQuoteAttVal = AttValPos & lex.DQuote
452                        SQuoteAttVal = AttValPos & lex.SQuote
453                        DQuoteAttEnd = pablo.ScanTo(DQuoteAttVal, DQuoteDelim &~ DQuoteAttVal)
454                        SQuoteAttEnd = pablo.ScanTo(SQuoteAttVal, SQuoteDelim &~ SQuoteAttVal)
455                        AttValEnd = DQuoteAttEnd | SQuoteAttEnd
456                        ParseError |= (AttValPos | AttValEnd) &~ (lex.DQuote | lex.SQuote)
457                        AttValFollow = pablo.Advance(AttValEnd)
458                        tag_Callouts.AttVal_ends |= AttValFollow
459                        #  AfterWS = pablo.ScanThru(AttValFollow, lex.WS)
460                        if AttValFollow & lex.WS: 
461                                AfterWS = pablo.ScanThru(AttValFollow, lex.WS)
462                                AttListEnd |= AfterWS & AttListDelim
463                                AttNameStart = AfterWS & ~AttListDelim
464                        else: 
465                                AttListEnd |= AttValFollow & AttListDelim       
466                                AttNameStart = 0
467                                ParseError |= AttValFollow & ~AttListDelim
468        else:
469                # No WS character after ElemName; must be at the end
470                AttListEnd = tag_Callouts.ElemName_ends & AttListDelim
471                ParseError |= tag_Callouts.ElemName_ends & ~AttListDelim
472
473        STagEnds = AttListEnd & lex.RAngle
474        # Mark any "/" characters found as the ends of empty element tags.
475        tag_Callouts.EmptyTag_marks = pablo.Advance(AttListEnd & lex.Slash)
476       
477        ParseError |= tag_Callouts.EmptyTag_marks & ~lex.RAngle
478
479        # End Tag Parsing
480
481        EndTagEnds = pablo.ScanThru(tag_Callouts.EndTag_marks, tag_Callouts.EndTag_marks | lex.NameScan)
482        if EndTagEnds & lex.WS:
483                EndTagEnds = pablo.ScanThru(EndTagEnds, lex.WS)
484        ParseError |= EndTagEnds & ~lex.RAngle
485        if ParseError:
486                error_tracker.NoteError("Tag parsing error found", (ParseError))
487               
488               
489        # Attribute value spans
490        tag_Callouts.AttVal_spans = tag_Callouts.AttVal_ends - tag_Callouts.AttVal_starts
491       
492#
493#  Parse a public/system ID of one of the form
494#  'PUBLIC' S pubid_literal:quoted_string S sysid_literal:quoted_string |
495#  'PUBLIC' S pubid_literal:quoted_string S?|
496#  'SYSTEM' S sysid_literal:quoted_string
497#  Form 2 is permitted only if require_system_id = 0
498#  (Note that the system literal is optional in NOTATION declarations.)
499#  Generate callout.{pubid_start, pubid_end, sysid_start, sysid_end, end_marker}
500def ParseExternalID(input_marker, require_system_id, callout):
501        public_marker = pablo.match('PUBLIC', input_marker)
502        system_marker = pablo.match('SYSTEM', input_marker)
503        no_marker = input_marker &~ (public_marker | system_marker)
504        if no_marker:
505                error_tracker.NoteError('ExpectedSystemOrPublicId', no_marker)
506        if public_marker:
507                marker = pablo.AdvancebyPos(input_marker, 6)
508                if marker &~ lex.WS:
509                        error_tracker.NoteError('ExpectedWhitespace', marker)
510                callout.pubid_start = pablo.ScanThru(marker, lex.WS)
511                if callout.pubid_start &~ (lex.DQuote | lex.SQuote):
512                        error_tracker.NoteError('ExpectedQuotedString', callout.pubid_start)
513                dq = callout.pubid_start & lex.DQuote
514                sq = callout.pubid_start & lex.SQuote
515                callout.pubid_end = pablo.ScanTo(dq, lex.DQuote &~ dq) | pablo.ScanTo(sq, lex.SQuote &~ sq)
516                if pablo.atEOF(callout.pubid_end): 
517                        error_tracker.NoteError('UnterminatedDOCTYPE', callout.pubid_end)
518                m1 = pablo.Advance(callout.pubid_end)
519                marker = pablo.ScanThru(m1, lex.WS)
520                if marker & (lex.DQuote | lex.SQuote):
521                        if marker & m1:
522                                error_tracker.NoteError('ExpectedWhitespace', marker)
523                        callout.sysid_start = marker
524                        dq = marker & lex.DQuote
525                        sq = marker & lex.SQuote
526                        marker = pablo.ScanTo(dq, lex.DQuote &~ dq) | pablo.ScanTo(sq, lex.SQuote & ~sq)
527                        if pablo.atEOF(marker): 
528                                error_tracker.NoteError('UnterminatedDOCTYPE', marker)
529                        callout.sysid_end = marker
530                else:
531                        if require_system_id:
532                                error_tracker.NoteError('ExpectedQuotedString', marker)
533        if system_marker:
534                marker = pablo.AdvancebyPos(input_marker, 6)
535                if marker &~ lex.WS:
536                        error_tracker.NoteError('ExpectedWhitespace', marker)
537                callout.sysid_start = pablo.ScanThru(marker, lex.WS)
538                if callout.sysid_start &~ (lex.DQuote | lex.SQuote):
539                        error_tracker.NoteError('ExpectedQuotedString', callout.sysid_start)
540                dq = callout.sysid_start & lex.DQuote
541                sq = callout.sysid_start & lex.SQuote
542                marker = pablo.ScanTo(dq, lex.DQuote &~ dq) | pablo.ScanTo(sq, lex.SQuote &~ sq)
543                if pablo.atEOF(marker): 
544                        error_tracker.NoteError('UnterminatedDOCTYPE', marker)
545                callout.sysid_end = marker
546        callout.end_marker = marker
547
548
549def ParseDTD(marker, DTD_out):
550        if ~pablo.match('DOCTYPE', marker) & marker:
551                #NoteXercesXMLErr(ExpectedCommentOrCDATA, marker)
552                return marker
553        marker = pablo.AdvancebyPos(marker, 7)
554       
555        if marker &~ lex.WS:
556                error_tracker.NoteError('ExpectedWhitespace', marker)
557        DTD_out.root_name_start = pablo.ScanThru(marker, lex.WS)
558        DTD_out.root_name_follow = pablo.ScanThru(DTD_out.root_name_start, lex.NameScan)
559        if DTD_out.root_name_start & DTD_out.root_name_follow:
560                error_tracker.NoteError('NoRootElemInDOCTYPE', DTD_out.root_name_start)
561        marker = pablo.ScanThru(DTD_out.root_name_follow, lex.WS)
562        if marker & lex.NameScan:
563                require_system_id = 1
564                ParseExternalID(marker, require_system_id, id_out)
565                DTD_out.pubid_start = id_out.pubid_start
566                DTD_out.pubid_end = id_out.pubid_end
567                DTD_out.sysid_start = id_out.sysid_start
568                DTD_out.sysid_end = id_out.sysid_end
569                marker = id_out.end_marker
570                marker = pablo.ScanThru(marker, id_out.end_marker | lex.WS)
571        # Now must be at "[" for internal subset or ">", if none.
572        if pablo.match('[', marker):
573                marker = pablo.ScanThru(marker, marker | lex.WS)
574                # Now enter the loop to parse the internal ENTITY, ELEMENT,
575                # ATTLIST, NOTATION, PI, Comment and PErefs.
576                while marker & lex.LAngle | pablo.match('%', marker):
577                        if pablo.match('%', marker):
578                                DTD_out.PERef_starts |= marker
579                                name_follow = Pablo.ScanThru(marker, marker | lex.NameScan)
580                                if name_follow &~ lex.Semicolon:
581                                        error_tracker.NoteError('UnterminatedEntityRef', name_follow)
582                                DTD_out.PERef_ends |= name_follow
583
584                        if marker & lex.LAngle:
585                                marker = pablo.Advance(marker)
586                                if marker & lex.QMark:
587                                        DTD_out.PI_starts |= marker
588                                        PI_name_follow = pablo.ScanThru(marker, lex.NameScan)
589                                        PI_error = marker & PI_name_end
590                                        if PI_error:
591                                                error_tracker.NoteError('PINameExpected', PI_name_follow)
592                                        DTD_out.PI_name_follows |= PI_name_follow
593                                        PI_error = pablo.Advance(PI_name_follow & ~ lex.WS) & ~ PI_closer
594                                        if PI_error:
595                                                error_tracker.NoteError('UnterminatedPI', PI_error)
596                                        marker = pablo.ScanTo(PI_name_follow, PI_closer)
597                                        if pablo.atEOF(marker):
598                                                error_tracker.NoteError('UnterminatedPI', marker)
599                                        DTD_out.PI_ends |= marker
600                                if pablo.match('!--', marker):
601                                        # Advance 4 to avoid match a double hyphen too early.
602                                        marker = pablo.Advance(pablo.ScanTo(pablo.AdvancebyPos(marker, 4), (pablo.Advance(lex.Hyphen)&lex.Hyphen)))
603                                        if pablo.atEOF(marker):
604                                                error_tracker.NoteError('UnterminatedComment', marker)
605                                        if marker & ~ lex.RAngle:
606                                                error_tracker.NoteError('IllegalSequenceInComment', marker)
607                                if pablo.match('!ENTITY', marker):
608                                        #print "ENTITY"
609                                        is_PE_entity = 0
610                                        marker = pablo.AdvancebyPos(marker, 7)
611                                        if marker &~ lex.WS:
612                                                error_tracker.NoteError('ExpectedWhitespace', marker)
613                                        marker = pablo.ScanThru(marker, lex.WS)
614                                        if pablo.match('%', marker):
615                                                is_PE_entity = 1
616                                                marker = pablo.Advance(marker)
617                                                if marker &~ lex.WS:
618                                                        error_tracker.NoteError('ExpectedWhitespace', marker)
619                                        entity_name_follow = pablo.ScanThru(marker, lex.NameScan)
620                                        if entity_name_follow & marker:
621                                                error_tracker.NoteError('ExpectedPEName', marker)
622                                        if entity_name_follow &~ lex.WS:
623                                                error_tracker.NoteError('ExpectedWhitespace', marker)
624                                        entity_value_start = pablo.ScanThru(entity_name_follow, lex.WS)
625                                        if entity_value_start & (lex.DQuote | lex.SQuote):
626                                                dq = entity_value_start & lex.DQuote
627                                                sq = entity_value_start & lex.SQuote
628                                                entity_value_end = pablo.ScanTo(dq, lex.DQuote &~ dq) | pablo.ScanTo(sq, lex.SQuote &~ sq)
629                                                marker = entity_value_end
630                                        else:
631                                                require_system_id = 1
632                                                ParseExternalID(entity_value_start, require_system_id, id_out)
633                                                m1 = pablo.Advance(id_out.end_marker)
634                                                marker = pablo.ScanThru(m1, lex.WS)
635                                                if pablo.match('NDATA', marker):
636                                                        if marker & m1:
637                                                                error_tracker.NoteError('ExpectedWhitespace', marker)
638                                                        if is_PE_entity:
639                                                                error_tracker.NoteError('NDATANotValidForPE', marker)
640                                                        marker = pablo.AdvancebyPos(marker, 5)
641                                                        if marker &~ lex.WS:
642                                                                error_tracker.NoteError('ExpectedWhitespace', marker)
643                                                        notation_name_start = pablo.ScanThru(marker, lex.WS)
644                                                        notation_name_follow =  pablo.ScanThru(notation_name_start, lex.NameScan)
645                                                        if notation_name_start & notation_name_follow:
646                                                                error_tracker.NoteError('ExpectedNotationName', notation_name_start)
647                                                        marker = notation_name_follow
648                                        marker = pablo.ScanThru(marker, lex.WS)
649                                        if marker &~ lex.RAngle:
650                                                error_tracker.NoteError('UnterminatedEntityDecl', marker)
651                                       
652                                if pablo.match('!ELEMENT', marker):
653                                        marker = pablo.AdvancebyPos(marker, 8)
654                                        if marker &~ lex.WS:
655                                                error_tracker.NoteError('ExpectedWhitespace', marker)
656                                        marker = pablo.ScanThru(marker, lex.WS)
657                                        elem_name_follow = pablo.ScanThru(marker, lex.NameScan)
658                                        if elem_name_follow & marker:
659                                                error_tracker.NoteError('ExpectedElemName', marker)
660                                        if elem_name_follow &~ lex.WS:
661                                                error_tracker.NoteError('ExpectedWhitespace', marker)
662                                        marker = pablo.ScanTo(elem_name_follow, lex.RAngle)
663                                       
664                                if pablo.match('!ATTLIST', marker):
665                                        marker = pablo.AdvancebyPos(marker, 8)
666                                        if marker &~ lex.WS:
667                                                error_tracker.NoteError('ExpectedWhitespace', marker)
668                                        marker = pablo.ScanThru(marker, lex.WS)
669                                        att_name_follow = pablo.ScanThru(marker, lex.NameScan)
670                                        if att_name_follow & marker:
671                                                error_tracker.NoteError('ExpectedAttName', marker)
672                                        #AttDef                                         
673                                        AttDef_start = att_name_follow
674                                        marker = pablo.ScanThru(AttDef_start, lex.WS)
675                                        while marker & ~lex.RAngle:
676                                                if AttDef_start &~ lex.WS:
677                                                        error_tracker.NoteError('ExpectedWhitespace', marker) 
678                                                attdef_name_follow = pablo.ScanThru(marker, lex.NameScan)
679                                                if attdef_name_follow & marker:
680                                                        error_tracker.NoteError('ExpectedAttDefName', marker)
681                                                if attdef_name_follow &~ lex.WS:
682                                                        error_tracker.NoteError('ExpectedWhitespace', marker)
683                                                marker = pablo.ScanThru(attdef_name_follow, lex.WS)
684                                                #AttType-StringType
685                                                if pablo.match('CDATA', marker):
686                                                        marker = pablo.AdvancebyPos(marker, 5)
687                                                #AttType-TokenizedType
688                                                elif pablo.match('ID', marker):
689                                                        marker = pablo.AdvancebyPos(marker, 2)
690                                                elif pablo.match('IDREF', marker):
691                                                        marker = pablo.AdvancebyPos(marker, 5)
692                                                elif pablo.match('IDREFS', marker):
693                                                        marker = pablo.AdvancebyPos(marker, 6)
694                                                elif pablo.match('ENTITY', marker):
695                                                        marker = pablo.AdvancebyPos(marker, 6)
696                                                elif pablo.match('ENTITIES', marker):
697                                                        marker = pablo.AdvancebyPos(marker, 8)
698                                                elif pablo.match('NMTOKENS', marker):
699                                                        marker = pablo.AdvancebyPos(marker, 8)
700                                                elif pablo.match('NMTOKEN', marker):
701                                                        marker = pablo.AdvancebyPos(marker, 7)
702                                                #AttType-EnumeratedType-Notaion
703                                                elif pablo.match('NOTATION', marker):
704                                                        marker = pablo.AdvancebyPos(marker, 8)
705                                                        if marker &~ lex.WS:
706                                                                error_tracker.NoteError('ExpectedWhitespace', marker)
707                                                        marker = pablo.ScanThru(marker, lex.WS)
708                                                        if pablo.match('(', marker):
709                                                                marker = pablo.Advance(marker)
710                                                        else:
711                                                                error_tracker.NoteError('ExpectedParentheses', marker)
712                                                        marker = pablo.ScanThru(marker, lex.WS)
713                                                        notation_name_follow = pablo.ScanThru(marker, lex.NameScan)
714                                                        if notation_name_follow & marker:
715                                                                error_tracker.NoteError('ExpectedNotationName', marker)
716                                                        marker = pablo.ScanThru(notation_name_follow, lex.WS)
717                                                        while (~pablo.match(')', marker)) & marker:
718                                                                if pablo.match('|', marker):
719                                                                        marker = pablo.ScanThru(marker, marker | lex.WS)
720                                                                        notation_name_follow = pablo.ScanThru(marker, lex.NameScan)
721                                                                        if notation_name_follow & marker:
722                                                                                error_tracker.NoteError('ExpectedNotationName', marker)
723                                                                        marker = notation_name_follow
724                                                                else:
725                                                                        error_tracker.NoteError('ExpectedBar', marker)
726                                                                marker = pablo.ScanThru(marker, lex.WS)
727                                                #AttType-EnumeratedType-Enumeration
728                                                elif pablo.match('(', marker):
729                                                        marker = pablo.ScanThru(marker, marker | lex.WS)
730                                                        nmtoken_follow = pablo.ScanThru(marker, lex.NameScan)
731                                                        if nmtoken_follow & marker:
732                                                                error_tracker.NoteError('ExpectedNmtoken', marker)
733                                                        marker = pablo.ScanThru(nmtoken_follow, lex.WS)
734                                                        while pablo.match('|', marker):
735                                                                marker = pablo.ScanThru(marker, marker | lex.WS)
736                                                                nmtoken_follow = pablo.ScanThru(marker, lex.NameScan)
737                                                                if nmtoken_follow & marker:
738                                                                        error_tracker.NoteError('ExpectedNmtoken', marker)
739                                                                marker = pablo.ScanThru(nmtoken_follow, lex.WS)
740                                                        if pablo.match(')', marker):
741                                                                marker = pablo.Advance(marker)
742                                                        else:
743                                                                error_tracker.NoteError('ExpectedParentheses', marker)
744                                                else:
745                                                        error_tracker.NoteError('ExpectedAttType', marker)     
746                                                #DefaultDecl   
747                                                if marker &~ lex.WS:
748                                                        print 'aaaaaaaaaaaaa'
749                                                        error_tracker.NoteError('ExpectedWhitespace', marker)
750                                                marker = pablo.ScanThru(marker, lex.WS)
751                                                if pablo.match('#REQUIRED', marker):
752                                                        marker = pablo.AdvancebyPos(marker, 9)
753                                                elif pablo.match('#IMPLIED', marker):
754                                                        marker = pablo.AdvancebyPos(marker, 8)
755                                                elif pablo.match('#FIXED', marker):
756                                                        marker = pablo.AdvancebyPos(marker, 6)
757                                                elif marker & (lex.DQuote | lex.SQuote):
758                                                        dq = marker & lex.DQuote
759                                                        sq = marker & lex.SQuote
760                                                        marker = pablo.ScanTo(dq, lex.DQuote &~ dq) | pablo.ScanTo(sq, lex.SQuote &~ sq)
761                                                        marker = pablo.Advance(marker)
762                                                else:
763                                                        error_tracker.NoteError('ExpectedDefaultDecl', marker)
764                                                AttDef_start = marker
765                                                marker = pablo.ScanThru(AttDef_start, lex.WS)
766                               
767                                if pablo.match('!NOTATION', marker):
768                                        marker = pablo.AdvancebyPos(marker, 9)
769                                        if marker &~ lex.WS:
770                                                error_tracker.NoteError('ExpectedWhitespace', marker)
771                                        DTD_out.notation_name_start |= pablo.ScanThru(marker, lex.WS)
772                                        DTD_out.notation_name_follow |= pablo.ScanThru(DTD_out.root_name_start, lex.NameScan)
773                                        if DTD_out.notation_name_start & DTD_out.notation_name_follow:
774                                                error_tracker.NoteError('ExpectedNotationName', DTD_out.notation_name_start)
775                                        if DTD_out.notation_name_follow &~ lex.WS:
776                                                error_tracker.NoteError('ExpectedWhitespace', DTD_out.notation_name_follow)
777                                        marker = pablo.ScanThru(DTD_out.notation_name_follow, lex.WS)
778                                        require_system_id = 0
779                                        ParseExternalID(marker, require_system_id, id_out)
780                                        DTD_out.notation_pubid_start |= id_out.pubid_start
781                                        DTD_out.notation_pubid_end |= id_out.pubid_end
782                                        DTD_out.notation_sysid_start |= id_out.sysid_start
783                                        DTD_out.notation_sysid_end |= id_out.sysid_end
784                                        marker = id_out.end_marker
785                                        marker = pablo.ScanThru(marker, id_out.end_marker | lex.WS)
786                                        if marker &~ lex.RAngle:
787                                                error_tracker.NoteError('UnterminatedNotationDecl', marker)
788                        # Now Advance past the closing ";" or ">" and scan for the
789                        # next declaration, PI, Comment or PERef.
790                        marker = pablo.ScanThru(marker, marker | lex.WS)
791                if pablo.match(']', marker):
792                        pablo.Advance(marker)
793                        marker = pablo.ScanThru(marker, marker | lex.WS)
794                else:
795                        error_tracker.NoteError('UnterminatedintSubset', marker)
796        # Finally must be at ">" to close the DTD decl.
797        if marker &~ lex.RAngle:
798                error_tracker.NoteError('UnterminatedDOCTYPE', marker)
799
800        return marker
801
802def Parse_refs(lex, marker, ref_Callouts):
803        ref_Callouts.GenRef_starts = 0
804        ref_Callouts.GenRef_ends = 0
805        ref_Callouts.DecRef_starts = 0
806        ref_Callouts.DecRef_ends = 0
807        ref_Callouts.HexRef_starts = 0
808        ref_Callouts.HexRef_ends = 0
809        ref_error = 0
810
811        # All remaining "&" must be reference start characters; parse them.
812        if marker.Ref_opener:
813                Ref_scope = pablo.Advance(marker.Ref_opener)
814                NumRef2 = Ref_scope & lex.Hash
815                ref_Callouts.GenRef_starts = Ref_scope &~ lex.Hash
816                NumRef3 = pablo.Advance(NumRef2)
817                HexRef3 = NumRef3 & lex.x
818                ref_Callouts.DecRef_starts = NumRef3 &~ lex.x
819                ref_Callouts.HexRef_starts = pablo.Advance(HexRef3) 
820                ref_Callouts.GenRef_ends = pablo.ScanThru(ref_Callouts.GenRef_starts, lex.NameScan)
821                ref_Callouts.DecRef_ends = pablo.ScanThru(ref_Callouts.DecRef_starts, lex.Digit)
822                ref_Callouts.HexRef_ends = pablo.ScanThru(ref_Callouts.HexRef_starts, lex.Hex)
823                # Error checks
824                # At least one digit required for DecRef, one hex digit for HexRef.
825                ref_error1 = ref_Callouts.DecRef_starts &~ lex.Digit
826                ref_error2 = ref_Callouts.HexRef_starts &~ lex.Hex
827                # Semicolon terminator required (also covers unterminated at EOF).
828                ref_ends = ref_Callouts.GenRef_ends | ref_Callouts.DecRef_ends | ref_Callouts.HexRef_ends
829                ref_error3 = ref_ends &~ lex.Semicolon
830                ref_error = ref_error1 | ref_error2 | ref_error3
831                if ref_error:
832                        error_tracker.NoteError("Reference error found", (ref_error))
833                       
834
835
836def Validate_xml_names(ctCDPI_Callouts, ref_Callouts, tag_Callouts, lex, u8, check_streams):
837        PI_names = ctCDPI_Callouts.PI_name_ends - ctCDPI_Callouts.PI_name_starts
838        GenRefs = ref_Callouts.GenRef_ends - ref_Callouts.GenRef_starts
839        ElemNames = tag_Callouts.ElemName_ends - tag_Callouts.ElemName_starts
840        AttNames = tag_Callouts.AttName_ends - tag_Callouts.AttName_starts
841        qname_stream =  ElemNames | AttNames
842        ncname_stream = PI_names | GenRefs
843        name_stream = qname_stream | ncname_stream
844        name_start = name_stream &~ pablo.Advance(name_stream)
845        name_cursor = name_stream & ~pablo.Advance(name_stream)
846        void_prefix_err = name_cursor & lex.Colon
847        namespace_sep = pablo.ScanThru(name_cursor, lex.NameScan &~ lex.Colon) & lex.Colon
848        local_part_start = pablo.Advance(namespace_sep)
849        local_part_err = local_part_start &~ lex.NameScan
850        colon2_err = pablo.ScanThru(local_part_start, lex.NameScan &~ lex.Colon) & lex.Colon
851        ncname_err = ncname_stream & lex.Colon
852        namespace_error = void_prefix_err | local_part_err | colon2_err | ncname_err
853        if namespace_error:
854                error_tracker.NoteError("error found", namespace_error)
855               
856                       
857        check_streams.non_ascii_name_starts = name_start &~lex.ASCII_name_start
858        check_streams.non_ascii_names = (name_stream &~ name_start) & ~lex.ASCII_name_char & ~u8.suffix
859   
860def Do_check_streams(marker, tag_Callouts, check_streams):
861        CD_end_error = marker.CD_closer & ~tag_Callouts.AttVal_spans
862        if CD_end_error: 
863                error_tracker.NoteError("Error: ]]> in text", CD_end_error)
864        check_streams.tag_marks = tag_Callouts.EmptyTag_marks | tag_Callouts.ElemName_starts | tag_Callouts.EndTag_marks | tag_Callouts.AttName_starts
865        check_streams.name_follows = tag_Callouts.ElemName_ends | tag_Callouts.AttName_ends
866        check_streams.att_refs = tag_Callouts.AttVal_spans & marker.Ref_opener
867
868
869def Main(basis_bits, lex, u8, xml_char, scope1, ctCDPI_Callouts, ref_Callouts, tag_Callouts, masks, xml_names, check_streams): 
870       
871        # Classify bytes for UTF-8 processing, whitespace and control
872        # processing and XML lexical analysis.
873        # Classify_bytes(basis_bits, lex)
874
875        # Validate UTF-8 multibyte sequences and determine the UTF-8 scope streams
876        # Validate_utf8(basis_bits, u8)
877                               
878        Classify_bytes_Validate_utf8(basis_bits, lex, u8)
879
880        # Parse all comments, CDATA sections and processing instructions.
881        Parse_CtCDPI(lex, marker, ctCDPI_Callouts, check_streams)
882               
883        # All remaining '<' must be tag start characters; parse tags.
884        Parse_tags(lex, marker, tag_Callouts) 
885
886        # All remaining '&' must be reference start characters; parse them.
887        Parse_refs(lex, marker, ref_Callouts)
888       
889        # Validate XML namespaces and generate bit streams to post validate non-ascii range XML names
890        Validate_xml_names(ctCDPI_Callouts, ref_Callouts, tag_Callouts, lex, u8, check_streams)
891   
892        Do_check_streams(marker, tag_Callouts, check_streams)
893
894
895
896basis_bits = Basis_bits()
897lex = Lex()
898u8 = U8()
899marker = Marker()
900ctCDPI_Callouts = CtCDPI_Callouts()
901tag_Callouts = Tag_Callouts()
902id_out = ID_Callouts()
903ref_Callouts = Ref_Callouts()
904check_streams = Check_streams()
905DTD_out = DTD_Callouts()
906
907if __name__ == "__main__":
908        #print "Starting ..."
909        if len(sys.argv) > 1:
910                u8data = pablo.readfile(sys.argv[1]) 
911                pablo.EOF_mask = pablo.transpose_streams(u8data, basis_bits)
912                Classify_bytes_Validate_utf8(basis_bits, lex, u8)
913                Parse_CtCDPI(lex, marker, ctCDPI_Callouts, check_streams)
914                Parse_tags(lex, marker, tag_Callouts)
915                Parse_refs(lex, marker, ref_Callouts)
916                Validate_xml_names(ctCDPI_Callouts, ref_Callouts, tag_Callouts, lex, u8, check_streams)
917                Do_check_streams(marker, tag_Callouts, check_streams)
918        else:
919                print("Usage: python parabix2.py <file>")
920       
921
922
Note: See TracBrowser for help on using the repository browser.