source: trunk/src/engine.c @ 80

Last change on this file since 80 was 80, checked in by cameron, 11 years ago

Specialized ScanTo? for MarkupStart? => Text_action at Buffer end

File size: 22.9 KB
Line 
1/*  engine.c - Parabix XML parsing engine.
2    Copyright (c) 2007, 2008, Robert D. Cameron and Dan Lin.
3    Licensed to the public under the Open Software License 3.0.
4    Licensed to International Characters, Inc., under the Academic
5    Free License 3.0.
6*/
7
8#include "engine.h"
9#include "byteplex.h"
10#include "xmldecl.h"
11#include "bytelex.h"
12#include "bitlex.h"
13
14#include <assert.h>
15#include <stdlib.h>
16#include <errno.h>
17#include <string.h>
18
19
20Parser_Interface * Parser_Interface::ParserFactory(char * filename) {
21       
22        int chars_read;
23        unsigned char signature[4];
24        FILE * infile;
25        infile = fopen(filename, "rb");
26        if (!infile) {
27                fprintf(stderr, "Error: cannot open %s for input.\n", filename);
28                exit(-1);
29        }
30        fread(signature,1,4,infile);
31        Model_Info * m = new Model_Info;
32        m->AnalyzeSignature(signature);
33        Byteplex * b = Byteplex::ByteplexFactory(m, infile);
34        b->InitializeBuffer(signature,4);
35
36        if (m->code_unit_base == ASCII) {
37                return new ParsingEngine<ASCII>(m, b);
38        }
39        else /* if (m->code_unit_base == EBCDIC) */ {
40                return new ParsingEngine<EBCDIC>(m, b);
41        }       
42}
43
44Parser_Interface::~Parser_Interface() {
45}
46
47
48bool Parser_Interface::has_ByteOrderMark() {
49        return model_info->BOM_units > 0;
50}
51
52XML_version Parser_Interface::get_version() {
53        return model_info->version;
54}
55
56XML_standalone Parser_Interface::standalone_status() {
57        return model_info->standalone;
58}
59
60bool Parser_Interface::has_EncodingDecl() {
61        return model_info->has_encoding_decl;
62}
63
64unsigned char * Parser_Interface::get_Encoding() {
65        return model_info->encoding;
66}
67
68unsigned char * Parser_Interface::GetCodeUnitPtr(int pos) {
69        int rel_pos = pos - buffer_base_pos;
70        return &((unsigned char *) (byteplex->src_buffer))[rel_pos * (int) model_info->code_unit_size];
71}
72
73
74
75
76template <CodeUnit_Base C>
77ParsingEngine<C>::ParsingEngine(Model_Info * m, Byteplex * b) : Parser_Interface () {
78
79        model_info = m;
80        byteplex = b;
81
82        byteplex->DoByteplex();
83        byteplex->PreparePseudoASCII_Stream();
84        decl_parser = new XML_Decl_Parser<C>(byteplex);
85        int content_start = decl_parser->ReadXMLInfo(model_info);
86
87    bitplex = new Bitplex;
88        buf = (LexicalStreamSet *) simd_new(sizeof(LexicalStreamSet)/PACKSIZE);
89
90  /* Install sentinels for every lexical item stream*/
91#ifndef OPTIMIZE_SHORT_SCAN
92        BitBlock sentinel_value = simd_const_1(1);
93#endif
94#ifdef OPTIMIZE_SHORT_SCAN
95        BitBlock sentinel_value = sisd_sfli(simd_const_1(1), 8*sizeof(unsigned long));
96#endif
97        for (int j = minLexicalItem; j < LexicalItemCount; j++) {
98                buf->item_stream[j][BUFFER_BLOCKS] = sentinel_value;
99        }
100
101        buffer_base_pos = 0;
102        buffer_rel_pos = content_start;
103        buffer_limit_pos = min(BUFFER_SIZE, byteplex->units_in_buffer);
104        int blocks_in_buffer = (buffer_limit_pos + BLOCKSIZE - 1)/BLOCKSIZE;
105        x8data = byteplex->x8data;
106        lexer = Lexer<C>::LexerFactory(m, buf);
107        bitplex->TransposeToBitStreams(byteplex->x8data, blocks_in_buffer);
108        lexer->AnalyzeBuffer(bitplex->x8basis, buffer_limit_pos);
109}
110
111template <CodeUnit_Base C>
112ParsingEngine<C>::~ParsingEngine() {
113  model_info->~Model_Info();
114  byteplex->~Byteplex();
115  decl_parser->~XML_Decl_Parser<C>();
116  bitplex->~Bitplex();
117  simd_delete((SIMD_type *) buf);
118  lexer->~Lexer_Interface();
119}
120
121template <CodeUnit_Base C>
122inline void ParsingEngine<C>::AdvanceBuffers(int preserve_pos){
123        int advance_amt = min(preserve_pos, text_or_markup_start) - buffer_base_pos;
124        advance_amt &= -PACKSIZE; // maintain alignment
125        byteplex->AdvanceInputBuffer(advance_amt);
126        buffer_base_pos += advance_amt;
127        buffer_rel_pos -= advance_amt;
128        buffer_limit_pos = min(BUFFER_SIZE, byteplex->units_in_buffer);
129        int blocks_in_buffer = (buffer_limit_pos + BLOCKSIZE - 1)/BLOCKSIZE;
130        byteplex->DoByteplex();
131        byteplex->PreparePseudoASCII_Stream();
132        bitplex->TransposeToBitStreams(byteplex->x8data, blocks_in_buffer);
133        lexer->AnalyzeBuffer(bitplex->x8basis, buffer_limit_pos);
134}
135
136template <CodeUnit_Base C>
137inline unsigned char * ParsingEngine<C>::cur() const {
138  return &((unsigned char *) x8data)[buffer_rel_pos];
139}
140
141template <CodeUnit_Base C>
142inline int ParsingEngine<C>::AbsPos() const {
143  return buffer_base_pos + buffer_rel_pos;
144}
145
146
147template <CodeUnit_Base C>
148inline int ParsingEngine<C>::BufferRelPos() const {
149  return buffer_rel_pos;
150}
151
152
153template <CodeUnit_Base C>
154inline bool ParsingEngine<C>::at_EOF() const {
155  return (buffer_rel_pos >= buffer_limit_pos) && 
156         (buffer_limit_pos < BUFFER_SIZE);
157}
158
159template <CodeUnit_Base C>
160inline void ParsingEngine<C>::Advance(int n) {
161        int preserve_pos;
162        buffer_rel_pos += n;
163#ifndef OMIT_BITBUFFER_LIMIT_TEST_IN_ADVANCE
164  if (buffer_rel_pos >= BUFFER_SIZE) {
165        FinalizeBuffer_action(preserve_pos);
166        AdvanceBuffers(preserve_pos);
167  }
168#endif
169}
170
171
172#ifndef OPTIMIZE_SHORT_SCAN
173template <CodeUnit_Base C>
174inline void ParsingEngine<C>::ScanTo(int item) {
175        int preserve_pos;
176  buffer_rel_pos = bitstream_scan(buf->item_stream[item], 
177                                      buffer_rel_pos);
178  while (buffer_rel_pos >= BUFFER_SIZE) {
179        FinalizeBuffer_action(preserve_pos);
180        AdvanceBuffers(preserve_pos);
181        buffer_rel_pos = bitstream_scan(buf->item_stream[item], buffer_rel_pos);
182  }
183}
184#endif
185
186template <CodeUnit_Base C>
187inline void ParsingEngine<C>::ScanToMarkupStart() {
188        int preserve_pos;
189        text_or_markup_start = AbsPos();
190        buffer_rel_pos = bitstream_scan(buf->item_stream[MarkupStart], buffer_rel_pos);
191        while (buffer_rel_pos >= BUFFER_SIZE) {
192                Text_action(text_or_markup_start, AbsPos());
193                text_or_markup_start = AbsPos();
194                FinalizeBuffer_action(preserve_pos);
195                AdvanceBuffers(preserve_pos);
196                buffer_rel_pos = bitstream_scan(buf->item_stream[MarkupStart], buffer_rel_pos);
197        }
198}
199
200#ifdef OPTIMIZE_SHORT_SCAN
201template <CodeUnit_Base C>
202inline void ParsingEngine<C>::ScanTo(int item) {
203  SIMD_type * stream = buf->item_stream[item];
204  unsigned long * bitstream_ptr = (unsigned long *) (((intptr_t) stream) + buffer_rel_pos/8);
205  unsigned long bitstream_slice = *bitstream_ptr >> buffer_rel_pos % 8;
206  if (bitstream_slice != 0) {
207    buffer_rel_pos += __builtin_ctzl(bitstream_slice);
208  }
209  else {
210    buffer_rel_pos = (buffer_rel_pos & -8) + 8*sizeof(unsigned long);
211    buffer_rel_pos += bitstream_scan0((SIMD_type *) &bitstream_ptr[1]);
212    while (buffer_rel_pos >= BUFFER_BLOCKS * BLOCKSIZE) {
213      buffer_rel_pos = BUFFER_BLOCKS * BLOCKSIZE;
214      FinalizeBuffer_action(preserve_pos);
215          AdvanceBuffers(preserve_pos);
216      buffer_rel_pos = bitstream_scan(buf->item_stream[item], buffer_rel_pos);
217    }
218  }
219}
220#endif
221
222
223/* Parse a markup item beginning '<' */
224template <CodeUnit_Base C>
225inline void ParsingEngine<C>::Parse_Markup() {
226        text_or_markup_start = AbsPos();
227        if (at_ElementTag_Start<C>(cur())) {
228                Parse_StartTag();
229        }
230        else if (at_EndTag_Start<C>(cur())) {
231                Parse_EndTag();
232        }
233        else if (at_Comment_Start<C>(cur())) {
234                Parse_Comment();
235        }
236        else if (at_CDATA_Start<C>(cur())) {
237                Parse_CDATA();
238        }
239        else if (at_PI_Start<C>(cur())) {
240                Parse_PI();
241        }
242        else {
243                Advance(1);
244                Error_action(text_or_markup_start, AbsPos());
245        }
246}
247
248/* Parse a comment beginning "<!--" */
249template <CodeUnit_Base C>
250inline void ParsingEngine<C>::Parse_Comment() {
251
252        Advance(4); /* Skip "<!--". */
253        ScanTo(Hyphen);
254        while (!at_DoubleHyphen<C>(cur())) {
255                Advance(2); /* Skip hyphen-nonhyphen pair */
256                ScanTo(Hyphen); 
257        }
258        if (at_Comment_End<C>(cur())) {
259                Advance(3); /* Skip "-->". */
260                Comment_action(text_or_markup_start, AbsPos());
261        }
262        else {
263                Advance(2);  /* "--" */
264                Error_action(text_or_markup_start, AbsPos());
265        }
266}
267
268/* Parse an end tag beginning "</" */
269template <CodeUnit_Base C>
270inline void ParsingEngine<C>::Parse_EndTag() {
271        Advance(2); /* Skip "</". */
272        ScanTo(NameFollow);
273        if (AtChar<C,'>'>(cur())) {
274                Advance(1);
275                EndTag_action(text_or_markup_start, AbsPos());
276        }
277        else {
278                ScanTo(NonWS);
279                if (AtChar<C,'>'>(cur())) {
280                        Advance(1);
281                        EndTag_action(text_or_markup_start, AbsPos());
282                }
283                else Error_action(text_or_markup_start, AbsPos());
284        }
285}
286
287/* Parse a CDATA section beginning "<![CDATA". */
288template <CodeUnit_Base C>
289inline void ParsingEngine<C>::Parse_CDATA() {
290        Advance(8); /* Skip "<![CDATA". */
291        if (!AtChar<C,'['>(cur())) {
292                Error_action(text_or_markup_start, AbsPos());
293        }
294        else {
295                ScanTo(CD_End_check);
296                while (!at_CDATA_End<C>(cur())) {
297                        Advance(1);
298                        ScanTo(CD_End_check);
299                }
300                Advance(3); /* Skip "]]>". */
301                CDATA_action(text_or_markup_start, AbsPos());
302        }
303}
304
305template <CodeUnit_Base C>
306inline void ParsingEngine<C>::Parse_Reference() {
307        Advance(1);  // skip "&"
308        ScanTo(NameFollow);  /* Name delimiter */
309        if (!AtChar<C,';'>(cur())) {
310                Error_action(text_or_markup_start, AbsPos());
311        }
312        else {
313                Advance(1);
314                Reference_action(text_or_markup_start, AbsPos());
315        }
316}
317
318template <CodeUnit_Base C>
319inline void ParsingEngine<C>::Parse_PI (){
320        Advance(2); /* Skip "<?". */
321        int target_start = AbsPos();
322        // Check for illegal [Xx][Mm][Ll] target.
323        if (at_XxMmLll_WS<C>(cur())) {
324                Advance(4);
325                Error_action(text_or_markup_start, AbsPos());
326                return;
327        } 
328        ScanTo(NameFollow);  /* Name delimiter */
329        PI_Target_action(target_start, AbsPos());
330        ScanTo(QMark);
331        while (!at_PI_End<C>(cur())) {
332                Advance(1);
333                ScanTo(QMark);
334        }
335        Advance(2); /* Skip "?>". */
336        PI_action(text_or_markup_start, AbsPos());
337}
338 
339/* Parse a start or empty element tag. */
340template <CodeUnit_Base C>
341inline void ParsingEngine<C>::Parse_StartTag (){
342        int att_name_start;
343        int att_val_start;
344        int att_name_end, att_val_end;
345        unsigned char quoteCh;
346        Advance(1);
347        ScanTo(NameFollow);  /* Name delimiter: WS, "/" or ">" */
348        ElementName_action(text_or_markup_start+1, AbsPos());
349        /* The following test optimizes the most common case of a
350        start tag with no attributes.  */
351        if (AtChar<C,'>'>(cur())) {
352                Advance(1);
353                StartTag_action(text_or_markup_start, AbsPos());
354        }
355        else {
356                ScanTo(NonWS);
357                if (AtChar<C,'>'>(cur())) {
358                        Advance(1);
359                        StartTag_action(text_or_markup_start, AbsPos());
360                }
361                else if (at_EmptyElementDelim<C>(cur())) {
362                        Advance(2);
363                        EmptyElement_action(text_or_markup_start, AbsPos());
364                }
365                else do {
366                        /* Must be an attribute-value pair or error. */
367                        att_name_start = AbsPos();
368                        ScanTo(NameFollow);
369                        att_name_end = AbsPos();
370                        /* The following optimized tests handle the frequently occurring
371                        case that there are no blanks on either side of the equals sign.
372                        In many cases, the very first test handles 100% of actual
373                        attribute-value pairs encountered. */
374                        if (at_EqualsQuote<C>(cur())) {
375                                quoteCh = cur()[1];
376                                Advance(2); 
377                        }
378                        else {
379                                ScanTo(NonWS);
380                                if (!AtChar<C,'='>(cur())) {
381                                        Error_action(text_or_markup_start, AbsPos()); 
382                                        break;
383                                }
384                                ScanTo(NonWS);
385                                quoteCh = cur()[0];
386                                if (!AtQuote<C>(cur())) {
387                                        Error_action(text_or_markup_start, AbsPos()); 
388                                        break;
389                                }
390                                Advance(1);
391                        }
392                        att_val_start = AbsPos();
393                        ScanTo(Quote);
394                        while (cur()[0] != quoteCh) {
395                                if (AtChar<C,'&'>(cur())) {
396                                        Parse_Reference();
397                                        ScanTo(Quote);
398                                }
399                                else if (AtQuote<C>(cur())) {
400                                        Advance(1);
401                                }
402                                else /* if (AtChar<C,'<'>(cur())) */{
403                                        Error_action(text_or_markup_start, AbsPos()); 
404                                        break;
405                                }
406                        }
407                        att_val_end = AbsPos();
408                        Advance(1); 
409                        if (at_xmlns<C>(cur()+att_name_start-AbsPos())) {
410                                Namespace_action(att_name_start, att_name_end,
411                                                 att_val_start, att_val_end);
412                        }
413                        else {
414                                AttributeValue_action(att_name_start, att_name_end,
415                                                      att_val_start, att_val_end);
416                        }
417                        /* Now check for end or repeat. Avoid whitespace scan if possible.*/
418                        if (AtChar<C,'>'>(cur())) {
419                                Advance(1);
420                                StartTag_action(text_or_markup_start, AbsPos());
421                                break;
422                        }
423                        else if (at_EmptyElementDelim<C>(cur())) {
424                                Advance(2);
425                                EmptyElement_action(text_or_markup_start, AbsPos());
426                                break;
427                        }
428                        ScanTo(NonWS);
429                        if (AtChar<C,'>'>(cur())) {
430                                Advance(1);
431                                StartTag_action(text_or_markup_start, AbsPos());
432                                break;
433                        }
434                        else if (at_EmptyElementDelim<C>(cur())) {
435                                Advance(2);
436                                EmptyElement_action(text_or_markup_start, AbsPos());
437                                break;
438                        }
439                        else if (AbsPos() == att_val_end + 1) { 
440                                /* No WS following att value */
441                                Error_action(text_or_markup_start, AbsPos());
442                                break;
443                        }
444                } while (1);
445        }
446}
447
448template <CodeUnit_Base C>
449inline void ParsingEngine<C>::text_if_nonnull_action(){
450        if (AbsPos() > text_or_markup_start) {
451                Text_action(text_or_markup_start, AbsPos());
452                text_or_markup_start = AbsPos();
453        }
454}
455
456template <CodeUnit_Base C>
457inline void ParsingEngine<C>::ParseContent() {
458        DocumentStart_action(); 
459        do {
460                text_or_markup_start = AbsPos();
461                ScanToMarkupStart(); /* '<', '&', or ']' for ']]>' test */
462/*              if (AtChar<C,'<'>(cur())) {
463                        text_if_nonnull_action();
464                        Parse_Markup<C>();
465                }*/
466                if (at_ElementTag_Start<C>(cur())) {
467                        text_if_nonnull_action();
468                        Parse_StartTag();
469                }
470                else if (at_EndTag_Start<C>(cur())) {
471                        text_if_nonnull_action();
472                        Parse_EndTag();
473                }
474                else if (at_Comment_Start<C>(cur())) {
475                        text_if_nonnull_action();
476                        Parse_Comment();
477                }
478                else if (AtChar<C,'&'>(cur())) {
479                        text_if_nonnull_action();
480                        Parse_Reference();
481                }
482                else if (at_CDATA_Start<C>(cur())) {
483                        text_if_nonnull_action();
484                        Parse_CDATA();
485                }
486                else if (at_PI_Start<C>(cur())) {
487                        text_if_nonnull_action();
488                        Parse_PI();
489                }
490                else if (at_CDATA_End<C>(cur())) {
491                        text_if_nonnull_action();
492                        Advance(3);
493                        Error_action(AbsPos()-3, AbsPos());
494                }
495                else if (at_EOF()) {
496                        text_if_nonnull_action();
497                        break;
498                }
499                else {
500                        Advance(1);
501                        continue;
502                }
503        } while (1);
504        DocumentEnd_action();   
505}
506
507
508template <CodeUnit_Base C>
509inline void ParsingEngine<C>::Parse_DocType (){
510
511        int old_abspos, start_pos;
512        ScanTo(NonWS);
513        start_pos = AbsPos();
514       
515        if (at_DOCTYPE_start<C>(cur()))
516        Advance(9);
517        else{
518//              printf("No Document definition!\n");
519                return;
520        }
521        requireWS();
522       
523        ScanTo(NameFollow);
524       
525        old_abspos = AbsPos(); 
526    ScanTo(NonWS);
527    if(at_SYSTEM<C>(cur())||at_PUBLIC<C>(cur())){
528        if(old_abspos == AbsPos())
529                Error_action(start_pos, AbsPos());
530        Parse_ExternalID();
531    }
532   
533    ScanTo(NonWS);     
534
535        if (AtChar<C,'['>(cur())){
536                Advance(1);
537                Parse_IntSubset();
538                if (AtChar<C,']'>(cur()))
539                        Advance(1);
540                else
541                        Error_action(start_pos, AbsPos()); 
542                ScanTo(NonWS);
543        }
544       
545        if (AtChar<C,'>'>(cur())){
546                Advance(1);   
547                Doctype_action(start_pos, AbsPos());
548        }
549}
550
551template <CodeUnit_Base C>
552inline void ParsingEngine<C>::Parse_ExternalID (){
553
554        if(at_SYSTEM<C>(cur())){
555                Advance(6);
556                requireWS();
557                Parse_MatchedQuote (); /*  SystemLiteral */
558        }
559        else if (at_PUBLIC<C>(cur())){
560                Advance(6);
561                requireWS();
562                Parse_MatchedQuote ();/*  PubidLiteral */
563                requireWS();
564                Parse_MatchedQuote ();/*  SystemLiteral */
565        }
566        else
567                Error_action(text_or_markup_start, AbsPos()); 
568}
569
570template <CodeUnit_Base C>
571inline void ParsingEngine<C>::Parse_MatchedQuote (){
572        unsigned char quoteCh;
573        if(AtQuote<C>(cur())){
574                quoteCh = cur()[0];
575                Advance(1);
576        }
577        ScanTo(Quote);                 
578        while (cur()[0] != quoteCh){
579                Advance(1);
580                ScanTo(Quote);
581        }
582        Advance(1);
583}
584
585template <CodeUnit_Base C>
586inline void ParsingEngine<C>::Parse_IntSubset (){
587       
588        while(1){
589                ScanTo(NonWS); 
590                text_or_markup_start = AbsPos();
591                if (AtChar<C,'%'>(cur()))
592                        Parse_PEReference();   
593                else if (AtChar<C,'<'>(cur())){
594                        Advance(1);
595
596                        if (AtChar<C,'?'>(cur())){
597                                Parse_PI();
598                        }
599                        else if(AtChar<C,'!'>(cur())){
600                                Advance(1);
601                                if(at_DoubleHyphen<C>(cur()))
602                                        Parse_Comment();
603                                else if(at_ELEMENT<C>(cur()))
604                                        Parse_Elementdecl();
605                                else if(at_ATTLIST<C>(cur()))
606                                        Parse_AttlistDecl();
607                                else if(at_ENTITY<C>(cur()))
608                                        Parse_Entitydecl();
609                                else if(at_NOTATION<C>(cur()))
610                                        Parse_Notationdecl();                   
611                                       
612                        }
613                        else
614                                Error_action(text_or_markup_start, AbsPos()); 
615                }
616                else if (AtChar<C,']'>(cur())){
617                        break;
618                }
619                else
620                        Error_action(text_or_markup_start, AbsPos()); 
621        }
622}
623
624
625template <CodeUnit_Base C>
626inline void ParsingEngine<C>::Parse_PEReference (){
627
628        Advance(1); /* Skip "%". */
629        ScanTo(NameFollow); 
630        if (AtChar<C,';'>(cur())) {
631                Advance(1);
632                PEReference_action(text_or_markup_start, AbsPos());
633        }
634        else
635                Error_action(text_or_markup_start, AbsPos());
636}
637
638
639template <CodeUnit_Base C>
640inline void ParsingEngine<C>::Parse_Elementdecl (){
641
642        Advance(7); /* Skip "<!ELEMENT". */
643
644    requireWS();
645        ScanTo(NameFollow);
646        requireWS();
647       
648        /* Start parsing "contentspec"*/
649        if (at_EMPTY<C>(cur()))
650        Advance(5);
651    else if (at_ANY<C>(cur()))
652        Advance(3);
653    else {
654        if (AtChar<C,'('>(cur()))
655                        Advance(1);
656                ScanTo(NonWS);
657                if (at_PCDATA<C>(cur()))
658                        Parse_RemainedMixed();
659                else
660                        Parse_RemainedChildren();
661    }
662               
663        if (AtChar<C,'>'>(cur())) {
664                Advance(1);
665                Elementdecl_action(text_or_markup_start, AbsPos());
666        }
667        else
668                Error_action(text_or_markup_start, AbsPos());
669}
670template <CodeUnit_Base C>
671inline void ParsingEngine<C>::Parse_RemainedMixed (){
672       
673        Advance(7);  /* Skip "#PCDATA". */
674   
675    if (AtChar<C,')'>(cur())){
676        if (AtChar<C,'*'>(cur()))
677                Advance(2);
678                else
679                        Advance(1);
680    }
681    else{
682        ScanTo(NonWS);
683        while(!at_Para_star<C>(cur())){
684                if (AtChar<C,'|'>(cur())){
685                                Advance(1);
686                                ScanTo(NonWS);
687                                ScanTo(NameFollow);
688                                ScanTo(NonWS);
689                }
690        }
691        Advance(2);
692    }
693}
694
695
696template <CodeUnit_Base C>
697inline void ParsingEngine<C>::Parse_RemainedChildren (){
698        Parse_Cp();
699        ScanTo(NonWS);
700        if(AtChar<C,'|'>(cur())){
701                Advance(1);
702                ScanTo(NonWS);
703                Parse_Cp();
704                ScanTo(NonWS);
705                while(!AtChar<C,')'>(cur())){
706                        if(AtChar<C,'|'>(cur()))
707                                Advance(1);
708                        ScanTo(NonWS);
709                        Parse_Cp();
710                        ScanTo(NonWS);
711                }
712                Advance(1);
713        }
714        else if(AtChar<C,','>(cur())){
715                Advance(1);
716                ScanTo(NonWS);
717                Parse_Cp();
718                ScanTo(NonWS);
719                while(!AtChar<C,')'>(cur())){
720                        if(AtChar<C,','>(cur()))
721                                Advance(1);
722                        ScanTo(NonWS);
723                        Parse_Cp();
724                        ScanTo(NonWS);
725                }
726                Advance(1);
727        }       
728        else if(AtChar<C,')'>(cur())){
729                Advance(1);
730        }
731        else
732                Error_action(text_or_markup_start, AbsPos());
733               
734        if (AtChar<C,'?'>(cur())||AtChar<C,'*'>(cur())||AtChar<C,'+'>(cur()))
735                Advance(1);
736}
737
738template <CodeUnit_Base C>
739inline void ParsingEngine<C>::Parse_Cp (){
740        if (AtChar<C,'('>(cur())){
741                Advance(1);
742                ScanTo(NonWS);
743                Parse_RemainedChildren();
744        }
745        else{
746                ScanTo(NameFollow);
747                if (AtChar<C,'?'>(cur())||AtChar<C,'*'>(cur())||AtChar<C,'+'>(cur()))
748                        Advance(1);
749        }
750}
751
752template <CodeUnit_Base C>
753inline void ParsingEngine<C>::Parse_AttlistDecl (){
754       
755        int old_abspos;
756        Advance(7); /* Skip "ATTLIST. */
757        requireWS();
758        ScanTo(NameFollow);
759       
760        old_abspos = AbsPos();
761        ScanTo(NonWS);
762        while(!AtChar<C,'>'>(cur())) {
763                if(old_abspos == AbsPos())
764                Error_action(text_or_markup_start, AbsPos());
765        ScanTo(NameFollow);
766        requireWS();
767        if (at_CDATA<C>(cur()))
768                Advance(5);
769        else if(at_ID<C>(cur()))
770                Advance(2);
771        else if(at_IDREF<C>(cur()))
772                Advance(5);
773        else if(at_IDREFS<C>(cur()))
774                Advance(6);
775        else if(at_ENTITY<C>(cur()))
776                Advance(6);
777        else if(at_ENTITIES<C>(cur()))
778                Advance(8);
779        else if(at_NMTOKEN<C>(cur()))
780                Advance(7);
781        else if(at_NMTOKENS<C>(cur()))
782                Advance(8);
783        else if(at_NOTATION<C>(cur())){ /* NotationType = 'NOTATION' S Enumeration
784                                                                         when Nmtoken = Name */
785                Advance(8);
786                        requireWS();
787                Parse_Enumeration();
788        }
789        else if(AtChar<C,'('>(cur()))
790                Parse_Enumeration();
791        else
792                Error_action(text_or_markup_start, AbsPos());
793        requireWS();
794        Parse_DefaultDecl();
795        old_abspos = AbsPos();
796                ScanTo(NonWS);
797        }
798        Advance(1);
799        AttlistDecl_action(text_or_markup_start, AbsPos());
800}
801
802template <CodeUnit_Base C>
803inline void ParsingEngine<C>::Parse_Enumeration (){
804
805        if(AtChar<C,'('>(cur()))
806                Advance(1);
807        else
808                Error_action(text_or_markup_start, AbsPos());
809        ScanTo(NonWS);
810        ScanTo(NameFollow);
811        ScanTo(NonWS);
812        while(AtChar<C,'|'>(cur())){
813                Advance(1);
814                ScanTo(NameFollow);
815                ScanTo(NonWS);
816        }
817        if (AtChar<C,')'>(cur())) 
818                Advance(1);
819        else
820                Error_action(text_or_markup_start, AbsPos());
821}
822
823template <CodeUnit_Base C>
824inline void ParsingEngine<C>::Parse_DefaultDecl (){
825        if(at_REQUIRED<C>(cur()))
826                Advance(9);
827        else if(at_IMPLIED<C>(cur()))
828                Advance(8);
829        else if(at_FIXED<C>(cur())){
830                Advance(6);
831                requireWS();
832        }
833        else if(AtQuote<C>(cur())){
834                Parse_AttValue();
835        }
836        else
837                Error_action(text_or_markup_start, AbsPos());
838}
839
840template <CodeUnit_Base C>
841inline void ParsingEngine<C>::Parse_Entitydecl (){
842       
843        int old_abspos;
844        Advance(6); /* Skip "ENTITY. */
845        requireWS();
846       
847        if (AtChar<C,'%'>(cur())){
848                Advance(1);
849                requireWS();
850                ScanTo(NameFollow);
851                requireWS();
852                if(at_SYSTEM<C>(cur())||at_PUBLIC<C>(cur())){
853                Parse_ExternalID();             
854        }
855        else if(AtQuote<C>(cur())){
856                Parse_AttValue(); /* Not parse PEReference*/
857        }
858        else
859                Error_action(text_or_markup_start, AbsPos());
860        }
861        else{
862                ScanTo(NameFollow);
863                requireWS();
864               
865                if(at_SYSTEM<C>(cur())||at_PUBLIC<C>(cur())){
866                Parse_ExternalID();
867                ScanTo(NonWS);
868                if(at_NOTATION<C>(cur())){
869                        if(old_abspos == AbsPos())
870                                Error_action(text_or_markup_start, AbsPos());
871                        else
872                                Advance(5);
873                        requireWS();
874                        ScanTo(NameFollow);
875                }
876        }
877        else if(AtQuote<C>(cur())){
878                Parse_AttValue(); /* Not parse PEReference*/
879        }
880        else
881                Error_action(text_or_markup_start, AbsPos());
882        }
883        ScanTo(NonWS);
884        if (AtChar<C,'>'>(cur())){
885                Advance(1);
886                Entitydecl_action(text_or_markup_start, AbsPos());
887        }
888        else
889                Error_action(text_or_markup_start, AbsPos());
890}
891
892template <CodeUnit_Base C>
893inline void ParsingEngine<C>::Parse_Notationdecl (){
894       
895        int old_abspos;
896        Advance(8); /* Skip "NOTATION. */
897        requireWS();
898        ScanTo(NameFollow);
899        requireWS();
900        if(at_SYSTEM<C>(cur())){
901                Advance(6);
902                requireWS();
903                Parse_MatchedQuote (); /*  SystemLiteral */
904        }
905        else if (at_PUBLIC<C>(cur())){
906                Advance(6);
907                requireWS();
908                Parse_MatchedQuote (); /*  PubidLiteral */
909                ScanTo(NonWS);
910                if (!AtChar<C,'>'>(cur())){
911                        if (old_abspos == AbsPos())
912                                Error_action(text_or_markup_start, AbsPos());
913                        Parse_MatchedQuote (); /*  SystemLiteral */
914                }
915        }
916        else
917                Error_action(text_or_markup_start, AbsPos());
918        ScanTo(NonWS);
919        if (AtChar<C,'>'>(cur())) {
920                Advance(1);
921                Notationdecl_action(text_or_markup_start, AbsPos());
922        }
923        else
924                Error_action(text_or_markup_start, AbsPos());
925}
926
927template <CodeUnit_Base C>
928inline void ParsingEngine<C>::requireWS(){
929       
930    int old_abspos = AbsPos(); 
931    ScanTo(NonWS);
932    if(old_abspos == AbsPos())
933        Error_action(text_or_markup_start, AbsPos());
934}
935
936template <CodeUnit_Base C>
937inline void ParsingEngine<C>::Parse_AttValue(){
938       
939        int     quoteCh = cur()[0];
940        Advance(1); /* Skip " or ' */
941
942        ScanTo(Quote);                 
943        while (cur()[0] != quoteCh){
944                if (AtChar<C,'&'>(cur())){
945                        Parse_Reference();
946                        ScanTo(Quote);
947                }
948                else if (AtQuote<C>(cur())) {
949                        Advance(1);
950                        ScanTo(Quote);
951                }
952                else /* if (AtChar<C,'<'>(cur())) */
953                        Error_action(text_or_markup_start, AbsPos());
954        }
955        Advance(1);
956}
957
958template <CodeUnit_Base C>
959inline void ParsingEngine<C>::Parse_Prolog(){
960        ScanTo(NonWS);
961        int old_pos = AbsPos();
962        while (!at_DOCTYPE_start<C>(cur())) {
963                if (at_Comment_Start<C>(cur())) 
964                        Parse_Comment();
965                else if (at_PI_Start<C>(cur()))
966                                Parse_PI();
967                else{
968                        Prolog_action(old_pos, AbsPos());
969                        return;
970                }
971                ScanTo(NonWS);
972        }
973        Parse_DocType();
974        ScanTo(NonWS);
975        while(at_Comment_Start<C>(cur()) || at_PI_Start<C>(cur()) ){
976                if (at_Comment_Start<C>(cur()))
977                        Parse_Comment();
978                else 
979                        Parse_PI();
980                ScanTo(NonWS);
981        }
982        Prolog_action(old_pos, AbsPos());
983}
984
985
986
Note: See TracBrowser for help on using the repository browser.