source: trunk/src/engine.c @ 6

Last change on this file since 6 was 6, checked in by cameron, 12 years ago

Ext_ASCII_16LE/charset_family updates.

File size: 11.6 KB
Line 
1/*  engine.c - Parabix XML parsing engine.
2    Copyright (c) 2007, 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 "bitlex.h"
12#include "charsets/ext_ascii_8.h"
13#include "charsets/ext_ascii_16.h"
14
15#include <assert.h>
16#include <stdlib.h>
17#include <errno.h>
18#include <string.h>
19#include <sys/types.h>
20#include <sys/stat.h>
21
22char sentinel[] = "<]]>?>-->'>\">";
23
24ParsingEngine::ParsingEngine (char * filename) {
25#ifdef BUFFER_PROFILING
26        bitstream_timer = init_BOM_timer(BUFFER_BLOCKS * BLOCKSIZE);
27        lextranspose_timer = init_BOM_timer(BUFFER_BLOCKS * BLOCKSIZE);
28        scanner_timer = init_BOM_timer(BUFFER_BLOCKS * BLOCKSIZE);
29#endif
30
31#define OFFSET32_SENTINEL
32#if (BYTE_ORDER == LITTLE_ENDIAN)
33#define bitblock_sfli sisd_slli
34#endif
35
36  /* Install sentinels for every lexical item stream*/
37#ifndef OPTIMIZE_SHORT_SCAN
38  BitBlock sentinel_value = simd_const_1(1);
39#endif
40#ifdef OPTIMIZE_SHORT_SCAN
41  BitBlock sentinel_value = bitblock_sfli(simd_const_1(1), 8*sizeof(unsigned long));
42#endif
43  for (int j = LAngle; j < LexicalItemCount; j++) {
44    buf.item_stream[j][BUFFER_BLOCKS] = sentinel_value;
45  }
46  buffer_base_pos = 0;
47  buffer_rel_pos = 0;
48  xml_buf = new XML_Buffer::XML_Buffer(filename, 4*strlen(sentinel));
49}
50
51void ParsingEngine::InitLexer() {
52  unsigned char * XML_signature = xml_buf->GetBytePtr(0);
53  if (xml_buf->PrepareBytes(4) < 4) {
54    printf("No XML input document.\n");
55    exit(-1);
56  }
57  Charset_Family family = Charset_Family_Detect(XML_signature);
58  switch (family) {
59    case Ext_ASCII_8:
60      printf("Ext_ASCII_8 document detected.\n");
61      lex = new Ext_ASCII_8_Lexer::Ext_ASCII_8_Lexer(xml_buf, &buf);
62      //lex = new Lexer::Lexer(xml_buf, &buf);
63      //xml_buf->InstallPadding(sentinel);
64      break;
65    case Ext_ASCII_16BE:
66      printf("Ext_ASCII_16BE document detected.\n");
67      lex = new Ext_ASCII_16BE_Lexer::Ext_ASCII_16BE_Lexer(xml_buf, &buf);
68      break;
69    case Ext_ASCII_16LE:
70      printf("Ext_ASCII_16LE document detected.\n");
71      lex = new Ext_ASCII_16LE_Lexer::Ext_ASCII_16LE_Lexer(xml_buf, &buf);
72      break;
73    default:
74      printf("Error: Charset family %i detected, but not supported.\n", family);
75      exit(-1);
76  }
77  rel_EOF_pos = lex-> AdvanceBuffer(0);
78}
79
80
81inline void ParsingEngine::AdvanceToNewBasePosn(int advance_amt) {
82  buffer_base_pos += advance_amt;
83  buffer_rel_pos = 0;
84}
85
86inline unsigned char * ParsingEngine::x8dataPtr(int offset) const {
87  return &((unsigned char *) buf.x8data)[buffer_rel_pos+offset];
88}
89
90
91inline int ParsingEngine::AbsPos() const {
92  return buffer_base_pos + buffer_rel_pos;
93}
94
95
96inline int ParsingEngine::BufferRelPos() const {
97  return buffer_rel_pos;
98}
99
100inline bool ParsingEngine::at_EOF () const {
101  return buffer_rel_pos >= rel_EOF_pos;
102}
103
104inline void ParsingEngine::Advance(int n) {
105  buffer_rel_pos += n;
106#ifndef OMIT_BITBUFFER_LIMIT_TEST_IN_ADVANCE
107  if (buffer_rel_pos >= BUFFER_BLOCKS * BLOCKSIZE) {
108    FinalizeBuffer_action();
109#ifdef BUFFER_PROFILING
110    end_BOM_interval(scanner_timer);
111#endif
112    AdvanceToNewBasePosn(buffer_rel_pos);
113    rel_EOF_pos = lex->AdvanceBuffer(AbsPos());
114  }
115#endif
116}
117
118#ifndef OPTIMIZE_SHORT_SCAN
119inline void ParsingEngine::ScanTo(int item) {
120  buffer_rel_pos = bitstream_scan(buf.item_stream[item], 
121                                      buffer_rel_pos);
122  while (buffer_rel_pos >= BUFFER_BLOCKS * BLOCKSIZE) {
123    FinalizeBuffer_action();
124#ifdef BUFFER_PROFILING
125    end_BOM_interval(scanner_timer);
126#endif
127    AdvanceToNewBasePosn(buffer_rel_pos);
128    rel_EOF_pos = lex->AdvanceBuffer(AbsPos());
129    buffer_rel_pos = bitstream_scan0(buf.item_stream[item]);
130  }
131}
132#endif
133
134
135#ifdef OPTIMIZE_SHORT_SCAN
136inline void ParsingEngine::ScanTo(int item) {
137  SIMD_type * stream = buf.item_stream[item];
138  unsigned long * bitstream_ptr = (unsigned long *) (((intptr_t) stream) + buffer_rel_pos/8);
139  unsigned long bitstream_slice = *bitstream_ptr >> buffer_rel_pos % 8;
140  if (bitstream_slice != 0) {
141    buffer_rel_pos += __builtin_ctzl(bitstream_slice);
142  }
143  else {
144    buffer_rel_pos = (buffer_rel_pos & -8) + 8*sizeof(unsigned long);
145    buffer_rel_pos += bitstream_scan0((SIMD_type *) &bitstream_ptr[1]);
146    while (buffer_rel_pos >= BUFFER_BLOCKS * BLOCKSIZE) {
147      buffer_rel_pos = BUFFER_BLOCKS * BLOCKSIZE;
148      FinalizeBuffer_action();
149#ifdef BUFFER_PROFILING
150      end_BOM_interval(scanner_timer);
151#endif
152      AdvanceToNewBasePosn(buffer_rel_pos);
153      rel_EOF_pos = lex->AdvanceBuffer(AbsPos());
154      buffer_rel_pos = bitstream_scan0(buf.item_stream[item]);
155    }
156  }
157}
158#endif
159
160
161
162inline bool ParsingEngine::AtChar(unsigned char c) const {
163  return *(x8dataPtr(0)) == c;
164}
165
166#include "multiliteral.h"
167/* Now the XML recognizers. */
168
169inline bool ParsingEngine::at_EndTag_Start() const {
170  return s2int16(x8dataPtr(0)) == c2int16('<', '/');
171}
172
173inline bool ParsingEngine::at_Comment_Start() const {
174  return s4int32(x8dataPtr(0)) == c4int32('<', '!', '-', '-');
175}
176
177inline bool ParsingEngine::at_DoubleHyphen() const {
178  return s2int16(x8dataPtr(0)) == c2int16('-', '-');
179}
180
181inline bool ParsingEngine::at_Comment_End() const {
182  return s3int32(x8dataPtr(0)) == c3int32('-', '-', '>');
183}
184
185inline bool ParsingEngine::at_CDATA_Start() const {
186  return s8int64(x8dataPtr(0)) == 
187         c8int64('<', '!', '[', 'C', 'D', 'A', 'T', 'A');
188}
189
190inline bool ParsingEngine::at_CDATA_End() const {
191  return s3int32(x8dataPtr(0)) == c3int32(']', ']', '>');
192}
193
194inline bool ParsingEngine::at_PI_Start() const {
195  return s2int16(x8dataPtr(0)) == c2int16('<', '?');
196}
197
198inline bool ParsingEngine::at_PI_End() const {
199  return s2int16(x8dataPtr(0)) == c2int16('?', '>');
200}
201
202inline bool ParsingEngine::at_EqualsDQuote() const {
203  return s2int16(x8dataPtr(0)) == c2int16('=', '"');
204}
205
206inline bool ParsingEngine::at_EqualsSQuote() const {
207  return s2int16(x8dataPtr(0)) == c2int16('=', '\'');
208}
209
210inline bool ParsingEngine::at_xmlns() const {
211  return s5int64(x8dataPtr(0)) == c5int64('x', 'm', 'l', 'n', 's'); 
212}
213
214inline bool ParsingEngine::at_EmptyElementDelim() const {
215  return s2int16(x8dataPtr(0)) == c2int16('/', '>');
216}
217
218
219/* The at_ElementTag_Start recognizer rules out '<!', '<?', '</'
220   combinations while returning true for '<' followed by any NameStrt
221   character. */
222inline bool ParsingEngine::at_ElementTag_Start() const {
223  assert(*(x8dataPtr(0)) == '<');
224  return (*(x8dataPtr(1)) & 0xE1) != 0x21;
225}
226
227
228
229
230inline void ParsingEngine::Parse_Text () {
231        int text_start;
232        int text_lgth;
233        if (!AtChar('<')) {
234                text_start = AbsPos();
235/*
236                ScanTo(NonWS);
237                non_WS_start = AbsPos(); */
238                ScanTo(LAngle);
239                /*if (text_lgth > 0) {*/
240                Text_action(text_start, AbsPos());
241        }
242}
243
244/* Parse a markup item beginning '<' */
245inline void ParsingEngine::Parse_Markup () {
246        int markup_start = AbsPos();
247        if (at_ElementTag_Start()) {
248                Parse_StartTag();
249        }
250        else if (at_EndTag_Start()) {
251                Parse_EndTag();
252        }
253        else if (at_Comment_Start()) {
254                Parse_Comment();
255        }
256        else if (at_CDATA_Start()) {
257                Parse_CDATA();
258        }
259        else if (at_PI_Start()) {
260                Parse_PI();
261        }
262        else {
263                Advance(1);
264                Error_action(markup_start, AbsPos());
265        }
266}
267
268/* Parse a comment beginning "<!--" */
269inline void ParsingEngine::Parse_Comment () {
270        int markup_start = AbsPos();
271        Advance(4); /* Skip "<!--". */
272        ScanTo(Hyphen);
273        while (!at_DoubleHyphen()) {
274                Advance(2); /* Skip hyphen-nonhyphen pair */
275                ScanTo(Hyphen); 
276        }
277        if (at_Comment_End()) {
278                Advance(3); /* Skip "-->". */
279                Comment_action(markup_start, AbsPos());
280        }
281        else {
282                Advance(2);  /* "--" */
283                Error_action(markup_start, AbsPos());
284        }
285}
286
287/* Parse an end tag beginning "</" */
288inline void ParsingEngine::Parse_EndTag () {
289        int markup_start = AbsPos();
290#ifndef OMIT_ADVANCE_PRIOR_TO_EXLUSIVE_SCAN
291        Advance(2); /* Skip "</". */
292#endif
293        ScanTo(RAngle);
294        Advance(1);
295        EndTag_action(markup_start, AbsPos());
296}
297
298/* Parse a CDATA section beginning "<![CDATA". */
299inline void ParsingEngine::Parse_CDATA () {
300        int markup_start = AbsPos();
301        Advance(8); /* Skip "<![CDATA". */
302        if (!AtChar('[')) {
303                Error_action(markup_start, AbsPos());
304        }
305        else {
306                ScanTo(RBracket);
307                while (!at_CDATA_End()) {
308                        Advance(1);
309                        ScanTo(RBracket);
310                }
311                Advance(3); /* Skip "]]>". */
312                CDATA_action(markup_start, AbsPos());
313        }
314}
315
316inline void ParsingEngine::Parse_PI () {
317        int markup_start = AbsPos();
318        Advance(2); /* Skip "<?". */
319        int target_start = AbsPos();
320        ScanTo(NameFollow);  /* Name delimiter */
321        PI_Target_action(target_start, AbsPos());
322        ScanTo(QMark);
323        while (!at_PI_End()) {
324                Advance(1);
325                ScanTo(QMark);
326        }
327        Advance(2); /* Skip "?>". */
328        PI_action(markup_start, AbsPos());
329}
330 
331/* Parse a start or empty element tag. */
332inline void ParsingEngine::Parse_StartTag () {
333        int markup_start = AbsPos();
334        int att_name_start;
335        int att_val_start;
336        int att_name_end, att_val_end;
337        ScanTo(NameFollow);  /* Name delimiter: WS, "/" or ">" */
338        ElementName_action(markup_start+1, AbsPos());
339        /* The following test optimizes the most common case of a
340        start tag with no attributes.  */
341        if (AtChar('>')) {
342                Advance(1);
343                StartTag_action(markup_start, AbsPos());
344        }
345        else {
346                ScanTo(NonWS);
347                if (AtChar('>')) {
348                        Advance(1);
349                        StartTag_action(markup_start, AbsPos());
350                }
351                else if (at_EmptyElementDelim()) {
352                        Advance(2);
353                        EmptyElement_action(markup_start, AbsPos());
354                }
355                else do {
356                        /* Must be an attribute-value pair or error. */
357                        att_name_start = AbsPos();
358                        ScanTo(NameFollow);
359                        att_name_end = AbsPos();
360                        /* The following optimized tests handle the frequently occurring
361                        case that there are no blanks on either side of the equals sign.
362                        In many cases, the very first test handles 100% of actual
363                        attribute-value pairs encountered. */
364                        if (at_EqualsDQuote()) {
365                                Advance(2); 
366                                att_val_start = AbsPos();
367                                ScanTo(DQuote);
368                        }
369                        else if (at_EqualsSQuote()) {
370                                Advance(2); 
371                                att_val_start = AbsPos();
372                                ScanTo(SQuote);
373                        }
374                        else {
375                                ScanTo(NonWS);
376                                if (!AtChar('=')) {
377                                        Error_action(markup_start, AbsPos()); 
378                                        break;
379                                }
380                                ScanTo(NonWS);
381                                att_val_start = AbsPos()+1;
382                                if (AtChar('"')) {
383                                        Advance(1); 
384                                        ScanTo(DQuote);
385                                }
386                                else if (AtChar('\'')) {
387                                        Advance(1); 
388                                        ScanTo(SQuote);
389                                }
390                                else {
391                                        Error_action(markup_start, AbsPos()); 
392                                        break;
393                                }
394                        }
395                        /* ScanTo(DQuote) or ScanTo(SQuote) complete. */
396                        att_val_end = AbsPos();
397                        Advance(1); 
398                        if (at_xmlns()) {
399                                Namespace_action(att_name_start, att_name_end,
400                                                 att_val_start, att_val_end);
401                        }
402                        else {
403                                AttributeValue_action(att_name_start, att_name_end,
404                                                      att_val_start, att_val_end);
405                        }
406                        /* Now check for end or repeat. Avoid whitespace scan if possible.*/
407                        if (AtChar('>')) {
408                                Advance(1);
409                                StartTag_action(markup_start, AbsPos());
410                                break;
411                        }
412                        else if (at_EmptyElementDelim()) {
413                                Advance(2);
414                                EmptyElement_action(markup_start, AbsPos());
415                                break;
416                        }
417                        ScanTo(NonWS);
418                        if (AtChar('>')) {
419                                Advance(1);
420                                StartTag_action(markup_start, AbsPos());
421                                break;
422                        }
423                        else if (at_EmptyElementDelim()) {
424                                Advance(2);
425                                EmptyElement_action(markup_start, AbsPos());
426                                break;
427                        }
428                        else if (AbsPos() == att_val_end + 1) { 
429                                /* No WS following att value */
430                                Error_action(markup_start, AbsPos());
431                                break;
432                        }
433                } while (1);
434        }
435}
436
437
438inline void ParsingEngine::ParseContent () {
439
440       
441        while (!at_EOF()) {
442                Parse_Text();
443                if (!at_EOF()) {
444                        Parse_Markup();
445                }
446        }
447        if (BufferRelPos() > rel_EOF_pos) {
448                printf("Incomplete markup item at end of file.\n");
449        }
450#ifdef BUFFER_PROFILING
451        printf("Bit stream computation.\n");
452        dump_BOM_table(bitstream_timer);
453        printf("Lexical stream transposition.\n");
454        dump_BOM_table(lextranspose_timer);
455        printf("Scanning.\n");
456        dump_BOM_table(scanner_timer);
457#endif
458}
Note: See TracBrowser for help on using the repository browser.