source: trunk/src/engine.c @ 84

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

Separate CDATA start/end actions as in expat.

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