source: trunk/src/engine.c @ 66

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

text_or_markup_start field for parsing engine

File size: 12.8 KB
Line 
1/*  engine.c - Parabix XML parsing engine.
2    Copyright (c) 2007, 2008, Robert D. Cameron.
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 "xmlbuffer.h"
10#include "bytelex.h"
11#include "bitlex.h"
12
13#include <assert.h>
14#include <stdlib.h>
15#include <errno.h>
16#include <string.h>
17
18
19Parser_Interface * Parser_Interface::ParserFactory(char * filename) {
20        XML_Buffer_Interface * b = XML_Buffer_Interface::BufferFactory(filename);
21        b->DoByteplex();
22        b->PreparePseudoASCII_Stream();
23#ifdef DEBUG
24        printf("PseudoASCII stream complete.\n");
25#endif
26        b->ReadXMLInfo();
27#ifdef DEBUG
28        printf("XML Info read; content start position = %i.\n", b->ContentStartUnit());
29#endif
30        if (b->code_unit_base == ASCII) {
31                return new ParsingEngine<ASCII>(b);
32        }
33        else /* if (b->code_unit_base == EBCDIC) */ {
34                return new ParsingEngine<EBCDIC>(b);
35        }
36}
37
38Parser_Interface::~Parser_Interface() {
39  xml_buf->~XML_Buffer_Interface();
40}
41
42
43bool Parser_Interface::has_ByteOrderMark() {
44        return xml_buf->BOM_units > 0;
45}
46
47XML_version Parser_Interface::get_version() {
48        return xml_buf->version;
49}
50
51XML_standalone Parser_Interface::standalone_status() {
52        return xml_buf->standalone;
53}
54
55bool Parser_Interface::has_EncodingDecl() {
56        return xml_buf->has_encoding_decl;
57}
58
59int Parser_Interface::get_Encoding_pos() {
60        return xml_buf->encoding_start_pos;
61}
62
63int Parser_Interface::get_Encoding_lgth() {
64        return xml_buf->encoding_lgth;
65}
66
67unsigned char * Parser_Interface::GetCodeUnitPtr(int pos) {
68        return &((unsigned char *) (xml_buf->ByteBuffer))[pos * (int) xml_buf->code_unit_size];
69}
70
71
72
73
74template <CodeUnit_Base C>
75ParsingEngine<C>::ParsingEngine(XML_Buffer_Interface * b) : Parser_Interface () {
76#ifdef BUFFER_PROFILING
77        bitstream_timer = init_BOM_timer(BUFFER_BLOCKS * BLOCKSIZE);
78        lextranspose_timer = init_BOM_timer(BUFFER_BLOCKS * BLOCKSIZE);
79        scanner_timer = init_BOM_timer(BUFFER_BLOCKS * BLOCKSIZE);
80#endif
81        buf = (LexicalStreamSet *) simd_new(sizeof(LexicalStreamSet)/PACKSIZE);
82
83  /* Install sentinels for every lexical item stream*/
84#ifndef OPTIMIZE_SHORT_SCAN
85        BitBlock sentinel_value = simd_const_1(1);
86#endif
87#ifdef OPTIMIZE_SHORT_SCAN
88        BitBlock sentinel_value = sisd_sfli(simd_const_1(1), 8*sizeof(unsigned long));
89#endif
90        for (int j = minLexicalItem; j < LexicalItemCount; j++) {
91                buf->item_stream[j][BUFFER_BLOCKS] = sentinel_value;
92        }
93#ifdef DEBUG
94        printf("Bitspace sentinels established.\n");
95#endif
96        xml_buf = b;
97        buffer_base_pos = 0;
98        buffer_rel_pos = b->ContentStartUnit();
99        lexer = Lexer<C>::LexerFactory(b, buf);
100#ifdef DEBUG
101        printf("Lexer created.\n");
102#endif
103        lexer->AdvanceBuffer(buffer_base_pos, buffer_rel_pos, buffer_limit_pos);
104        x8data = &xml_buf->x8data[buffer_base_pos/PACKSIZE];
105#ifdef DEBUG
106        printf("Initial lexical buffer formed.\n");
107#endif
108}
109
110
111template <CodeUnit_Base C>
112ParsingEngine<C>::~ParsingEngine() {
113  simd_delete((SIMD_type *) buf);
114  lexer->~Lexer_Interface();
115}
116
117template <CodeUnit_Base C>
118inline unsigned char * ParsingEngine<C>::cur() const {
119  return &((unsigned char *) x8data)[buffer_rel_pos];
120}
121
122template <CodeUnit_Base C>
123inline int ParsingEngine<C>::AbsPos() const {
124  return buffer_base_pos + buffer_rel_pos;
125}
126
127
128template <CodeUnit_Base C>
129inline int ParsingEngine<C>::BufferRelPos() const {
130  return buffer_rel_pos;
131}
132
133
134template <CodeUnit_Base C>
135inline bool ParsingEngine<C>::at_EOF() const {
136  return (buffer_rel_pos >= buffer_limit_pos) && 
137         (buffer_limit_pos < BUFFER_BLOCKS * BLOCKSIZE + LOOKAHEAD_POSITIONS);
138}
139
140template <CodeUnit_Base C>
141inline void ParsingEngine<C>::Advance(int n) {
142  buffer_rel_pos += n;
143#ifndef OMIT_BITBUFFER_LIMIT_TEST_IN_ADVANCE
144  if (buffer_rel_pos >= buffer_limit_pos) {
145    FinalizeBuffer_action();
146#ifdef BUFFER_PROFILING
147    end_BOM_interval(scanner_timer);
148#endif
149    lexer->AdvanceBuffer(buffer_base_pos, buffer_rel_pos, buffer_limit_pos);
150    x8data = &xml_buf->x8data[buffer_base_pos/PACKSIZE];
151  }
152#endif
153}
154
155
156#ifndef OPTIMIZE_SHORT_SCAN
157template <CodeUnit_Base C>
158inline void ParsingEngine<C>::ScanTo(int item) {
159  buffer_rel_pos = bitstream_scan(buf->item_stream[item], 
160                                      buffer_rel_pos);
161  while (buffer_rel_pos >= BUFFER_SIZE) {
162    FinalizeBuffer_action();
163#ifdef BUFFER_PROFILING
164    end_BOM_interval(scanner_timer);
165#endif
166    lexer->AdvanceBuffer(buffer_base_pos, buffer_rel_pos, buffer_limit_pos);
167#ifdef DEBUG
168printf("lexer->AdvanceBuffer complete; base_pos = %i, rel_pos = %i, limit_pos = %i\n",
169       buffer_base_pos, buffer_rel_pos, buffer_limit_pos);
170#endif
171    x8data = &xml_buf->x8data[buffer_base_pos/PACKSIZE];
172    buffer_rel_pos = bitstream_scan(buf->item_stream[item], buffer_rel_pos);
173  }
174}
175#endif
176
177#ifdef OPTIMIZE_SHORT_SCAN
178template <CodeUnit_Base C>
179inline void ParsingEngine<C>::ScanTo(int item) {
180  SIMD_type * stream = buf->item_stream[item];
181  unsigned long * bitstream_ptr = (unsigned long *) (((intptr_t) stream) + buffer_rel_pos/8);
182  unsigned long bitstream_slice = *bitstream_ptr >> buffer_rel_pos % 8;
183  if (bitstream_slice != 0) {
184    buffer_rel_pos += __builtin_ctzl(bitstream_slice);
185  }
186  else {
187    buffer_rel_pos = (buffer_rel_pos & -8) + 8*sizeof(unsigned long);
188    buffer_rel_pos += bitstream_scan0((SIMD_type *) &bitstream_ptr[1]);
189    while (buffer_rel_pos >= BUFFER_BLOCKS * BLOCKSIZE) {
190      buffer_rel_pos = BUFFER_BLOCKS * BLOCKSIZE;
191      FinalizeBuffer_action();
192#ifdef BUFFER_PROFILING
193      end_BOM_interval(scanner_timer);
194#endif
195      lexer->AdvanceBuffer(buffer_base_pos, buffer_rel_pos, buffer_limit_pos);
196      x8data = &xml_buf->x8data[buffer_base_pos/PACKSIZE];
197      buffer_rel_pos = bitstream_scan(buf->item_stream[item], buffer_rel_pos);
198    }
199  }
200}
201#endif
202
203
204/* Parse a markup item beginning '<' */
205template <CodeUnit_Base C>
206inline void ParsingEngine<C>::Parse_Markup() {
207        text_or_markup_start = AbsPos();
208        if (at_ElementTag_Start<C>(cur())) {
209                Parse_StartTag();
210        }
211        else if (at_EndTag_Start<C>(cur())) {
212                Parse_EndTag();
213        }
214        else if (at_Comment_Start<C>(cur())) {
215                Parse_Comment();
216        }
217        else if (at_CDATA_Start<C>(cur())) {
218                Parse_CDATA();
219        }
220        else if (at_PI_Start<C>(cur())) {
221                Parse_PI();
222        }
223        else {
224                Advance(1);
225                Error_action(text_or_markup_start, AbsPos());
226        }
227}
228
229/* Parse a comment beginning "<!--" */
230template <CodeUnit_Base C>
231inline void ParsingEngine<C>::Parse_Comment() {
232
233        Advance(4); /* Skip "<!--". */
234        ScanTo(Hyphen);
235        while (!at_DoubleHyphen<C>(cur())) {
236                Advance(2); /* Skip hyphen-nonhyphen pair */
237                ScanTo(Hyphen); 
238        }
239        if (at_Comment_End<C>(cur())) {
240                Advance(3); /* Skip "-->". */
241                Comment_action(text_or_markup_start, AbsPos());
242        }
243        else {
244                Advance(2);  /* "--" */
245                Error_action(text_or_markup_start, AbsPos());
246        }
247}
248
249/* Parse an end tag beginning "</" */
250template <CodeUnit_Base C>
251inline void ParsingEngine<C>::Parse_EndTag() {
252
253#ifndef OMIT_ADVANCE_PRIOR_TO_EXCLUSIVE_SCAN
254        Advance(2); /* Skip "</". */
255#endif
256        ScanTo(NameFollow);
257        if (AtChar<C,'>'>(cur())) {
258                Advance(1);
259                EndTag_action(text_or_markup_start, AbsPos());
260        }
261        else {
262                ScanTo(NonWS);
263                if (AtChar<C,'>'>(cur())) {
264                        Advance(1);
265                        EndTag_action(text_or_markup_start, AbsPos());
266                }
267                else Error_action(text_or_markup_start, AbsPos());
268        }
269}
270
271/* Parse a CDATA section beginning "<![CDATA". */
272template <CodeUnit_Base C>
273inline void ParsingEngine<C>::Parse_CDATA() {
274
275        Advance(8); /* Skip "<![CDATA". */
276        if (!AtChar<C,'['>(cur())) {
277                Error_action(text_or_markup_start, AbsPos());
278        }
279        else {
280                ScanTo(CD_End_check);
281                while (!at_CDATA_End<C>(cur())) {
282                        Advance(1);
283                        ScanTo(CD_End_check);
284                }
285                Advance(3); /* Skip "]]>". */
286                CDATA_action(text_or_markup_start, AbsPos());
287        }
288}
289
290template <CodeUnit_Base C>
291inline void ParsingEngine<C>::Parse_Reference() {
292
293        /* Advance(1);  // skip "&" */
294        ScanTo(NameFollow);  /* Name delimiter */
295        if (!AtChar<C,';'>(cur())) {
296                Error_action(text_or_markup_start, AbsPos());
297        }
298        else {
299                Advance(1);
300                Reference_action(text_or_markup_start, AbsPos());
301        }
302}
303
304template <CodeUnit_Base C>
305inline void ParsingEngine<C>::Parse_PI (){
306
307        Advance(2); /* Skip "<?". */
308        int target_start = AbsPos();
309        // Check for illegal [Xx][Mm][Ll] target.
310        if (at_XxMmLll_WS<C>(cur())) {
311                Advance(4);
312                Error_action(text_or_markup_start, AbsPos());
313                return;
314        } 
315        ScanTo(NameFollow);  /* Name delimiter */
316        PI_Target_action(target_start, AbsPos());
317        ScanTo(QMark);
318        while (!at_PI_End<C>(cur())) {
319                Advance(1);
320                ScanTo(QMark);
321        }
322        Advance(2); /* Skip "?>". */
323        PI_action(text_or_markup_start, AbsPos());
324}
325 
326/* Parse a start or empty element tag. */
327template <CodeUnit_Base C>
328inline void ParsingEngine<C>::Parse_StartTag (){
329
330        int att_name_start;
331        int att_val_start;
332        int att_name_end, att_val_end;
333        unsigned char quoteCh;
334        ScanTo(NameFollow);  /* Name delimiter: WS, "/" or ">" */
335        ElementName_action(text_or_markup_start+1, AbsPos());
336        /* The following test optimizes the most common case of a
337        start tag with no attributes.  */
338        if (AtChar<C,'>'>(cur())) {
339                Advance(1);
340                StartTag_action(text_or_markup_start, AbsPos());
341        }
342        else {
343                ScanTo(NonWS);
344                if (AtChar<C,'>'>(cur())) {
345                        Advance(1);
346                        StartTag_action(text_or_markup_start, AbsPos());
347                }
348                else if (at_EmptyElementDelim<C>(cur())) {
349                        Advance(2);
350                        EmptyElement_action(text_or_markup_start, AbsPos());
351                }
352                else do {
353                        /* Must be an attribute-value pair or error. */
354                        att_name_start = AbsPos();
355                        ScanTo(NameFollow);
356                        att_name_end = AbsPos();
357                        /* The following optimized tests handle the frequently occurring
358                        case that there are no blanks on either side of the equals sign.
359                        In many cases, the very first test handles 100% of actual
360                        attribute-value pairs encountered. */
361                        if (at_EqualsQuote<C>(cur())) {
362                                quoteCh = cur()[1];
363                                Advance(2); 
364                        }
365                        else {
366                                ScanTo(NonWS);
367                                if (!AtChar<C,'='>(cur())) {
368                                        Error_action(text_or_markup_start, AbsPos()); 
369                                        break;
370                                }
371                                ScanTo(NonWS);
372                                quoteCh = cur()[0];
373                                if (!AtQuote<C>(cur())) {
374                                        Error_action(text_or_markup_start, AbsPos()); 
375                                        break;
376                                }
377                                Advance(1);
378                        }
379                        att_val_start = AbsPos();
380                        ScanTo(Quote);
381                        while (cur()[0] != quoteCh) {
382                                if (AtChar<C,'&'>(cur())) {
383                                        Parse_Reference();
384                                        ScanTo(Quote);
385                                }
386                                else if (AtQuote<C>(cur())) {
387                                        Advance(1);
388                                }
389                                else /* if (AtChar<C,'<'>(cur())) */{
390                                        Error_action(text_or_markup_start, AbsPos()); 
391                                        break;
392                                }
393                        }
394                        att_val_end = AbsPos();
395                        Advance(1); 
396                        if (at_xmlns<C>(cur()+att_name_start-AbsPos())) {
397                                Namespace_action(att_name_start, att_name_end,
398                                                 att_val_start, att_val_end);
399                        }
400                        else {
401                                AttributeValue_action(att_name_start, att_name_end,
402                                                      att_val_start, att_val_end);
403                        }
404                        /* Now check for end or repeat. Avoid whitespace scan if possible.*/
405                        if (AtChar<C,'>'>(cur())) {
406                                Advance(1);
407                                StartTag_action(text_or_markup_start, AbsPos());
408                                break;
409                        }
410                        else if (at_EmptyElementDelim<C>(cur())) {
411                                Advance(2);
412                                EmptyElement_action(text_or_markup_start, AbsPos());
413                                break;
414                        }
415                        ScanTo(NonWS);
416                        if (AtChar<C,'>'>(cur())) {
417                                Advance(1);
418                                StartTag_action(text_or_markup_start, AbsPos());
419                                break;
420                        }
421                        else if (at_EmptyElementDelim<C>(cur())) {
422                                Advance(2);
423                                EmptyElement_action(text_or_markup_start, AbsPos());
424                                break;
425                        }
426                        else if (AbsPos() == att_val_end + 1) { 
427                                /* No WS following att value */
428                                Error_action(text_or_markup_start, AbsPos());
429                                break;
430                        }
431                } while (1);
432        }
433}
434
435template <CodeUnit_Base C>
436inline void ParsingEngine<C>::text_if_nonnull_action(){
437        if (AbsPos() > text_or_markup_start) {
438                Text_action(text_or_markup_start, AbsPos());
439                text_or_markup_start = AbsPos();
440        }
441}
442
443template <CodeUnit_Base C>
444inline void ParsingEngine<C>::ParseContent() {
445
446        text_or_markup_start = AbsPos();
447        DocumentStart_action(); 
448        do {
449                ScanTo(MarkupStart); /* '<', '&', or ']' for ']]>' test */
450/*              if (AtChar<C,'<'>(cur())) {
451                        text_if_nonnull_action();
452                        Parse_Markup<C>();
453                }*/
454                if (at_ElementTag_Start<C>(cur())) {
455                        text_if_nonnull_action();
456                        Parse_StartTag();
457                }
458                else if (at_EndTag_Start<C>(cur())) {
459                        text_if_nonnull_action();
460                        Parse_EndTag();
461                }
462                else if (at_Comment_Start<C>(cur())) {
463                        text_if_nonnull_action();
464                        Parse_Comment();
465                }
466                else if (AtChar<C,'&'>(cur())) {
467                        text_if_nonnull_action();
468                        Parse_Reference();
469                }
470                else if (at_CDATA_Start<C>(cur())) {
471                        text_if_nonnull_action();
472                        Parse_CDATA();
473                }
474                else if (at_PI_Start<C>(cur())) {
475                        text_if_nonnull_action();
476                        Parse_PI();
477                }
478                else if (at_CDATA_End<C>(cur())) {
479                        text_if_nonnull_action();
480                        Advance(3);
481                        Error_action(AbsPos()-3, AbsPos());
482                }
483                else if (at_EOF()) {
484                        text_if_nonnull_action();
485                        break;
486                }
487                else {
488                        Advance(1);
489                        continue;
490                }
491                text_or_markup_start = AbsPos();
492        } while (1);
493        DocumentEnd_action();   
494#ifdef BUFFER_PROFILING
495        printf("Bit stream computation.\n");
496        dump_BOM_table(bitstream_timer);
497        printf("Lexical stream transposition.\n");
498        dump_BOM_table(lextranspose_timer);
499        printf("Scanning.\n");
500        dump_BOM_table(scanner_timer);
501#endif
502}
503
Note: See TracBrowser for help on using the repository browser.