source: trunk/src/engine.c @ 92

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

Passing buffer pointers/lgths to markup actions.

File size: 28.5 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
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_Enumeration(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        old_abspos = AbsPos();
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_Enumeration (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        ScanTo(NameFollow);
893        ScanTo(NonWS);
894        while(AtChar<C,'|'>(cur())){
895                Advance(1);
896                ScanTo(NameFollow);
897                ScanTo(NonWS);
898        }
899        if (AtChar<C,')'>(cur())) 
900                Advance(1);
901        else
902                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
903}
904
905template <CodeUnit_Base C>
906inline void ParsingEngine<C>::Parse_DefaultDecl (ATT_info * this_info){
907        if(at_REQUIRED<C>(cur())){
908                Advance(9);
909                this_info->defaultKind = REQUIRED_att;
910        }
911        else if(at_IMPLIED<C>(cur())){
912                Advance(8);
913                this_info->defaultKind = IMPLIED_att;
914        }
915        else {
916                if(at_FIXED<C>(cur())){
917                        Advance(6);
918                        requireWS();
919                        this_info->defaultKind = FIXED_att;
920                }
921                else this_info->defaultKind = DEFAULT_att;
922                if(AtQuote<C>(cur())){
923                        int quot_start = AbsPos()+1;
924                        Parse_AttValue();
925                        /* need to normalize */
926                        this_info->defaultValueLgth = AbsPos() - quot_start - 1;
927                       
928                        this_info->defaultValue = new unsigned char[this_info->defaultValueLgth+1];
929                        memcpy(this_info->defaultValue, GetCodeUnitPtr(quot_start),this_info->defaultValueLgth); 
930                        this_info->defaultValue[this_info->defaultValueLgth] = '\0';
931                        }
932                else
933                        Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
934        }
935}
936
937template <CodeUnit_Base C>
938inline void ParsingEngine<C>::Parse_Entitydecl (){
939       
940        int entity_name_start;
941        int entity_name_end;
942        int old_abspos;
943        Advance(6); /* Skip "ENTITY. */
944        requireWS();
945       
946        if (AtChar<C,'%'>(cur())){
947                Advance(1);
948                requireWS();
949                entity_name_start = AbsPos();
950                ScanTo(NameFollow);
951                entity_name_end = AbsPos();
952                requireWS();
953                if(at_SYSTEM<C>(cur())||at_PUBLIC<C>(cur())){
954                Parse_ExternalID();             
955        }
956        else if(AtQuote<C>(cur())){
957                Parse_AttValue(); /* Not parse PEReference*/
958        }
959        else
960                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
961        }
962        else{
963                entity_name_start = AbsPos();
964                ScanTo(NameFollow);
965                entity_name_end = AbsPos();
966                requireWS();
967               
968                if(at_SYSTEM<C>(cur())||at_PUBLIC<C>(cur())){
969                Parse_ExternalID();
970                ScanTo(NonWS);
971                if(at_NOTATION<C>(cur())){
972                        if(old_abspos == AbsPos())
973                                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
974                        else
975                                Advance(5);
976                        requireWS();
977                        ScanTo(NameFollow);
978                }
979        }
980        else if(AtQuote<C>(cur())){
981                Parse_AttValue(); /* Not parse PEReference*/
982        }
983        else
984                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
985        }
986        ScanTo(NonWS);
987        if (AtChar<C,'>'>(cur())){
988                Advance(1);
989                Entitydecl_action(GetCodeUnitPtr(entity_name_start), entity_name_end - entity_name_start, 
990                                  GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
991        }
992        else
993                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
994}
995
996template <CodeUnit_Base C>
997inline void ParsingEngine<C>::Parse_Notationdecl (){
998       
999        int old_abspos;
1000        Advance(8); /* Skip "NOTATION. */
1001        requireWS();
1002        ScanTo(NameFollow);
1003        requireWS();
1004        if(at_SYSTEM<C>(cur())){
1005                Advance(6);
1006                requireWS();
1007                Parse_MatchedQuote (); /*  SystemLiteral */
1008        }
1009        else if (at_PUBLIC<C>(cur())){
1010                Advance(6);
1011                requireWS();
1012                Parse_MatchedQuote (); /*  PubidLiteral */
1013                ScanTo(NonWS);
1014                if (!AtChar<C,'>'>(cur())){
1015                        if (old_abspos == AbsPos())
1016                                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1017                        Parse_MatchedQuote (); /*  SystemLiteral */
1018                }
1019        }
1020        else
1021                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1022        ScanTo(NonWS);
1023        if (AtChar<C,'>'>(cur())) {
1024                Advance(1);
1025                Notationdecl_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1026        }
1027        else
1028                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1029}
1030
1031template <CodeUnit_Base C>
1032inline void ParsingEngine<C>::requireWS(){
1033       
1034    int old_abspos = AbsPos(); 
1035    ScanTo(NonWS);
1036    if(old_abspos == AbsPos())
1037        Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1038}
1039
1040template <CodeUnit_Base C>
1041inline void ParsingEngine<C>::Parse_AttValue(){
1042       
1043        int     quoteCh = cur()[0];
1044        Advance(1); /* Skip " or ' */
1045
1046        ScanTo(Quote);                 
1047        while (cur()[0] != quoteCh){
1048                if (AtChar<C,'&'>(cur())){
1049                        Parse_Reference();
1050                        ScanTo(Quote);
1051                }
1052                else if (AtQuote<C>(cur())) {
1053                        Advance(1);
1054                        ScanTo(Quote);
1055                }
1056                else /* if (AtChar<C,'<'>(cur())) */
1057                        Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1058        }
1059        Advance(1);
1060}
1061
1062template <CodeUnit_Base C>
1063inline void ParsingEngine<C>::Parse_Prolog(){
1064        ScanTo(NonWS);
1065        int old_pos = AbsPos();
1066        while (!at_DOCTYPE_start<C>(cur())) {
1067                if (at_Comment_Start<C>(cur())) 
1068                        Parse_Comment();
1069                else if (at_PI_Start<C>(cur()))
1070                                Parse_PI();
1071                else{
1072                        Prolog_action(GetCodeUnitPtr(old_pos), LengthFrom(old_pos));
1073                        return;
1074                }
1075                ScanTo(NonWS);
1076        }
1077        Parse_DocType();
1078        ScanTo(NonWS);
1079        while(at_Comment_Start<C>(cur()) || at_PI_Start<C>(cur()) ){
1080                if (at_Comment_Start<C>(cur()))
1081                        Parse_Comment();
1082                else 
1083                        Parse_PI();
1084                ScanTo(NonWS);
1085        }
1086        Prolog_action(GetCodeUnitPtr(old_pos), LengthFrom(old_pos));
1087}
1088
1089
1090
Note: See TracBrowser for help on using the repository browser.