source: trunk/src/engine.c @ 99

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

Internal entity parsing.

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