source: trunk/src/engine.c @ 94

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

Add Notation table.

File size: 30.8 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         StrictWellFormedness=false;
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
151template <CodeUnit_Base C>
152inline int ParsingEngine<C>::LengthFrom(int start_pos) const {
153  return buffer_base_pos + buffer_rel_pos - start_pos;
154}
155
156
157
158template <CodeUnit_Base C>
159inline int ParsingEngine<C>::BufferRelPos() const {
160  return buffer_rel_pos;
161}
162
163
164template <CodeUnit_Base C>
165inline bool ParsingEngine<C>::at_EOF() const {
166  return (buffer_rel_pos >= buffer_limit_pos) && 
167         (buffer_limit_pos < BUFFER_SIZE);
168}
169
170template <CodeUnit_Base C>
171inline void ParsingEngine<C>::Advance(int n) {
172        int preserve_pos;
173        buffer_rel_pos += n;
174#ifndef OMIT_BITBUFFER_LIMIT_TEST_IN_ADVANCE
175  if (buffer_rel_pos >= BUFFER_SIZE) {
176        FinalizeBuffer_action(preserve_pos);
177        AdvanceBuffers(preserve_pos);
178  }
179#endif
180}
181
182
183#ifndef OPTIMIZE_SHORT_SCAN
184template <CodeUnit_Base C>
185inline void ParsingEngine<C>::ScanTo(int item) {
186        int preserve_pos;
187  buffer_rel_pos = bitstream_scan(buf->item_stream[item], 
188                                      buffer_rel_pos);
189  while (buffer_rel_pos >= BUFFER_SIZE) {
190        FinalizeBuffer_action(preserve_pos);
191        AdvanceBuffers(preserve_pos);
192        buffer_rel_pos = bitstream_scan(buf->item_stream[item], buffer_rel_pos);
193  }
194}
195#endif
196
197template <CodeUnit_Base C>
198inline void ParsingEngine<C>::ScanToMarkupStart() {
199        int preserve_pos;
200        text_or_markup_start = AbsPos();
201        buffer_rel_pos = bitstream_scan(buf->item_stream[MarkupStart], buffer_rel_pos);
202        while (buffer_rel_pos >= BUFFER_SIZE) {
203                Text_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
204                text_or_markup_start = AbsPos();
205                FinalizeBuffer_action(preserve_pos);
206                AdvanceBuffers(preserve_pos);
207                buffer_rel_pos = bitstream_scan(buf->item_stream[MarkupStart], buffer_rel_pos);
208        }
209}
210
211template <CodeUnit_Base C>
212inline void ParsingEngine<C>::ScanToCD_End_check() {
213        int preserve_pos;
214        buffer_rel_pos = bitstream_scan(buf->item_stream[CD_End_check], buffer_rel_pos);
215        while (buffer_rel_pos >= BUFFER_SIZE) {
216                Text_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
217                text_or_markup_start = AbsPos();
218                FinalizeBuffer_action(preserve_pos);
219                AdvanceBuffers(preserve_pos);
220                buffer_rel_pos = bitstream_scan(buf->item_stream[CD_End_check], buffer_rel_pos);
221        }
222}
223
224#ifdef OPTIMIZE_SHORT_SCAN
225template <CodeUnit_Base C>
226inline void ParsingEngine<C>::ScanTo(int item) {
227  SIMD_type * stream = buf->item_stream[item];
228  unsigned long * bitstream_ptr = (unsigned long *) (((intptr_t) stream) + buffer_rel_pos/8);
229  unsigned long bitstream_slice = *bitstream_ptr >> buffer_rel_pos % 8;
230  if (bitstream_slice != 0) {
231    buffer_rel_pos += __builtin_ctzl(bitstream_slice);
232  }
233  else {
234    buffer_rel_pos = (buffer_rel_pos & -8) + 8*sizeof(unsigned long);
235    buffer_rel_pos += bitstream_scan0((SIMD_type *) &bitstream_ptr[1]);
236    while (buffer_rel_pos >= BUFFER_BLOCKS * BLOCKSIZE) {
237      buffer_rel_pos = BUFFER_BLOCKS * BLOCKSIZE;
238      FinalizeBuffer_action(preserve_pos);
239          AdvanceBuffers(preserve_pos);
240      buffer_rel_pos = bitstream_scan(buf->item_stream[item], buffer_rel_pos);
241    }
242  }
243}
244#endif
245
246
247/* Parse a markup item beginning '<' */
248template <CodeUnit_Base C>
249inline void ParsingEngine<C>::Parse_Markup() {
250        text_or_markup_start = AbsPos();
251        if (at_ElementTag_Start<C>(cur())) {
252                Parse_StartTag();
253        }
254        else if (at_EndTag_Start<C>(cur())) {
255                Parse_EndTag();
256        }
257        else if (at_Comment_Start<C>(cur())) {
258                Parse_Comment();
259        }
260        else if (at_CDATA_Start<C>(cur())) {
261                Parse_CDATA();
262        }
263        else if (at_PI_Start<C>(cur())) {
264                Parse_PI();
265        }
266        else {
267                Advance(1);
268                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
269        }
270}
271
272/* Parse a comment beginning "<!--" */
273template <CodeUnit_Base C>
274inline void ParsingEngine<C>::Parse_Comment() {
275
276        Advance(4); /* Skip "<!--". */
277        ScanTo(Hyphen);
278        while (!at_DoubleHyphen<C>(cur())) {
279                Advance(2); /* Skip hyphen-nonhyphen pair */
280                ScanTo(Hyphen); 
281        }
282        if (at_Comment_End<C>(cur())) {
283                Advance(3); /* Skip "-->". */
284                Comment_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
285        }
286        else {
287                Advance(2);  /* "--" */
288                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
289        }
290}
291
292/* Parse an end tag beginning "</" */
293template <CodeUnit_Base C>
294inline void ParsingEngine<C>::Parse_EndTag() {
295        Advance(2); /* Skip "</". */
296        ScanTo(NameFollow);
297        if (AtChar<C,'>'>(cur())) {
298                Advance(1);
299                EndTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
300        }
301        else {
302                ScanTo(NonWS);
303                if (AtChar<C,'>'>(cur())) {
304                        Advance(1);
305                        EndTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
306                }
307                else Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
308        }
309}
310
311/* Parse a CDATA section beginning "<![CDATA". */
312template <CodeUnit_Base C>
313inline void ParsingEngine<C>::Parse_CDATA() {
314        Advance(8); /* Skip "<![CDATA". */
315        if (!AtChar<C,'['>(cur())) {
316                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
317        }
318        else { 
319                Advance(1);
320                CDATA_start_action(GetCodeUnitPtr(text_or_markup_start));
321                text_or_markup_start = AbsPos();
322                ScanTo(CD_End_check);
323                while (!at_CDATA_End<C>(cur())) {
324                        Advance(1);
325                        ScanTo(CD_End_check);
326                }
327                Text_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
328                Advance(3); /* Skip "]]>". */
329                CDATA_end_action(GetCodeUnitPtr(AbsPos()));
330        }
331}
332
333template <CodeUnit_Base C>
334inline void ParsingEngine<C>::Parse_Reference() {
335        Advance(1);  // skip "&"
336        ScanTo(NameFollow);  /* Name delimiter */
337        if (!AtChar<C,';'>(cur())) {
338                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
339        }
340        else {
341                Advance(1);
342                Reference_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
343        }
344}
345
346template <CodeUnit_Base C>
347inline void ParsingEngine<C>::Parse_PI (){
348        Advance(2); /* Skip "<?". */
349        int target_start = AbsPos();
350        // Check for illegal [Xx][Mm][Ll] target.
351        if (at_XxMmLll_WS<C>(cur())) {
352                Advance(4);
353                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
354                return;
355        } 
356        ScanTo(NameFollow);  /* Name delimiter */
357        PI_Target_action(GetCodeUnitPtr(target_start), LengthFrom(target_start));
358        ScanTo(QMark);
359        while (!at_PI_End<C>(cur())) {
360                Advance(1);
361                ScanTo(QMark);
362        }
363        Advance(2); /* Skip "?>". */
364        PI_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
365}
366 
367/* Parse a start or empty element tag. */
368template <CodeUnit_Base C>
369inline void ParsingEngine<C>::Parse_StartTag (){
370        int att_name_start;
371        int att_val_start;
372        int att_name_end, att_val_end;
373        unsigned char quoteCh;
374        Advance(1);
375        ScanTo(NameFollow);  /* Name delimiter: WS, "/" or ">" */
376        ElementName_action(GetCodeUnitPtr(text_or_markup_start+1), LengthFrom(text_or_markup_start+1));
377        /* The following test optimizes the most common case of a
378        start tag with no attributes.  */
379        if (AtChar<C,'>'>(cur())) {
380                Advance(1);
381                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
382        }
383        else {
384                ScanTo(NonWS);
385                if (AtChar<C,'>'>(cur())) {
386                        Advance(1);
387                        StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
388                }
389                else if (at_EmptyElementDelim<C>(cur())) {
390                        Advance(2);
391                        EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
392                }
393                else do {
394                        /* Must be an attribute-value pair or error. */
395                        att_name_start = AbsPos();
396                        ScanTo(NameFollow);
397                        att_name_end = AbsPos();
398                        int lgth = att_name_end-att_name_start;
399               
400                        int attID = model_info->getOrInsertGlobalAttName(GetCodeUnitPtr(att_name_start), lgth);
401                        if (attID >= LastAttOccurrence.size()) LastAttOccurrence.push_back(0);
402                        else {
403                                if (LastAttOccurrence[attID] > text_or_markup_start) {
404                                        Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start)); /* Duplicate attribute. */
405                                        break;
406                                }                       
407                        }
408                        LastAttOccurrence[attID] = att_name_start;
409                        /* The following optimized tests handle the frequently occurring
410                        case that there are no blanks on either side of the equals sign.
411                        In many cases, the very first test handles 100% of actual
412                        attribute-value pairs encountered. */
413                        if (at_EqualsQuote<C>(cur())) {
414                                quoteCh = cur()[1];
415                                Advance(2); 
416                        }
417                        else {
418                                ScanTo(NonWS);
419                                if (!AtChar<C,'='>(cur())) {
420                                        Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start)); 
421                                        break;
422                                }
423                                ScanTo(NonWS);
424                                quoteCh = cur()[0];
425                                if (!AtQuote<C>(cur())) {
426                                        Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start)); 
427                                        break;
428                                }
429                                Advance(1);
430                        }
431                        att_val_start = AbsPos();
432                        ScanTo(Quote);
433                        while (cur()[0] != quoteCh) {
434                                if (AtChar<C,'&'>(cur())) {
435                                        Parse_Reference();
436                                        ScanTo(Quote);
437                                }
438                                else if (AtQuote<C>(cur())) {
439                                        Advance(1);
440                                }
441                                else /* if (AtChar<C,'<'>(cur())) */{
442                                        Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start)); 
443                                        break;
444                                }
445                        }
446                        att_val_end = AbsPos();
447                        Advance(1); 
448                        if (at_xmlns<C>(cur()+att_name_start-AbsPos())) {
449                                Namespace_action(GetCodeUnitPtr(att_name_start), att_name_end - att_name_start,
450                                                 GetCodeUnitPtr(att_val_start), att_val_end - att_val_start);
451                        }
452                        else {
453                                AttributeValue_action(GetCodeUnitPtr(att_name_start), att_name_end - att_name_start,
454                                                 GetCodeUnitPtr(att_val_start), att_val_end - att_val_start);
455                        }
456                        /* Now check for end or repeat. Avoid whitespace scan if possible.*/
457                        if (AtChar<C,'>'>(cur())) {
458                                Advance(1);
459                                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
460                                break;
461                        }
462                        else if (at_EmptyElementDelim<C>(cur())) {
463                                Advance(2);
464                                EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
465                                break;
466                        }
467                        ScanTo(NonWS);
468                        if (AtChar<C,'>'>(cur())) {
469                                Advance(1);
470                                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
471                                break;
472                        }
473                        else if (at_EmptyElementDelim<C>(cur())) {
474                                Advance(2);
475                                EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
476                                break;
477                        }
478                        else if (AbsPos() == att_val_end + 1) { 
479                                /* No WS following att value */
480                                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
481                                break;
482                        }
483                } while (1);
484        }
485}
486
487template <CodeUnit_Base C>
488inline void ParsingEngine<C>::text_if_nonnull_action(){
489        if (AbsPos() > text_or_markup_start) {
490                Text_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
491                text_or_markup_start = AbsPos();
492        }
493}
494
495template <CodeUnit_Base C>
496inline void ParsingEngine<C>::ParseContent() {
497        DocumentStart_action(); 
498        do {
499                text_or_markup_start = AbsPos();
500                ScanToMarkupStart(); /* '<', '&', or ']' for ']]>' test */
501/*              if (AtChar<C,'<'>(cur())) {
502                        text_if_nonnull_action();
503                        Parse_Markup<C>();
504                }*/
505                if (at_ElementTag_Start<C>(cur())) {
506                        text_if_nonnull_action();
507                        Parse_StartTag();
508                }
509                else if (at_EndTag_Start<C>(cur())) {
510                        text_if_nonnull_action();
511                        Parse_EndTag();
512                }
513                else if (at_Comment_Start<C>(cur())) {
514                        text_if_nonnull_action();
515                        Parse_Comment();
516                }
517                else if (AtChar<C,'&'>(cur())) {
518                        text_if_nonnull_action();
519                        Parse_Reference();
520                }
521                else if (at_CDATA_Start<C>(cur())) {
522                        text_if_nonnull_action();
523                        Parse_CDATA();
524                }
525                else if (at_PI_Start<C>(cur())) {
526                        text_if_nonnull_action();
527                        Parse_PI();
528                }
529                else if (at_CDATA_End<C>(cur())) {
530                        text_if_nonnull_action();
531                        Advance(3);
532                        Error_action(GetCodeUnitPtr(AbsPos()-3), 3);
533                }
534                else if (at_EOF()) {
535                        text_if_nonnull_action();
536                        break;
537                }
538                else {
539                        Advance(1);
540                        continue;
541                }
542        } while (1);
543        DocumentEnd_action();   
544}
545
546
547template <CodeUnit_Base C>
548inline void ParsingEngine<C>::Parse_DocType (){
549
550        int old_abspos, start_pos;
551        ScanTo(NonWS);
552        start_pos = AbsPos();
553       
554        if (at_DOCTYPE_start<C>(cur()))
555        Advance(9);
556        else{
557//              printf("No Document definition!\n");
558                return;
559        }
560        requireWS();
561       
562        ScanTo(NameFollow);
563       
564        old_abspos = AbsPos(); 
565    ScanTo(NonWS);
566    if(at_SYSTEM<C>(cur())||at_PUBLIC<C>(cur())){
567        if(old_abspos == AbsPos())
568                Error_action(GetCodeUnitPtr(start_pos), LengthFrom(start_pos));
569        Parse_ExternalID();
570    }
571   
572    ScanTo(NonWS);     
573
574        if (AtChar<C,'['>(cur())){
575                Advance(1);
576                Parse_IntSubset();
577                if (AtChar<C,']'>(cur()))
578                        Advance(1);
579                else
580                        Error_action(GetCodeUnitPtr(start_pos), LengthFrom(start_pos)); 
581                ScanTo(NonWS);
582        }
583       
584        if (AtChar<C,'>'>(cur())){
585                Advance(1);   
586                Doctype_action(GetCodeUnitPtr(start_pos), LengthFrom(start_pos));
587        }
588}
589
590template <CodeUnit_Base C>
591inline void ParsingEngine<C>::Parse_ExternalID (){
592
593        if(at_SYSTEM<C>(cur())){
594                Advance(6);
595                requireWS();
596                Parse_MatchedQuote (); /*  SystemLiteral */
597        }
598        else if (at_PUBLIC<C>(cur())){
599                Advance(6);
600                requireWS();
601                Parse_MatchedQuote ();/*  PubidLiteral */
602                requireWS();
603                Parse_MatchedQuote ();/*  SystemLiteral */
604        }
605        else
606                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start)); 
607}
608
609template <CodeUnit_Base C>
610inline void ParsingEngine<C>::Parse_MatchedQuote (){
611        unsigned char quoteCh;
612        if(AtQuote<C>(cur())){
613                quoteCh = cur()[0];
614                Advance(1);
615        }
616        ScanTo(Quote);                 
617        while (cur()[0] != quoteCh){
618                Advance(1);
619                ScanTo(Quote);
620        }
621        Advance(1);
622}
623
624template <CodeUnit_Base C>
625inline void ParsingEngine<C>::Parse_IntSubset (){
626       
627        while(1){
628                ScanTo(NonWS); 
629                text_or_markup_start = AbsPos();
630                if (AtChar<C,'%'>(cur()))
631                        Parse_PEReference();   
632                else if (AtChar<C,'<'>(cur())){
633                        Advance(1);
634
635                        if (AtChar<C,'?'>(cur())){
636                                Parse_PI();
637                        }
638                        else if(AtChar<C,'!'>(cur())){
639                                Advance(1);
640                                if(at_DoubleHyphen<C>(cur()))
641                                        Parse_Comment();
642                                else if(at_ELEMENT<C>(cur()))
643                                        Parse_Elementdecl();
644                                else if(at_ATTLIST<C>(cur()))
645                                        Parse_AttlistDecl();
646                                else if(at_ENTITY<C>(cur()))
647                                        Parse_Entitydecl();
648                                else if(at_NOTATION<C>(cur()))
649                                        Parse_Notationdecl();                   
650                                       
651                        }
652                        else
653                                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start)); 
654                }
655                else if (AtChar<C,']'>(cur())){
656                        break;
657                }
658                else
659                        Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start)); 
660        }
661}
662
663
664template <CodeUnit_Base C>
665inline void ParsingEngine<C>::Parse_PEReference (){
666
667        Advance(1); /* Skip "%". */
668        ScanTo(NameFollow); 
669        if (AtChar<C,';'>(cur())) {
670                Advance(1);
671                PEReference_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
672        }
673        else
674                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
675}
676
677
678template <CodeUnit_Base C>
679inline void ParsingEngine<C>::Parse_Elementdecl (){
680
681        Advance(7); /* Skip "<!ELEMENT". */
682
683    requireWS();
684    int name_start = AbsPos();
685        ScanTo(NameFollow);
686        int lgth = AbsPos() - name_start;
687        int elemID = model_info->getOrInsertGlobalElement(GetCodeUnitPtr(name_start), lgth);
688        requireWS();
689       
690        /* Start parsing "contentspec"*/
691        if (at_EMPTY<C>(cur()))
692        Advance(5);
693    else if (at_ANY<C>(cur()))
694        Advance(3);
695    else {
696        if (AtChar<C,'('>(cur()))
697                        Advance(1);
698                ScanTo(NonWS);
699                if (at_PCDATA<C>(cur()))
700                        Parse_RemainingMixed();
701                else
702                        Parse_RemainingChildren();
703    }
704               
705        if (AtChar<C,'>'>(cur())) {
706                Advance(1);
707                Elementdecl_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
708        }
709        else
710                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
711}
712template <CodeUnit_Base C>
713inline void ParsingEngine<C>::Parse_RemainingMixed (){
714       
715        Advance(7);  /* Skip "#PCDATA". */
716   
717    if (AtChar<C,')'>(cur())){
718        if (AtChar<C,'*'>(cur()))
719                Advance(2);
720                else
721                        Advance(1);
722    }
723    else{
724        ScanTo(NonWS);
725        while(!at_Para_star<C>(cur())){
726                if (AtChar<C,'|'>(cur())){
727                                Advance(1);
728                                ScanTo(NonWS);
729                                ScanTo(NameFollow);
730                                ScanTo(NonWS);
731                }
732        }
733        Advance(2);
734    }
735}
736
737
738template <CodeUnit_Base C>
739inline void ParsingEngine<C>::Parse_RemainingChildren (){
740        Parse_Cp();
741        ScanTo(NonWS);
742        if(AtChar<C,'|'>(cur())){
743                Advance(1);
744                ScanTo(NonWS);
745                Parse_Cp();
746                ScanTo(NonWS);
747                while(!AtChar<C,')'>(cur())){
748                        if(AtChar<C,'|'>(cur()))
749                                Advance(1);
750                        ScanTo(NonWS);
751                        Parse_Cp();
752                        ScanTo(NonWS);
753                }
754                Advance(1);
755        }
756        else if(AtChar<C,','>(cur())){
757                Advance(1);
758                ScanTo(NonWS);
759                Parse_Cp();
760                ScanTo(NonWS);
761                while(!AtChar<C,')'>(cur())){
762                        if(AtChar<C,','>(cur()))
763                                Advance(1);
764                        ScanTo(NonWS);
765                        Parse_Cp();
766                        ScanTo(NonWS);
767                }
768                Advance(1);
769        }       
770        else if(AtChar<C,')'>(cur())){
771                Advance(1);
772        }
773        else
774                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
775               
776        if (AtChar<C,'?'>(cur())||AtChar<C,'*'>(cur())||AtChar<C,'+'>(cur()))
777                Advance(1);
778}
779
780template <CodeUnit_Base C>
781inline void ParsingEngine<C>::Parse_Cp (){
782        if (AtChar<C,'('>(cur())){
783                Advance(1);
784                ScanTo(NonWS);
785                Parse_RemainingChildren();
786        }
787        else{
788                ScanTo(NameFollow);
789                if (AtChar<C,'?'>(cur())||AtChar<C,'*'>(cur())||AtChar<C,'+'>(cur()))
790                        Advance(1);
791        }
792}
793
794template <CodeUnit_Base C>
795inline void ParsingEngine<C>::Parse_AttlistDecl (){
796       
797        int old_abspos;
798       
799        int name_start;
800        int lgth;
801       
802        int elemID;
803        int attID;
804       
805        Advance(7); /* Skip "ATTLIST. */
806        requireWS();
807       
808        name_start = AbsPos();
809        ScanTo(NameFollow);
810        lgth = AbsPos()-name_start;
811        elemID = model_info->getOrInsertGlobalElement(GetCodeUnitPtr(name_start), lgth);
812       
813        old_abspos = AbsPos();
814        ScanTo(NonWS);
815        while(!AtChar<C,'>'>(cur())) {
816                if(old_abspos == AbsPos())
817                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
818               
819        name_start = AbsPos();
820                ScanTo(NameFollow);
821                lgth = AbsPos()-name_start;
822               
823                attID = model_info->getOrInsertGlobalAttName(GetCodeUnitPtr(name_start), lgth);
824                if (attID >= LastAttOccurrence.size()) LastAttOccurrence.push_back(0);
825        ATT_info * this_info = new ATT_info;
826        this_info->globalATT_id = attID;
827        requireWS();
828        if (at_CDATA<C>(cur())){
829                Advance(5);
830                this_info->attType = CDATA_att;
831        }
832        else if(at_ID<C>(cur())){
833                Advance(2);
834                this_info->attType = ID_att;
835        }
836        else if(at_IDREF<C>(cur())){
837                Advance(5);
838                this_info->attType = IDREF_att;
839        }
840        else if(at_IDREFS<C>(cur())){
841                Advance(6);
842                this_info->attType = IDREFS_att;
843        }
844        else if(at_ENTITY<C>(cur())){
845                Advance(6);
846                this_info->attType = ENTITY_att;
847        }
848        else if(at_ENTITIES<C>(cur())){
849                Advance(8);
850                this_info->attType = ENTITIES_att;
851        }
852        else if(at_NMTOKEN<C>(cur())){
853                Advance(7);
854                this_info->attType = NMTOKEN_att;
855        }
856        else if(at_NMTOKENS<C>(cur())){
857                Advance(8);
858                this_info->attType = NMTOKENS_att;
859        }
860        else if(at_NOTATION<C>(cur())){ /* NotationType = 'NOTATION' S Enumeration
861                                                                         when Nmtoken = Name */
862                Advance(8);
863                        requireWS();
864                Parse_Notation(this_info);
865                this_info->attType = NOTATION_att;
866        }
867        else if(AtChar<C,'('>(cur())){
868                Parse_Enumeration(this_info);
869                this_info->attType = enumeration_att;
870        }
871        else
872                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
873        requireWS();
874        Parse_DefaultDecl(this_info);
875
876                ScanTo(NonWS);
877                model_info->ElementAttributeData[elemID].push_back(this_info);
878        }
879
880        Advance(1);
881        AttlistDecl_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
882}
883
884template <CodeUnit_Base C>
885inline void ParsingEngine<C>::Parse_Notation (ATT_info * this_info){
886
887        if(AtChar<C,'('>(cur()))
888                Advance(1);
889        else
890                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
891        ScanTo(NonWS);
892       
893    int name_start = AbsPos();
894        ScanTo(NameFollow);
895        int     lgth = AbsPos()-name_start;
896       
897        char *s = new char[lgth+1];
898        memcpy(s, GetCodeUnitPtr(name_start), lgth);
899        s[lgth] = '\0';
900
901        /*Notation name is not in the global table!*/
902        if(model_info->GlobalNotationTable[s]==0)
903                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
904       
905        ScanTo(NonWS);
906        while(AtChar<C,'|'>(cur())){
907                Advance(1);
908                ScanTo(NonWS);         
909                name_start = AbsPos();
910                ScanTo(NameFollow);
911                lgth = AbsPos()-name_start;
912       
913                char *s = new char[lgth+1];
914                memcpy(s, GetCodeUnitPtr(name_start), lgth);
915                s[lgth] = '\0';
916       
917                if(model_info->GlobalNotationTable[s]==0)
918                        Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
919                       
920                ScanTo(NonWS);
921        }
922        if (AtChar<C,')'>(cur())) 
923                Advance(1);
924        else
925                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
926}
927
928template <CodeUnit_Base C>
929inline void ParsingEngine<C>::Parse_Enumeration (ATT_info * this_info){
930
931        int enumCount=0;
932        if(AtChar<C,'('>(cur()))
933                Advance(1);
934        else
935                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
936        ScanTo(NonWS);
937       
938    int name_start = AbsPos();
939        ScanTo(NameFollow);
940        int     lgth = AbsPos()-name_start;
941       
942        char *s = new char[lgth+1];
943        memcpy(s, GetCodeUnitPtr(name_start), lgth);
944        s[lgth] = '\0';
945       
946        this_info->enumValues[s]=++(enumCount);
947       
948        ScanTo(NonWS);
949        while(AtChar<C,'|'>(cur())){
950                Advance(1);
951                ScanTo(NonWS);         
952                name_start = AbsPos();
953                ScanTo(NameFollow);
954                lgth = AbsPos()-name_start;
955       
956                char *s = new char[lgth+1];
957                memcpy(s, GetCodeUnitPtr(name_start), lgth);
958                s[lgth] = '\0';
959       
960                int enumID = this_info->enumValues[s];
961                if(enumID==0){ 
962                        this_info->enumValues[s]=++(enumCount);
963                        enumID = enumCount;
964                }
965                else if(!StrictWellFormedness){
966                        Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
967                }
968                ScanTo(NonWS);
969        }
970        if (AtChar<C,')'>(cur())) 
971                Advance(1);
972        else
973                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
974}
975
976template <CodeUnit_Base C>
977inline void ParsingEngine<C>::Parse_DefaultDecl (ATT_info * this_info){
978        if(at_REQUIRED<C>(cur())){
979                Advance(9);
980                this_info->defaultKind = REQUIRED_att;
981        }
982        else if(at_IMPLIED<C>(cur())){
983                Advance(8);
984                this_info->defaultKind = IMPLIED_att;
985        }
986        else {
987                if(at_FIXED<C>(cur())){
988                        Advance(6);
989                        requireWS();
990                        this_info->defaultKind = FIXED_att;
991                }
992                else this_info->defaultKind = DEFAULT_att;
993                if(AtQuote<C>(cur())){
994                        int quot_start = AbsPos()+1;
995                        Parse_AttValue();
996                        /* need to normalize */
997                        this_info->defaultValueLgth = AbsPos() - quot_start - 1;
998                       
999                        this_info->defaultValue = new unsigned char[this_info->defaultValueLgth+1];
1000                        memcpy(this_info->defaultValue, GetCodeUnitPtr(quot_start),this_info->defaultValueLgth); 
1001                        this_info->defaultValue[this_info->defaultValueLgth] = '\0';
1002                        }
1003                else
1004                        Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1005        }
1006}
1007
1008template <CodeUnit_Base C>
1009inline void ParsingEngine<C>::Parse_Entitydecl (){
1010       
1011        int entity_name_start;
1012        int entity_name_end;
1013        int old_abspos;
1014        Advance(6); /* Skip "ENTITY. */
1015        requireWS();
1016       
1017        if (AtChar<C,'%'>(cur())){
1018                Advance(1);
1019                requireWS();
1020                entity_name_start = AbsPos();
1021                ScanTo(NameFollow);
1022                entity_name_end = AbsPos();
1023                requireWS();
1024                if(at_SYSTEM<C>(cur())||at_PUBLIC<C>(cur())){
1025                Parse_ExternalID();             
1026        }
1027        else if(AtQuote<C>(cur())){
1028                Parse_AttValue(); /* Not parse PEReference*/
1029        }
1030        else
1031                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1032        }
1033        else{
1034                entity_name_start = AbsPos();
1035                ScanTo(NameFollow);
1036                entity_name_end = AbsPos();
1037                requireWS();
1038               
1039                if(at_SYSTEM<C>(cur())||at_PUBLIC<C>(cur())){
1040                Parse_ExternalID();
1041                ScanTo(NonWS);
1042                if(at_NOTATION<C>(cur())){
1043                        if(old_abspos == AbsPos())
1044                                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1045                        else
1046                                Advance(5);
1047                        requireWS();
1048                        ScanTo(NameFollow);
1049                }
1050        }
1051        else if(AtQuote<C>(cur())){
1052                Parse_AttValue(); /* Not parse PEReference*/
1053        }
1054        else
1055                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1056        }
1057        ScanTo(NonWS);
1058        if (AtChar<C,'>'>(cur())){
1059                Advance(1);
1060                Entitydecl_action(GetCodeUnitPtr(entity_name_start), entity_name_end - entity_name_start, 
1061                                  GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1062        }
1063        else
1064                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1065}
1066
1067template <CodeUnit_Base C>
1068inline void ParsingEngine<C>::Parse_Notationdecl (){
1069
1070        int old_abspos;
1071        Advance(8); /* Skip "NOTATION. */
1072        requireWS();
1073       
1074        int name_start = AbsPos();
1075        ScanTo(NameFollow);
1076        int     lgth = AbsPos()-name_start;
1077       
1078        char *s = new char[lgth+1];
1079        memcpy(s, GetCodeUnitPtr(name_start), lgth);
1080        s[lgth] = '\0';
1081
1082        int notationID = model_info->GlobalNotationTable[s];
1083        if(notationID==0){     
1084                model_info->GlobalNotationTable[s]=++(model_info->globalNotationCount);
1085                notationID = model_info->globalNotationCount;
1086        }
1087        else /*Duplicate notation name!*/
1088                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1089               
1090        requireWS();
1091        if(at_SYSTEM<C>(cur())){
1092                Advance(6);
1093                requireWS();
1094                Parse_MatchedQuote (); /*  SystemLiteral */
1095        }
1096        else if (at_PUBLIC<C>(cur())){
1097                Advance(6);
1098                requireWS();
1099                Parse_MatchedQuote (); /*  PubidLiteral */
1100                ScanTo(NonWS);
1101                if (!AtChar<C,'>'>(cur())){
1102                        if (old_abspos == AbsPos())
1103                                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1104                        Parse_MatchedQuote (); /*  SystemLiteral */
1105                }
1106        }
1107        else
1108                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1109        ScanTo(NonWS);
1110        if (AtChar<C,'>'>(cur())) {
1111                Advance(1);
1112                Notationdecl_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1113        }
1114        else
1115                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1116}
1117
1118template <CodeUnit_Base C>
1119inline void ParsingEngine<C>::requireWS(){
1120       
1121    int old_abspos = AbsPos(); 
1122    ScanTo(NonWS);
1123    if(old_abspos == AbsPos())
1124        Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1125}
1126
1127template <CodeUnit_Base C>
1128inline void ParsingEngine<C>::Parse_AttValue(){
1129       
1130        int     quoteCh = cur()[0];
1131        Advance(1); /* Skip " or ' */
1132
1133        ScanTo(Quote);                 
1134        while (cur()[0] != quoteCh){
1135                if (AtChar<C,'&'>(cur())){
1136                        Parse_Reference();
1137                        ScanTo(Quote);
1138                }
1139                else if (AtQuote<C>(cur())) {
1140                        Advance(1);
1141                        ScanTo(Quote);
1142                }
1143                else /* if (AtChar<C,'<'>(cur())) */
1144                        Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1145        }
1146        Advance(1);
1147}
1148
1149template <CodeUnit_Base C>
1150inline void ParsingEngine<C>::Parse_Prolog(){
1151        ScanTo(NonWS);
1152        int old_pos = AbsPos();
1153        while (!at_DOCTYPE_start<C>(cur())) {
1154                if (at_Comment_Start<C>(cur())) 
1155                        Parse_Comment();
1156                else if (at_PI_Start<C>(cur()))
1157                                Parse_PI();
1158                else{
1159                        Prolog_action(GetCodeUnitPtr(old_pos), LengthFrom(old_pos));
1160                        return;
1161                }
1162                ScanTo(NonWS);
1163        }
1164        Parse_DocType();
1165        ScanTo(NonWS);
1166        while(at_Comment_Start<C>(cur()) || at_PI_Start<C>(cur()) ){
1167                if (at_Comment_Start<C>(cur()))
1168                        Parse_Comment();
1169                else 
1170                        Parse_PI();
1171                ScanTo(NonWS);
1172        }
1173        Prolog_action(GetCodeUnitPtr(old_pos), LengthFrom(old_pos));
1174}
1175
1176
1177
Note: See TracBrowser for help on using the repository browser.