source: trunk/src/engine.c @ 93

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

Hashmap for enumerated types in Attlists.

File size: 29.2 KB
RevLine 
[4]1/*  engine.c - Parabix XML parsing engine.
[78]2    Copyright (c) 2007, 2008, Robert D. Cameron and Dan Lin.
[4]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"
[73]9#include "byteplex.h"
10#include "xmldecl.h"
[19]11#include "bytelex.h"
[4]12#include "bitlex.h"
13
14#include <assert.h>
15#include <stdlib.h>
16#include <errno.h>
17#include <string.h>
[91]18#include <string>
19#include <iostream>
20using namespace std;
[4]21
[37]22Parser_Interface * Parser_Interface::ParserFactory(char * filename) {
[73]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);
[37]31        }
[73]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);
[37]40        }
[73]41        else /* if (m->code_unit_base == EBCDIC) */ {
42                return new ParsingEngine<EBCDIC>(m, b);
43        }       
[37]44}
45
[52]46Parser_Interface::~Parser_Interface() {
47}
48
49
[37]50bool Parser_Interface::has_ByteOrderMark() {
[73]51        return model_info->BOM_units > 0;
[37]52}
53
54XML_version Parser_Interface::get_version() {
[73]55        return model_info->version;
[37]56}
57
58XML_standalone Parser_Interface::standalone_status() {
[73]59        return model_info->standalone;
[37]60}
61
62bool Parser_Interface::has_EncodingDecl() {
[73]63        return model_info->has_encoding_decl;
[37]64}
65
[73]66unsigned char * Parser_Interface::get_Encoding() {
67        return model_info->encoding;
[37]68}
69
[44]70unsigned char * Parser_Interface::GetCodeUnitPtr(int pos) {
[73]71        int rel_pos = pos - buffer_base_pos;
72        return &((unsigned char *) (byteplex->src_buffer))[rel_pos * (int) model_info->code_unit_size];
[44]73}
[37]74
75
76
[44]77
[37]78template <CodeUnit_Base C>
[73]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();
[93]86         StrictWellFormedness=false;
[91]87        LastAttOccurrence.push_back(0);
88       
[73]89        decl_parser = new XML_Decl_Parser<C>(byteplex);
90        int content_start = decl_parser->ReadXMLInfo(model_info);
91
[78]92    bitplex = new Bitplex;
[42]93        buf = (LexicalStreamSet *) simd_new(sizeof(LexicalStreamSet)/PACKSIZE);
[4]94
95  /* Install sentinels for every lexical item stream*/
96#ifndef OPTIMIZE_SHORT_SCAN
[37]97        BitBlock sentinel_value = simd_const_1(1);
[4]98#endif
99#ifdef OPTIMIZE_SHORT_SCAN
[37]100        BitBlock sentinel_value = sisd_sfli(simd_const_1(1), 8*sizeof(unsigned long));
[4]101#endif
[44]102        for (int j = minLexicalItem; j < LexicalItemCount; j++) {
[37]103                buf->item_stream[j][BUFFER_BLOCKS] = sentinel_value;
104        }
[73]105
[37]106        buffer_base_pos = 0;
[73]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);
[4]114}
115
[52]116template <CodeUnit_Base C>
117ParsingEngine<C>::~ParsingEngine() {
[73]118  model_info->~Model_Info();
119  byteplex->~Byteplex();
120  decl_parser->~XML_Decl_Parser<C>();
121  bitplex->~Bitplex();
[52]122  simd_delete((SIMD_type *) buf);
123  lexer->~Lexer_Interface();
124}
[4]125
[37]126template <CodeUnit_Base C>
[73]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>
[37]142inline unsigned char * ParsingEngine<C>::cur() const {
143  return &((unsigned char *) x8data)[buffer_rel_pos];
[4]144}
145
[37]146template <CodeUnit_Base C>
147inline int ParsingEngine<C>::AbsPos() const {
[4]148  return buffer_base_pos + buffer_rel_pos;
149}
150
[92]151template <CodeUnit_Base C>
152inline int ParsingEngine<C>::LengthFrom(int start_pos) const {
153  return buffer_base_pos + buffer_rel_pos - start_pos;
154}
[4]155
[92]156
157
[37]158template <CodeUnit_Base C>
159inline int ParsingEngine<C>::BufferRelPos() const {
[4]160  return buffer_rel_pos;
161}
162
[15]163
[37]164template <CodeUnit_Base C>
165inline bool ParsingEngine<C>::at_EOF() const {
166  return (buffer_rel_pos >= buffer_limit_pos) && 
[73]167         (buffer_limit_pos < BUFFER_SIZE);
[4]168}
169
[37]170template <CodeUnit_Base C>
171inline void ParsingEngine<C>::Advance(int n) {
[73]172        int preserve_pos;
173        buffer_rel_pos += n;
[4]174#ifndef OMIT_BITBUFFER_LIMIT_TEST_IN_ADVANCE
[73]175  if (buffer_rel_pos >= BUFFER_SIZE) {
176        FinalizeBuffer_action(preserve_pos);
177        AdvanceBuffers(preserve_pos);
[4]178  }
179#endif
180}
181
[15]182
[4]183#ifndef OPTIMIZE_SHORT_SCAN
[37]184template <CodeUnit_Base C>
185inline void ParsingEngine<C>::ScanTo(int item) {
[73]186        int preserve_pos;
[37]187  buffer_rel_pos = bitstream_scan(buf->item_stream[item], 
[4]188                                      buffer_rel_pos);
[37]189  while (buffer_rel_pos >= BUFFER_SIZE) {
[73]190        FinalizeBuffer_action(preserve_pos);
191        AdvanceBuffers(preserve_pos);
192        buffer_rel_pos = bitstream_scan(buf->item_stream[item], buffer_rel_pos);
[4]193  }
194}
195#endif
196
[80]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) {
[92]203                Text_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[80]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
[81]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) {
[92]216                Text_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[81]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
[4]224#ifdef OPTIMIZE_SHORT_SCAN
[37]225template <CodeUnit_Base C>
226inline void ParsingEngine<C>::ScanTo(int item) {
227  SIMD_type * stream = buf->item_stream[item];
[4]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;
[73]238      FinalizeBuffer_action(preserve_pos);
239          AdvanceBuffers(preserve_pos);
[37]240      buffer_rel_pos = bitstream_scan(buf->item_stream[item], buffer_rel_pos);
[4]241    }
242  }
243}
244#endif
245
246
247/* Parse a markup item beginning '<' */
[37]248template <CodeUnit_Base C>
249inline void ParsingEngine<C>::Parse_Markup() {
[66]250        text_or_markup_start = AbsPos();
[37]251        if (at_ElementTag_Start<C>(cur())) {
[4]252                Parse_StartTag();
253        }
[37]254        else if (at_EndTag_Start<C>(cur())) {
[4]255                Parse_EndTag();
256        }
[37]257        else if (at_Comment_Start<C>(cur())) {
[4]258                Parse_Comment();
259        }
[37]260        else if (at_CDATA_Start<C>(cur())) {
[4]261                Parse_CDATA();
262        }
[37]263        else if (at_PI_Start<C>(cur())) {
[4]264                Parse_PI();
265        }
266        else {
267                Advance(1);
[92]268                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[4]269        }
270}
271
272/* Parse a comment beginning "<!--" */
[37]273template <CodeUnit_Base C>
274inline void ParsingEngine<C>::Parse_Comment() {
[66]275
[4]276        Advance(4); /* Skip "<!--". */
277        ScanTo(Hyphen);
[37]278        while (!at_DoubleHyphen<C>(cur())) {
[4]279                Advance(2); /* Skip hyphen-nonhyphen pair */
280                ScanTo(Hyphen); 
281        }
[37]282        if (at_Comment_End<C>(cur())) {
[4]283                Advance(3); /* Skip "-->". */
[92]284                Comment_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[4]285        }
286        else {
287                Advance(2);  /* "--" */
[92]288                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[4]289        }
290}
291
292/* Parse an end tag beginning "</" */
[37]293template <CodeUnit_Base C>
294inline void ParsingEngine<C>::Parse_EndTag() {
[4]295        Advance(2); /* Skip "</". */
[14]296        ScanTo(NameFollow);
[37]297        if (AtChar<C,'>'>(cur())) {
[14]298                Advance(1);
[92]299                EndTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[14]300        }
301        else {
302                ScanTo(NonWS);
[37]303                if (AtChar<C,'>'>(cur())) {
[14]304                        Advance(1);
[92]305                        EndTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[14]306                }
[92]307                else Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[14]308        }
[4]309}
310
311/* Parse a CDATA section beginning "<![CDATA". */
[37]312template <CodeUnit_Base C>
313inline void ParsingEngine<C>::Parse_CDATA() {
[4]314        Advance(8); /* Skip "<![CDATA". */
[37]315        if (!AtChar<C,'['>(cur())) {
[92]316                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[4]317        }
[81]318        else { 
319                Advance(1);
[92]320                CDATA_start_action(GetCodeUnitPtr(text_or_markup_start));
[81]321                text_or_markup_start = AbsPos();
[14]322                ScanTo(CD_End_check);
[37]323                while (!at_CDATA_End<C>(cur())) {
[4]324                        Advance(1);
[14]325                        ScanTo(CD_End_check);
[4]326                }
[92]327                Text_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[4]328                Advance(3); /* Skip "]]>". */
[92]329                CDATA_end_action(GetCodeUnitPtr(AbsPos()));
[4]330        }
331}
332
[37]333template <CodeUnit_Base C>
334inline void ParsingEngine<C>::Parse_Reference() {
[73]335        Advance(1);  // skip "&"
[7]336        ScanTo(NameFollow);  /* Name delimiter */
[37]337        if (!AtChar<C,';'>(cur())) {
[92]338                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[7]339        }
340        else {
341                Advance(1);
[92]342                Reference_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[7]343        }
344}
345
[37]346template <CodeUnit_Base C>
347inline void ParsingEngine<C>::Parse_PI (){
[4]348        Advance(2); /* Skip "<?". */
349        int target_start = AbsPos();
[11]350        // Check for illegal [Xx][Mm][Ll] target.
[37]351        if (at_XxMmLll_WS<C>(cur())) {
[19]352                Advance(4);
[92]353                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[11]354                return;
355        } 
[19]356        ScanTo(NameFollow);  /* Name delimiter */
[92]357        PI_Target_action(GetCodeUnitPtr(target_start), LengthFrom(target_start));
[4]358        ScanTo(QMark);
[37]359        while (!at_PI_End<C>(cur())) {
[4]360                Advance(1);
361                ScanTo(QMark);
362        }
363        Advance(2); /* Skip "?>". */
[92]364        PI_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[4]365}
366 
367/* Parse a start or empty element tag. */
[37]368template <CodeUnit_Base C>
369inline void ParsingEngine<C>::Parse_StartTag (){
[4]370        int att_name_start;
371        int att_val_start;
372        int att_name_end, att_val_end;
[37]373        unsigned char quoteCh;
[73]374        Advance(1);
[4]375        ScanTo(NameFollow);  /* Name delimiter: WS, "/" or ">" */
[92]376        ElementName_action(GetCodeUnitPtr(text_or_markup_start+1), LengthFrom(text_or_markup_start+1));
[4]377        /* The following test optimizes the most common case of a
378        start tag with no attributes.  */
[37]379        if (AtChar<C,'>'>(cur())) {
[4]380                Advance(1);
[92]381                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[4]382        }
383        else {
384                ScanTo(NonWS);
[37]385                if (AtChar<C,'>'>(cur())) {
[4]386                        Advance(1);
[92]387                        StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[4]388                }
[37]389                else if (at_EmptyElementDelim<C>(cur())) {
[4]390                        Advance(2);
[92]391                        EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[4]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();
[91]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) {
[92]404                                        Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start)); /* Duplicate attribute. */
[91]405                                        break;
406                                }                       
407                        }
408                        LastAttOccurrence[attID] = att_name_start;
[4]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. */
[37]413                        if (at_EqualsQuote<C>(cur())) {
414                                quoteCh = cur()[1];
[4]415                                Advance(2); 
416                        }
417                        else {
418                                ScanTo(NonWS);
[37]419                                if (!AtChar<C,'='>(cur())) {
[92]420                                        Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start)); 
[4]421                                        break;
422                                }
423                                ScanTo(NonWS);
[37]424                                quoteCh = cur()[0];
425                                if (!AtQuote<C>(cur())) {
[92]426                                        Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start)); 
[37]427                                        break;
[4]428                                }
[37]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);
[4]437                                }
[37]438                                else if (AtQuote<C>(cur())) {
439                                        Advance(1);
440                                }
441                                else /* if (AtChar<C,'<'>(cur())) */{
[92]442                                        Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start)); 
[4]443                                        break;
444                                }
445                        }
446                        att_val_end = AbsPos();
447                        Advance(1); 
[37]448                        if (at_xmlns<C>(cur()+att_name_start-AbsPos())) {
[92]449                                Namespace_action(GetCodeUnitPtr(att_name_start), att_name_end - att_name_start,
450                                                 GetCodeUnitPtr(att_val_start), att_val_end - att_val_start);
[4]451                        }
452                        else {
[92]453                                AttributeValue_action(GetCodeUnitPtr(att_name_start), att_name_end - att_name_start,
454                                                 GetCodeUnitPtr(att_val_start), att_val_end - att_val_start);
[4]455                        }
456                        /* Now check for end or repeat. Avoid whitespace scan if possible.*/
[37]457                        if (AtChar<C,'>'>(cur())) {
[4]458                                Advance(1);
[92]459                                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[4]460                                break;
461                        }
[37]462                        else if (at_EmptyElementDelim<C>(cur())) {
[4]463                                Advance(2);
[92]464                                EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[4]465                                break;
466                        }
467                        ScanTo(NonWS);
[37]468                        if (AtChar<C,'>'>(cur())) {
[4]469                                Advance(1);
[92]470                                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[4]471                                break;
472                        }
[37]473                        else if (at_EmptyElementDelim<C>(cur())) {
[4]474                                Advance(2);
[92]475                                EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[4]476                                break;
477                        }
478                        else if (AbsPos() == att_val_end + 1) { 
479                                /* No WS following att value */
[92]480                                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[4]481                                break;
482                        }
483                } while (1);
484        }
485}
486
[37]487template <CodeUnit_Base C>
[66]488inline void ParsingEngine<C>::text_if_nonnull_action(){
489        if (AbsPos() > text_or_markup_start) {
[92]490                Text_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[66]491                text_or_markup_start = AbsPos();
492        }
493}
494
495template <CodeUnit_Base C>
[37]496inline void ParsingEngine<C>::ParseContent() {
[62]497        DocumentStart_action(); 
[7]498        do {
[73]499                text_or_markup_start = AbsPos();
[80]500                ScanToMarkupStart(); /* '<', '&', or ']' for ']]>' test */
[37]501/*              if (AtChar<C,'<'>(cur())) {
[66]502                        text_if_nonnull_action();
[37]503                        Parse_Markup<C>();
[7]504                }*/
[37]505                if (at_ElementTag_Start<C>(cur())) {
[66]506                        text_if_nonnull_action();
[7]507                        Parse_StartTag();
[4]508                }
[37]509                else if (at_EndTag_Start<C>(cur())) {
[66]510                        text_if_nonnull_action();
[7]511                        Parse_EndTag();
512                }
[37]513                else if (at_Comment_Start<C>(cur())) {
[66]514                        text_if_nonnull_action();
[7]515                        Parse_Comment();
516                }
[37]517                else if (AtChar<C,'&'>(cur())) {
[66]518                        text_if_nonnull_action();
[7]519                        Parse_Reference();
520                }
[37]521                else if (at_CDATA_Start<C>(cur())) {
[66]522                        text_if_nonnull_action();
[7]523                        Parse_CDATA();
524                }
[37]525                else if (at_PI_Start<C>(cur())) {
[66]526                        text_if_nonnull_action();
[7]527                        Parse_PI();
528                }
[37]529                else if (at_CDATA_End<C>(cur())) {
[66]530                        text_if_nonnull_action();
[7]531                        Advance(3);
[92]532                        Error_action(GetCodeUnitPtr(AbsPos()-3), 3);
[7]533                }
534                else if (at_EOF()) {
[66]535                        text_if_nonnull_action();
[7]536                        break;
537                }
538                else {
539                        Advance(1);
540                        continue;
541                }
542        } while (1);
[62]543        DocumentEnd_action();   
[4]544}
[11]545
[78]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())
[92]568                Error_action(GetCodeUnitPtr(start_pos), LengthFrom(start_pos));
[78]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
[92]580                        Error_action(GetCodeUnitPtr(start_pos), LengthFrom(start_pos)); 
[78]581                ScanTo(NonWS);
582        }
583       
584        if (AtChar<C,'>'>(cur())){
585                Advance(1);   
[92]586                Doctype_action(GetCodeUnitPtr(start_pos), LengthFrom(start_pos));
[78]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
[92]606                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start)); 
[78]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
[92]653                                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start)); 
[78]654                }
655                else if (AtChar<C,']'>(cur())){
656                        break;
657                }
658                else
[92]659                        Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start)); 
[78]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);
[92]671                PEReference_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[78]672        }
673        else
[92]674                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[78]675}
676
677
678template <CodeUnit_Base C>
679inline void ParsingEngine<C>::Parse_Elementdecl (){
680
681        Advance(7); /* Skip "<!ELEMENT". */
682
683    requireWS();
[91]684    int name_start = AbsPos();
[78]685        ScanTo(NameFollow);
[91]686        int lgth = AbsPos() - name_start;
687        int elemID = model_info->getOrInsertGlobalElement(GetCodeUnitPtr(name_start), lgth);
[78]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()))
[91]700                        Parse_RemainingMixed();
[78]701                else
[91]702                        Parse_RemainingChildren();
[78]703    }
704               
705        if (AtChar<C,'>'>(cur())) {
706                Advance(1);
[92]707                Elementdecl_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[78]708        }
709        else
[92]710                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[78]711}
712template <CodeUnit_Base C>
[91]713inline void ParsingEngine<C>::Parse_RemainingMixed (){
[78]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>
[91]739inline void ParsingEngine<C>::Parse_RemainingChildren (){
[78]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
[92]774                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[78]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);
[91]785                Parse_RemainingChildren();
[78]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;
[91]798       
799        int name_start;
800        int lgth;
801       
802        int elemID;
803        int attID;
804       
[78]805        Advance(7); /* Skip "ATTLIST. */
806        requireWS();
[91]807       
808        name_start = AbsPos();
[78]809        ScanTo(NameFollow);
[91]810        lgth = AbsPos()-name_start;
811        elemID = model_info->getOrInsertGlobalElement(GetCodeUnitPtr(name_start), lgth);
[78]812       
813        old_abspos = AbsPos();
814        ScanTo(NonWS);
815        while(!AtChar<C,'>'>(cur())) {
816                if(old_abspos == AbsPos())
[92]817                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[91]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;
[78]827        requireWS();
[91]828        if (at_CDATA<C>(cur())){
[78]829                Advance(5);
[91]830                this_info->attType = CDATA_att;
831        }
832        else if(at_ID<C>(cur())){
[78]833                Advance(2);
[91]834                this_info->attType = ID_att;
835        }
836        else if(at_IDREF<C>(cur())){
[78]837                Advance(5);
[91]838                this_info->attType = IDREF_att;
839        }
840        else if(at_IDREFS<C>(cur())){
[78]841                Advance(6);
[91]842                this_info->attType = IDREFS_att;
843        }
844        else if(at_ENTITY<C>(cur())){
[78]845                Advance(6);
[91]846                this_info->attType = ENTITY_att;
847        }
848        else if(at_ENTITIES<C>(cur())){
[78]849                Advance(8);
[91]850                this_info->attType = ENTITIES_att;
851        }
852        else if(at_NMTOKEN<C>(cur())){
[78]853                Advance(7);
[91]854                this_info->attType = NMTOKEN_att;
855        }
856        else if(at_NMTOKENS<C>(cur())){
[78]857                Advance(8);
[91]858                this_info->attType = NMTOKENS_att;
859        }
[78]860        else if(at_NOTATION<C>(cur())){ /* NotationType = 'NOTATION' S Enumeration
861                                                                         when Nmtoken = Name */
862                Advance(8);
863                        requireWS();
[91]864                Parse_Enumeration(this_info);
865                this_info->attType = NOTATION_att;
[78]866        }
[91]867        else if(AtChar<C,'('>(cur())){
868                Parse_Enumeration(this_info);
869                this_info->attType = enumeration_att;
870        }
[78]871        else
[92]872                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[78]873        requireWS();
[91]874        Parse_DefaultDecl(this_info);
[78]875        old_abspos = AbsPos();
876                ScanTo(NonWS);
[91]877                model_info->ElementAttributeData[elemID].push_back(this_info);
[78]878        }
[91]879
[78]880        Advance(1);
[92]881        AttlistDecl_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[78]882}
883
884template <CodeUnit_Base C>
[91]885inline void ParsingEngine<C>::Parse_Enumeration (ATT_info * this_info){
[78]886
[93]887        int enumCount=0;
[78]888        if(AtChar<C,'('>(cur()))
889                Advance(1);
890        else
[92]891                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[78]892        ScanTo(NonWS);
[93]893       
894    int name_start = AbsPos();
[78]895        ScanTo(NameFollow);
[93]896        int     lgth = AbsPos()-name_start;
897       
898        char *s = new char[lgth+1];
899        memcpy(s, GetCodeUnitPtr(name_start), lgth);
900        s[lgth] = '\0';
901       
902        this_info->enumValues[s]=++(enumCount);
903       
[78]904        ScanTo(NonWS);
905        while(AtChar<C,'|'>(cur())){
906                Advance(1);
[93]907                ScanTo(NonWS);         
908                name_start = AbsPos();
[78]909                ScanTo(NameFollow);
[93]910                lgth = AbsPos()-name_start;
911       
912                char *s = new char[lgth+1];
913                memcpy(s, GetCodeUnitPtr(name_start), lgth);
914                s[lgth] = '\0';
915       
916                int enumID = this_info->enumValues[s];
917                if(enumID==0){ 
918                        this_info->enumValues[s]=++(enumCount);
919                        enumID = enumCount;
920                }
921                else if(!StrictWellFormedness){
922                        Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
923                }
[78]924                ScanTo(NonWS);
925        }
926        if (AtChar<C,')'>(cur())) 
927                Advance(1);
928        else
[92]929                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[78]930}
931
932template <CodeUnit_Base C>
[91]933inline void ParsingEngine<C>::Parse_DefaultDecl (ATT_info * this_info){
934        if(at_REQUIRED<C>(cur())){
[78]935                Advance(9);
[91]936                this_info->defaultKind = REQUIRED_att;
937        }
938        else if(at_IMPLIED<C>(cur())){
[78]939                Advance(8);
[91]940                this_info->defaultKind = IMPLIED_att;
[78]941        }
[91]942        else {
943                if(at_FIXED<C>(cur())){
944                        Advance(6);
945                        requireWS();
946                        this_info->defaultKind = FIXED_att;
947                }
948                else this_info->defaultKind = DEFAULT_att;
949                if(AtQuote<C>(cur())){
950                        int quot_start = AbsPos()+1;
951                        Parse_AttValue();
952                        /* need to normalize */
953                        this_info->defaultValueLgth = AbsPos() - quot_start - 1;
954                       
955                        this_info->defaultValue = new unsigned char[this_info->defaultValueLgth+1];
956                        memcpy(this_info->defaultValue, GetCodeUnitPtr(quot_start),this_info->defaultValueLgth); 
957                        this_info->defaultValue[this_info->defaultValueLgth] = '\0';
958                        }
959                else
[92]960                        Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[78]961        }
962}
963
964template <CodeUnit_Base C>
965inline void ParsingEngine<C>::Parse_Entitydecl (){
966       
[91]967        int entity_name_start;
968        int entity_name_end;
[78]969        int old_abspos;
970        Advance(6); /* Skip "ENTITY. */
971        requireWS();
972       
973        if (AtChar<C,'%'>(cur())){
974                Advance(1);
975                requireWS();
[91]976                entity_name_start = AbsPos();
[78]977                ScanTo(NameFollow);
[91]978                entity_name_end = AbsPos();
[78]979                requireWS();
980                if(at_SYSTEM<C>(cur())||at_PUBLIC<C>(cur())){
981                Parse_ExternalID();             
982        }
983        else if(AtQuote<C>(cur())){
984                Parse_AttValue(); /* Not parse PEReference*/
985        }
986        else
[92]987                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[78]988        }
989        else{
[91]990                entity_name_start = AbsPos();
[78]991                ScanTo(NameFollow);
[91]992                entity_name_end = AbsPos();
[78]993                requireWS();
994               
995                if(at_SYSTEM<C>(cur())||at_PUBLIC<C>(cur())){
996                Parse_ExternalID();
997                ScanTo(NonWS);
998                if(at_NOTATION<C>(cur())){
999                        if(old_abspos == AbsPos())
[92]1000                                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[78]1001                        else
1002                                Advance(5);
1003                        requireWS();
1004                        ScanTo(NameFollow);
1005                }
1006        }
1007        else if(AtQuote<C>(cur())){
1008                Parse_AttValue(); /* Not parse PEReference*/
1009        }
1010        else
[92]1011                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[78]1012        }
1013        ScanTo(NonWS);
1014        if (AtChar<C,'>'>(cur())){
1015                Advance(1);
[92]1016                Entitydecl_action(GetCodeUnitPtr(entity_name_start), entity_name_end - entity_name_start, 
1017                                  GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[78]1018        }
1019        else
[92]1020                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[78]1021}
1022
1023template <CodeUnit_Base C>
1024inline void ParsingEngine<C>::Parse_Notationdecl (){
1025       
1026        int old_abspos;
1027        Advance(8); /* Skip "NOTATION. */
1028        requireWS();
1029        ScanTo(NameFollow);
1030        requireWS();
1031        if(at_SYSTEM<C>(cur())){
1032                Advance(6);
1033                requireWS();
1034                Parse_MatchedQuote (); /*  SystemLiteral */
1035        }
1036        else if (at_PUBLIC<C>(cur())){
1037                Advance(6);
1038                requireWS();
1039                Parse_MatchedQuote (); /*  PubidLiteral */
1040                ScanTo(NonWS);
1041                if (!AtChar<C,'>'>(cur())){
1042                        if (old_abspos == AbsPos())
[92]1043                                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[78]1044                        Parse_MatchedQuote (); /*  SystemLiteral */
1045                }
1046        }
1047        else
[92]1048                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[78]1049        ScanTo(NonWS);
1050        if (AtChar<C,'>'>(cur())) {
1051                Advance(1);
[92]1052                Notationdecl_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[78]1053        }
1054        else
[92]1055                Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[78]1056}
1057
1058template <CodeUnit_Base C>
1059inline void ParsingEngine<C>::requireWS(){
1060       
1061    int old_abspos = AbsPos(); 
1062    ScanTo(NonWS);
1063    if(old_abspos == AbsPos())
[92]1064        Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[78]1065}
1066
1067template <CodeUnit_Base C>
1068inline void ParsingEngine<C>::Parse_AttValue(){
1069       
1070        int     quoteCh = cur()[0];
1071        Advance(1); /* Skip " or ' */
1072
1073        ScanTo(Quote);                 
1074        while (cur()[0] != quoteCh){
1075                if (AtChar<C,'&'>(cur())){
1076                        Parse_Reference();
1077                        ScanTo(Quote);
1078                }
1079                else if (AtQuote<C>(cur())) {
1080                        Advance(1);
1081                        ScanTo(Quote);
1082                }
1083                else /* if (AtChar<C,'<'>(cur())) */
[92]1084                        Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
[78]1085        }
1086        Advance(1);
1087}
1088
1089template <CodeUnit_Base C>
1090inline void ParsingEngine<C>::Parse_Prolog(){
1091        ScanTo(NonWS);
1092        int old_pos = AbsPos();
1093        while (!at_DOCTYPE_start<C>(cur())) {
1094                if (at_Comment_Start<C>(cur())) 
1095                        Parse_Comment();
1096                else if (at_PI_Start<C>(cur()))
1097                                Parse_PI();
1098                else{
[92]1099                        Prolog_action(GetCodeUnitPtr(old_pos), LengthFrom(old_pos));
[78]1100                        return;
1101                }
1102                ScanTo(NonWS);
1103        }
1104        Parse_DocType();
1105        ScanTo(NonWS);
1106        while(at_Comment_Start<C>(cur()) || at_PI_Start<C>(cur()) ){
1107                if (at_Comment_Start<C>(cur()))
1108                        Parse_Comment();
1109                else 
1110                        Parse_PI();
1111                ScanTo(NonWS);
1112        }
[92]1113        Prolog_action(GetCodeUnitPtr(old_pos), LengthFrom(old_pos));
[78]1114}
1115
1116
1117
Note: See TracBrowser for help on using the repository browser.