source: trunk/src/engine.c @ 91

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

ATTLIST semantics

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