source: trunk/src/engine.c @ 78

Last change on this file since 78 was 78, checked in by lindanl, 11 years ago

DTD parsing.

File size: 22.4 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
186#ifdef OPTIMIZE_SHORT_SCAN
187template <CodeUnit_Base C>
188inline void ParsingEngine<C>::ScanTo(int item) {
189  SIMD_type * stream = buf->item_stream[item];
190  unsigned long * bitstream_ptr = (unsigned long *) (((intptr_t) stream) + buffer_rel_pos/8);
191  unsigned long bitstream_slice = *bitstream_ptr >> buffer_rel_pos % 8;
192  if (bitstream_slice != 0) {
193    buffer_rel_pos += __builtin_ctzl(bitstream_slice);
194  }
195  else {
196    buffer_rel_pos = (buffer_rel_pos & -8) + 8*sizeof(unsigned long);
197    buffer_rel_pos += bitstream_scan0((SIMD_type *) &bitstream_ptr[1]);
198    while (buffer_rel_pos >= BUFFER_BLOCKS * BLOCKSIZE) {
199      buffer_rel_pos = BUFFER_BLOCKS * BLOCKSIZE;
200      FinalizeBuffer_action(preserve_pos);
201          AdvanceBuffers(preserve_pos);
202      buffer_rel_pos = bitstream_scan(buf->item_stream[item], buffer_rel_pos);
203    }
204  }
205}
206#endif
207
208
209/* Parse a markup item beginning '<' */
210template <CodeUnit_Base C>
211inline void ParsingEngine<C>::Parse_Markup() {
212        text_or_markup_start = AbsPos();
213        if (at_ElementTag_Start<C>(cur())) {
214                Parse_StartTag();
215        }
216        else if (at_EndTag_Start<C>(cur())) {
217                Parse_EndTag();
218        }
219        else if (at_Comment_Start<C>(cur())) {
220                Parse_Comment();
221        }
222        else if (at_CDATA_Start<C>(cur())) {
223                Parse_CDATA();
224        }
225        else if (at_PI_Start<C>(cur())) {
226                Parse_PI();
227        }
228        else {
229                Advance(1);
230                Error_action(text_or_markup_start, AbsPos());
231        }
232}
233
234/* Parse a comment beginning "<!--" */
235template <CodeUnit_Base C>
236inline void ParsingEngine<C>::Parse_Comment() {
237
238        Advance(4); /* Skip "<!--". */
239        ScanTo(Hyphen);
240        while (!at_DoubleHyphen<C>(cur())) {
241                Advance(2); /* Skip hyphen-nonhyphen pair */
242                ScanTo(Hyphen); 
243        }
244        if (at_Comment_End<C>(cur())) {
245                Advance(3); /* Skip "-->". */
246                Comment_action(text_or_markup_start, AbsPos());
247        }
248        else {
249                Advance(2);  /* "--" */
250                Error_action(text_or_markup_start, AbsPos());
251        }
252}
253
254/* Parse an end tag beginning "</" */
255template <CodeUnit_Base C>
256inline void ParsingEngine<C>::Parse_EndTag() {
257        Advance(2); /* Skip "</". */
258        ScanTo(NameFollow);
259        if (AtChar<C,'>'>(cur())) {
260                Advance(1);
261                EndTag_action(text_or_markup_start, AbsPos());
262        }
263        else {
264                ScanTo(NonWS);
265                if (AtChar<C,'>'>(cur())) {
266                        Advance(1);
267                        EndTag_action(text_or_markup_start, AbsPos());
268                }
269                else Error_action(text_or_markup_start, AbsPos());
270        }
271}
272
273/* Parse a CDATA section beginning "<![CDATA". */
274template <CodeUnit_Base C>
275inline void ParsingEngine<C>::Parse_CDATA() {
276        Advance(8); /* Skip "<![CDATA". */
277        if (!AtChar<C,'['>(cur())) {
278                Error_action(text_or_markup_start, AbsPos());
279        }
280        else {
281                ScanTo(CD_End_check);
282                while (!at_CDATA_End<C>(cur())) {
283                        Advance(1);
284                        ScanTo(CD_End_check);
285                }
286                Advance(3); /* Skip "]]>". */
287                CDATA_action(text_or_markup_start, AbsPos());
288        }
289}
290
291template <CodeUnit_Base C>
292inline void ParsingEngine<C>::Parse_Reference() {
293        Advance(1);  // skip "&"
294        ScanTo(NameFollow);  /* Name delimiter */
295        if (!AtChar<C,';'>(cur())) {
296                Error_action(text_or_markup_start, AbsPos());
297        }
298        else {
299                Advance(1);
300                Reference_action(text_or_markup_start, AbsPos());
301        }
302}
303
304template <CodeUnit_Base C>
305inline void ParsingEngine<C>::Parse_PI (){
306        Advance(2); /* Skip "<?". */
307        int target_start = AbsPos();
308        // Check for illegal [Xx][Mm][Ll] target.
309        if (at_XxMmLll_WS<C>(cur())) {
310                Advance(4);
311                Error_action(text_or_markup_start, AbsPos());
312                return;
313        } 
314        ScanTo(NameFollow);  /* Name delimiter */
315        PI_Target_action(target_start, AbsPos());
316        ScanTo(QMark);
317        while (!at_PI_End<C>(cur())) {
318                Advance(1);
319                ScanTo(QMark);
320        }
321        Advance(2); /* Skip "?>". */
322        PI_action(text_or_markup_start, AbsPos());
323}
324 
325/* Parse a start or empty element tag. */
326template <CodeUnit_Base C>
327inline void ParsingEngine<C>::Parse_StartTag (){
328        int att_name_start;
329        int att_val_start;
330        int att_name_end, att_val_end;
331        unsigned char quoteCh;
332        Advance(1);
333        ScanTo(NameFollow);  /* Name delimiter: WS, "/" or ">" */
334        ElementName_action(text_or_markup_start+1, AbsPos());
335        /* The following test optimizes the most common case of a
336        start tag with no attributes.  */
337        if (AtChar<C,'>'>(cur())) {
338                Advance(1);
339                StartTag_action(text_or_markup_start, AbsPos());
340        }
341        else {
342                ScanTo(NonWS);
343                if (AtChar<C,'>'>(cur())) {
344                        Advance(1);
345                        StartTag_action(text_or_markup_start, AbsPos());
346                }
347                else if (at_EmptyElementDelim<C>(cur())) {
348                        Advance(2);
349                        EmptyElement_action(text_or_markup_start, AbsPos());
350                }
351                else do {
352                        /* Must be an attribute-value pair or error. */
353                        att_name_start = AbsPos();
354                        ScanTo(NameFollow);
355                        att_name_end = AbsPos();
356                        /* The following optimized tests handle the frequently occurring
357                        case that there are no blanks on either side of the equals sign.
358                        In many cases, the very first test handles 100% of actual
359                        attribute-value pairs encountered. */
360                        if (at_EqualsQuote<C>(cur())) {
361                                quoteCh = cur()[1];
362                                Advance(2); 
363                        }
364                        else {
365                                ScanTo(NonWS);
366                                if (!AtChar<C,'='>(cur())) {
367                                        Error_action(text_or_markup_start, AbsPos()); 
368                                        break;
369                                }
370                                ScanTo(NonWS);
371                                quoteCh = cur()[0];
372                                if (!AtQuote<C>(cur())) {
373                                        Error_action(text_or_markup_start, AbsPos()); 
374                                        break;
375                                }
376                                Advance(1);
377                        }
378                        att_val_start = AbsPos();
379                        ScanTo(Quote);
380                        while (cur()[0] != quoteCh) {
381                                if (AtChar<C,'&'>(cur())) {
382                                        Parse_Reference();
383                                        ScanTo(Quote);
384                                }
385                                else if (AtQuote<C>(cur())) {
386                                        Advance(1);
387                                }
388                                else /* if (AtChar<C,'<'>(cur())) */{
389                                        Error_action(text_or_markup_start, AbsPos()); 
390                                        break;
391                                }
392                        }
393                        att_val_end = AbsPos();
394                        Advance(1); 
395                        if (at_xmlns<C>(cur()+att_name_start-AbsPos())) {
396                                Namespace_action(att_name_start, att_name_end,
397                                                 att_val_start, att_val_end);
398                        }
399                        else {
400                                AttributeValue_action(att_name_start, att_name_end,
401                                                      att_val_start, att_val_end);
402                        }
403                        /* Now check for end or repeat. Avoid whitespace scan if possible.*/
404                        if (AtChar<C,'>'>(cur())) {
405                                Advance(1);
406                                StartTag_action(text_or_markup_start, AbsPos());
407                                break;
408                        }
409                        else if (at_EmptyElementDelim<C>(cur())) {
410                                Advance(2);
411                                EmptyElement_action(text_or_markup_start, AbsPos());
412                                break;
413                        }
414                        ScanTo(NonWS);
415                        if (AtChar<C,'>'>(cur())) {
416                                Advance(1);
417                                StartTag_action(text_or_markup_start, AbsPos());
418                                break;
419                        }
420                        else if (at_EmptyElementDelim<C>(cur())) {
421                                Advance(2);
422                                EmptyElement_action(text_or_markup_start, AbsPos());
423                                break;
424                        }
425                        else if (AbsPos() == att_val_end + 1) { 
426                                /* No WS following att value */
427                                Error_action(text_or_markup_start, AbsPos());
428                                break;
429                        }
430                } while (1);
431        }
432}
433
434template <CodeUnit_Base C>
435inline void ParsingEngine<C>::text_if_nonnull_action(){
436        if (AbsPos() > text_or_markup_start) {
437                Text_action(text_or_markup_start, AbsPos());
438                text_or_markup_start = AbsPos();
439        }
440}
441
442template <CodeUnit_Base C>
443inline void ParsingEngine<C>::ParseContent() {
444        DocumentStart_action(); 
445        do {
446                text_or_markup_start = AbsPos();
447                ScanTo(MarkupStart); /* '<', '&', or ']' for ']]>' test */
448/*              if (AtChar<C,'<'>(cur())) {
449                        text_if_nonnull_action();
450                        Parse_Markup<C>();
451                }*/
452                if (at_ElementTag_Start<C>(cur())) {
453                        text_if_nonnull_action();
454                        Parse_StartTag();
455                }
456                else if (at_EndTag_Start<C>(cur())) {
457                        text_if_nonnull_action();
458                        Parse_EndTag();
459                }
460                else if (at_Comment_Start<C>(cur())) {
461                        text_if_nonnull_action();
462                        Parse_Comment();
463                }
464                else if (AtChar<C,'&'>(cur())) {
465                        text_if_nonnull_action();
466                        Parse_Reference();
467                }
468                else if (at_CDATA_Start<C>(cur())) {
469                        text_if_nonnull_action();
470                        Parse_CDATA();
471                }
472                else if (at_PI_Start<C>(cur())) {
473                        text_if_nonnull_action();
474                        Parse_PI();
475                }
476                else if (at_CDATA_End<C>(cur())) {
477                        text_if_nonnull_action();
478                        Advance(3);
479                        Error_action(AbsPos()-3, AbsPos());
480                }
481                else if (at_EOF()) {
482                        text_if_nonnull_action();
483                        break;
484                }
485                else {
486                        Advance(1);
487                        continue;
488                }
489        } while (1);
490        DocumentEnd_action();   
491}
492
493
494template <CodeUnit_Base C>
495inline void ParsingEngine<C>::Parse_DocType (){
496
497        int old_abspos, start_pos;
498        ScanTo(NonWS);
499        start_pos = AbsPos();
500       
501        if (at_DOCTYPE_start<C>(cur()))
502        Advance(9);
503        else{
504//              printf("No Document definition!\n");
505                return;
506        }
507        requireWS();
508       
509        ScanTo(NameFollow);
510       
511        old_abspos = AbsPos(); 
512    ScanTo(NonWS);
513    if(at_SYSTEM<C>(cur())||at_PUBLIC<C>(cur())){
514        if(old_abspos == AbsPos())
515                Error_action(start_pos, AbsPos());
516        Parse_ExternalID();
517    }
518   
519    ScanTo(NonWS);     
520
521        if (AtChar<C,'['>(cur())){
522                Advance(1);
523                Parse_IntSubset();
524                if (AtChar<C,']'>(cur()))
525                        Advance(1);
526                else
527                        Error_action(start_pos, AbsPos()); 
528                ScanTo(NonWS);
529        }
530       
531        if (AtChar<C,'>'>(cur())){
532                Advance(1);   
533                Doctype_action(start_pos, AbsPos());
534        }
535}
536
537template <CodeUnit_Base C>
538inline void ParsingEngine<C>::Parse_ExternalID (){
539
540        if(at_SYSTEM<C>(cur())){
541                Advance(6);
542                requireWS();
543                Parse_MatchedQuote (); /*  SystemLiteral */
544        }
545        else if (at_PUBLIC<C>(cur())){
546                Advance(6);
547                requireWS();
548                Parse_MatchedQuote ();/*  PubidLiteral */
549                requireWS();
550                Parse_MatchedQuote ();/*  SystemLiteral */
551        }
552        else
553                Error_action(text_or_markup_start, AbsPos()); 
554}
555
556template <CodeUnit_Base C>
557inline void ParsingEngine<C>::Parse_MatchedQuote (){
558        unsigned char quoteCh;
559        if(AtQuote<C>(cur())){
560                quoteCh = cur()[0];
561                Advance(1);
562        }
563        ScanTo(Quote);                 
564        while (cur()[0] != quoteCh){
565                Advance(1);
566                ScanTo(Quote);
567        }
568        Advance(1);
569}
570
571template <CodeUnit_Base C>
572inline void ParsingEngine<C>::Parse_IntSubset (){
573       
574        while(1){
575                ScanTo(NonWS); 
576                text_or_markup_start = AbsPos();
577                if (AtChar<C,'%'>(cur()))
578                        Parse_PEReference();   
579                else if (AtChar<C,'<'>(cur())){
580                        Advance(1);
581
582                        if (AtChar<C,'?'>(cur())){
583                                Parse_PI();
584                        }
585                        else if(AtChar<C,'!'>(cur())){
586                                Advance(1);
587                                if(at_DoubleHyphen<C>(cur()))
588                                        Parse_Comment();
589                                else if(at_ELEMENT<C>(cur()))
590                                        Parse_Elementdecl();
591                                else if(at_ATTLIST<C>(cur()))
592                                        Parse_AttlistDecl();
593                                else if(at_ENTITY<C>(cur()))
594                                        Parse_Entitydecl();
595                                else if(at_NOTATION<C>(cur()))
596                                        Parse_Notationdecl();                   
597                                       
598                        }
599                        else
600                                Error_action(text_or_markup_start, AbsPos()); 
601                }
602                else if (AtChar<C,']'>(cur())){
603                        break;
604                }
605                else
606                        Error_action(text_or_markup_start, AbsPos()); 
607        }
608}
609
610
611template <CodeUnit_Base C>
612inline void ParsingEngine<C>::Parse_PEReference (){
613
614        Advance(1); /* Skip "%". */
615        ScanTo(NameFollow); 
616        if (AtChar<C,';'>(cur())) {
617                Advance(1);
618                PEReference_action(text_or_markup_start, AbsPos());
619        }
620        else
621                Error_action(text_or_markup_start, AbsPos());
622}
623
624
625template <CodeUnit_Base C>
626inline void ParsingEngine<C>::Parse_Elementdecl (){
627
628        Advance(7); /* Skip "<!ELEMENT". */
629
630    requireWS();
631        ScanTo(NameFollow);
632        requireWS();
633       
634        /* Start parsing "contentspec"*/
635        if (at_EMPTY<C>(cur()))
636        Advance(5);
637    else if (at_ANY<C>(cur()))
638        Advance(3);
639    else {
640        if (AtChar<C,'('>(cur()))
641                        Advance(1);
642                ScanTo(NonWS);
643                if (at_PCDATA<C>(cur()))
644                        Parse_RemainedMixed();
645                else
646                        Parse_RemainedChildren();
647    }
648               
649        if (AtChar<C,'>'>(cur())) {
650                Advance(1);
651                Elementdecl_action(text_or_markup_start, AbsPos());
652        }
653        else
654                Error_action(text_or_markup_start, AbsPos());
655}
656template <CodeUnit_Base C>
657inline void ParsingEngine<C>::Parse_RemainedMixed (){
658       
659        Advance(7);  /* Skip "#PCDATA". */
660   
661    if (AtChar<C,')'>(cur())){
662        if (AtChar<C,'*'>(cur()))
663                Advance(2);
664                else
665                        Advance(1);
666    }
667    else{
668        ScanTo(NonWS);
669        while(!at_Para_star<C>(cur())){
670                if (AtChar<C,'|'>(cur())){
671                                Advance(1);
672                                ScanTo(NonWS);
673                                ScanTo(NameFollow);
674                                ScanTo(NonWS);
675                }
676        }
677        Advance(2);
678    }
679}
680
681
682template <CodeUnit_Base C>
683inline void ParsingEngine<C>::Parse_RemainedChildren (){
684        Parse_Cp();
685        ScanTo(NonWS);
686        if(AtChar<C,'|'>(cur())){
687                Advance(1);
688                ScanTo(NonWS);
689                Parse_Cp();
690                ScanTo(NonWS);
691                while(!AtChar<C,')'>(cur())){
692                        if(AtChar<C,'|'>(cur()))
693                                Advance(1);
694                        ScanTo(NonWS);
695                        Parse_Cp();
696                        ScanTo(NonWS);
697                }
698                Advance(1);
699        }
700        else 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        }
717        else
718                Error_action(text_or_markup_start, AbsPos());
719               
720        if (AtChar<C,'?'>(cur())||AtChar<C,'*'>(cur())||AtChar<C,'+'>(cur()))
721                Advance(1);
722}
723
724template <CodeUnit_Base C>
725inline void ParsingEngine<C>::Parse_Cp (){
726        if (AtChar<C,'('>(cur())){
727                Advance(1);
728                ScanTo(NonWS);
729                Parse_RemainedChildren();
730        }
731        else{
732                ScanTo(NameFollow);
733                if (AtChar<C,'?'>(cur())||AtChar<C,'*'>(cur())||AtChar<C,'+'>(cur()))
734                        Advance(1);
735        }
736}
737
738template <CodeUnit_Base C>
739inline void ParsingEngine<C>::Parse_AttlistDecl (){
740       
741        int old_abspos;
742        Advance(7); /* Skip "ATTLIST. */
743        requireWS();
744        ScanTo(NameFollow);
745       
746        old_abspos = AbsPos();
747        ScanTo(NonWS);
748        while(!AtChar<C,'>'>(cur())) {
749                if(old_abspos == AbsPos())
750                Error_action(text_or_markup_start, AbsPos());
751        ScanTo(NameFollow);
752        requireWS();
753        if (at_CDATA<C>(cur()))
754                Advance(5);
755        else if(at_ID<C>(cur()))
756                Advance(2);
757        else if(at_IDREF<C>(cur()))
758                Advance(5);
759        else if(at_IDREFS<C>(cur()))
760                Advance(6);
761        else if(at_ENTITY<C>(cur()))
762                Advance(6);
763        else if(at_ENTITIES<C>(cur()))
764                Advance(8);
765        else if(at_NMTOKEN<C>(cur()))
766                Advance(7);
767        else if(at_NMTOKENS<C>(cur()))
768                Advance(8);
769        else if(at_NOTATION<C>(cur())){ /* NotationType = 'NOTATION' S Enumeration
770                                                                         when Nmtoken = Name */
771                Advance(8);
772                        requireWS();
773                Parse_Enumeration();
774        }
775        else if(AtChar<C,'('>(cur()))
776                Parse_Enumeration();
777        else
778                Error_action(text_or_markup_start, AbsPos());
779        requireWS();
780        Parse_DefaultDecl();
781        old_abspos = AbsPos();
782                ScanTo(NonWS);
783        }
784        Advance(1);
785        AttlistDecl_action(text_or_markup_start, AbsPos());
786}
787
788template <CodeUnit_Base C>
789inline void ParsingEngine<C>::Parse_Enumeration (){
790
791        if(AtChar<C,'('>(cur()))
792                Advance(1);
793        else
794                Error_action(text_or_markup_start, AbsPos());
795        ScanTo(NonWS);
796        ScanTo(NameFollow);
797        ScanTo(NonWS);
798        while(AtChar<C,'|'>(cur())){
799                Advance(1);
800                ScanTo(NameFollow);
801                ScanTo(NonWS);
802        }
803        if (AtChar<C,')'>(cur())) 
804                Advance(1);
805        else
806                Error_action(text_or_markup_start, AbsPos());
807}
808
809template <CodeUnit_Base C>
810inline void ParsingEngine<C>::Parse_DefaultDecl (){
811        if(at_REQUIRED<C>(cur()))
812                Advance(9);
813        else if(at_IMPLIED<C>(cur()))
814                Advance(8);
815        else if(at_FIXED<C>(cur())){
816                Advance(6);
817                requireWS();
818        }
819        else if(AtQuote<C>(cur())){
820                Parse_AttValue();
821        }
822        else
823                Error_action(text_or_markup_start, AbsPos());
824}
825
826template <CodeUnit_Base C>
827inline void ParsingEngine<C>::Parse_Entitydecl (){
828       
829        int old_abspos;
830        Advance(6); /* Skip "ENTITY. */
831        requireWS();
832       
833        if (AtChar<C,'%'>(cur())){
834                Advance(1);
835                requireWS();
836                ScanTo(NameFollow);
837                requireWS();
838                if(at_SYSTEM<C>(cur())||at_PUBLIC<C>(cur())){
839                Parse_ExternalID();             
840        }
841        else if(AtQuote<C>(cur())){
842                Parse_AttValue(); /* Not parse PEReference*/
843        }
844        else
845                Error_action(text_or_markup_start, AbsPos());
846        }
847        else{
848                ScanTo(NameFollow);
849                requireWS();
850               
851                if(at_SYSTEM<C>(cur())||at_PUBLIC<C>(cur())){
852                Parse_ExternalID();
853                ScanTo(NonWS);
854                if(at_NOTATION<C>(cur())){
855                        if(old_abspos == AbsPos())
856                                Error_action(text_or_markup_start, AbsPos());
857                        else
858                                Advance(5);
859                        requireWS();
860                        ScanTo(NameFollow);
861                }
862        }
863        else if(AtQuote<C>(cur())){
864                Parse_AttValue(); /* Not parse PEReference*/
865        }
866        else
867                Error_action(text_or_markup_start, AbsPos());
868        }
869        ScanTo(NonWS);
870        if (AtChar<C,'>'>(cur())){
871                Advance(1);
872                Entitydecl_action(text_or_markup_start, AbsPos());
873        }
874        else
875                Error_action(text_or_markup_start, AbsPos());
876}
877
878template <CodeUnit_Base C>
879inline void ParsingEngine<C>::Parse_Notationdecl (){
880       
881        int old_abspos;
882        Advance(8); /* Skip "NOTATION. */
883        requireWS();
884        ScanTo(NameFollow);
885        requireWS();
886        if(at_SYSTEM<C>(cur())){
887                Advance(6);
888                requireWS();
889                Parse_MatchedQuote (); /*  SystemLiteral */
890        }
891        else if (at_PUBLIC<C>(cur())){
892                Advance(6);
893                requireWS();
894                Parse_MatchedQuote (); /*  PubidLiteral */
895                ScanTo(NonWS);
896                if (!AtChar<C,'>'>(cur())){
897                        if (old_abspos == AbsPos())
898                                Error_action(text_or_markup_start, AbsPos());
899                        Parse_MatchedQuote (); /*  SystemLiteral */
900                }
901        }
902        else
903                Error_action(text_or_markup_start, AbsPos());
904        ScanTo(NonWS);
905        if (AtChar<C,'>'>(cur())) {
906                Advance(1);
907                Notationdecl_action(text_or_markup_start, AbsPos());
908        }
909        else
910                Error_action(text_or_markup_start, AbsPos());
911}
912
913template <CodeUnit_Base C>
914inline void ParsingEngine<C>::requireWS(){
915       
916    int old_abspos = AbsPos(); 
917    ScanTo(NonWS);
918    if(old_abspos == AbsPos())
919        Error_action(text_or_markup_start, AbsPos());
920}
921
922template <CodeUnit_Base C>
923inline void ParsingEngine<C>::Parse_AttValue(){
924       
925        int     quoteCh = cur()[0];
926        Advance(1); /* Skip " or ' */
927
928        ScanTo(Quote);                 
929        while (cur()[0] != quoteCh){
930                if (AtChar<C,'&'>(cur())){
931                        Parse_Reference();
932                        ScanTo(Quote);
933                }
934                else if (AtQuote<C>(cur())) {
935                        Advance(1);
936                        ScanTo(Quote);
937                }
938                else /* if (AtChar<C,'<'>(cur())) */
939                        Error_action(text_or_markup_start, AbsPos());
940        }
941        Advance(1);
942}
943
944template <CodeUnit_Base C>
945inline void ParsingEngine<C>::Parse_Prolog(){
946        ScanTo(NonWS);
947        int old_pos = AbsPos();
948        while (!at_DOCTYPE_start<C>(cur())) {
949                if (at_Comment_Start<C>(cur())) 
950                        Parse_Comment();
951                else if (at_PI_Start<C>(cur()))
952                                Parse_PI();
953                else{
954                        Prolog_action(old_pos, AbsPos());
955                        return;
956                }
957                ScanTo(NonWS);
958        }
959        Parse_DocType();
960        ScanTo(NonWS);
961        while(at_Comment_Start<C>(cur()) || at_PI_Start<C>(cur()) ){
962                if (at_Comment_Start<C>(cur()))
963                        Parse_Comment();
964                else 
965                        Parse_PI();
966                ScanTo(NonWS);
967        }
968        Prolog_action(old_pos, AbsPos());
969}
970
971
972
Note: See TracBrowser for help on using the repository browser.