source: trunk/src/engine.c @ 97

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

External Subset and error messages and global entity table.

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