source: trunk/src/engine.c @ 42

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

lib_simd: refactored allocation, bitstream_scan

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