2 * Copyright 2001-2006 Adrian Thurston <thurston@cs.queensu.ca>
5 /* This file is part of Ragel.
7 * Ragel is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * Ragel is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Ragel; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #define YY_NEVER_INTERACTIVE 1
25 //#define WANT_TOKEN_WRITE
29 #include "rlcodegen.h"
39 bool inlineWhitespace = true;
40 bool handlingInclude = false;
48 void extendToken( char *data, int len );
50 int emitToken( int token, char *data, int len );
51 int emitNoData( int token );
52 int emitTag( char *data, int len, bool isOpen );
53 void passThrough( char *data );
57 enum InlineBlockType {
62 /* Using a wrapper for the parser, must the lex declaration. */
63 #define YY_DECL int rlcodegen_lex()
68 static inline unsigned int hash (const char *str, unsigned int len);
71 static struct XMLTagHashPair *in_word_set (const char *str, unsigned int len);
74 Vector<bool> shouldEmitXMLData;
92 IDENT [a-zA-Z_][a-zA-Z_0-9\-]*
96 /* Numbers in outter code. */
99 shouldEmitXMLData.prepend( false );
100 return emitNoData( *yytext );
104 if ( shouldEmitXMLData[0] )
105 xmlData.append( yytext, yyleng );
109 if ( shouldEmitXMLData[0] )
110 xmlData.append( "&", 1 );
114 if ( shouldEmitXMLData[0] )
115 xmlData.append( "<", 1 );
119 if ( shouldEmitXMLData[0] )
120 xmlData.append( ">", 1 );
131 return emitNoData( *yytext );
136 return emitTag( yytext, yyleng, true );
139 <OPEN_TAG,CLOSE_TAG1>{WSCHAR}+ {
143 <CLOSE_TAG1>{IDENT} {
145 return emitTag( yytext, yyleng, false );
149 shouldEmitXMLData.remove( 0 );
151 return emitNoData( *yytext );
155 return emitToken( XML_Word, yytext, yyleng );
162 <ATTR_LITERAL>\\. extendToken( yytext+1, 1 );
163 <ATTR_LITERAL>\\\n extendToken( yytext+1, 1 );
164 <ATTR_LITERAL>[^\\"]+ extendToken( yytext, yyleng );
166 /* Terminate a double literal */
169 return emitToken( XML_Literal, 0, 0 );
172 <ATTR_LIST>{WSCHAR}+ {
178 return emitNoData( *yytext );
182 return emitNoData( *yytext );
187 /* Write out token data, escaping special charachters. */
188 #ifdef WANT_TOKEN_WRITE
189 void writeToken( int token, char *data )
191 cout << "token id " << token << " at " << id->fileName << ":" <<
192 yylloc->first_line << ":" << yylloc->first_column << "-" <<
193 yylloc->last_line << ":" << yylloc->last_column << " ";
196 while ( *data != 0 ) {
198 case '\n': cout << "\\n"; break;
199 case '\t': cout << "\\t"; break;
200 default: cout << *data; break;
209 /* Caclulate line info from yytext. Called on every pattern match. */
210 void updateLineInfo()
212 /* yytext should always have at least wone char. */
213 assert( yytext[0] != 0 );
215 /* Scan through yytext up to the last character. */
217 for ( ; p[1] != 0; p++ ) {
218 if ( p[0] == '\n' ) {
227 /* Always consider the last character as not a newline. Newlines at the
228 * end of a token are as any old character at the end of the line. */
231 /* The caller may be about to emit a token, be prepared to pass the line
232 * info to the parser. */
233 yylloc->first_line = first_line;
234 yylloc->first_column = first_column;
235 yylloc->last_line = last_line;
236 yylloc->last_column = last_column;
238 /* If the last character was indeed a newline, then wrap ahead now. */
239 if ( p[0] == '\n' ) {
246 /* Eat up a matched pattern that will not be part of a token. */
249 /* Update line information from yytext. */
252 /* The next token starts ahead of the last token. */
253 first_line = last_line;
254 first_column = last_column + 1;
257 /* Extend a token, but don't add any data to it, more token data expected. */
260 /* Update line information from yytext. */
264 /* Append data to the end of the token. More token data expected. */
265 void extendToken( char *data, int len )
267 if ( data != 0 && len > 0 )
268 tokbuf.append( data, len );
270 /* Update line information from yytext. */
275 /* Append data to the end of a token and emitToken it to the parser. */
276 int emitToken( int token, char *data, int len )
278 /* Append the data and null terminate. */
279 if ( data != 0 && len > 0 )
280 tokbuf.append( data, len );
283 /* Duplicate the buffer. */
284 yylval->data = new char[tokbuf.length];
285 strcpy( yylval->data, tokbuf.data );
287 /* Update line information from yytext. */
290 /* Write token info. */
291 #ifdef WANT_TOKEN_WRITE
292 writeToken( token, tokbuf.data );
295 /* Clear out the buffer. */
298 /* The next token starts ahead of the last token. */
299 first_line = last_line;
300 first_column = last_column + 1;
305 /* Append data to the end of a token and emitToken it to the parser. */
306 int emitTag( char *data, int len, bool isOpen )
308 /* Lookup the tag. */
309 int token = TAG_unknown;
311 XMLTagHashPair *tag = Perfect_Hash::in_word_set( data, len );
317 case TAG_host: case TAG_t: case TAG_start_state:
318 case TAG_action_table:
319 case TAG_alphtype: case TAG_state_actions:
320 case TAG_entry_points:
321 case TAG_text: case TAG_goto:
322 case TAG_call: case TAG_next:
323 case TAG_set_act: case TAG_set_tokend:
324 case TAG_entry: case TAG_option:
325 case TAG_cond_space: case TAG_c:
326 shouldEmitXMLData[0] = true;
331 return emitToken( token, data, len );
334 /* Emit a token with no data to the parser. */
335 int emitNoData( int token )
337 /* Return null to the parser. */
340 /* Update line information from yytext. */
343 /* Write token info. */
344 #ifdef WANT_TOKEN_WRITE
345 writeToken( token, 0 );
348 /* Clear out the buffer. */
351 /* The next token starts ahead of the last token. */
352 first_line = last_line;
353 first_column = last_column + 1;
358 /* Pass tokens in outter code through to the output. */
359 void passThrough( char *data )
361 /* If no errors, we are emitting code and we are at the bottom of the
362 * include stack (the source file listed on the command line) then write
364 if ( gblErrorCount == 0 && outputFormat == OutCode )
377 /* Empty out a buffer on destruction. */
383 /* Free the space allocated for the buffer. */
395 /* Grow the buffer when to len allocation. */
396 void Buffer::upAllocate( int len )
399 data = (char*) malloc( len );
401 data = (char*) realloc( data, len );
407 /* Once processessing of the input is done, signal no more. */
411 /* Here simply to suppress the unused yyunpt warning. */
412 void thisFuncIsNeverCalled()
419 /* Set this up in case we are initially given something other
420 * than an opening tag. */
421 shouldEmitXMLData.prepend( false );
424 /* Wrapper for the lexer which stores the locations of the value and location
425 * variables of the parser into globals. The parser is reentrant, however the scanner
426 * does not need to be, so globals work fine. This saves us passing them around
427 * all the helper functions. */
428 int yylex( YYSTYPE *yylval, YYLTYPE *yylloc )
432 return rlcodegen_lex();