source: trunk/src/engine.c @ 49

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

Make ilax actions into ParsingEngine? methods.

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