comparison libinterp/parse-tree/lex.ll @ 16236:d8c0f46efaf0 classdef

maint: periodic merge of default to classdef
author John W. Eaton <jwe@octave.org>
date Sat, 09 Mar 2013 17:54:40 -0500
parents d2b268936783 2b15ae55c721
children b8a2df776118
comparison
equal deleted inserted replaced
16212:d2b268936783 16236:d8c0f46efaf0
44 } 44 }
45 45
46 %s COMMAND_START 46 %s COMMAND_START
47 %s MATRIX_START 47 %s MATRIX_START
48 48
49 %x INPUT_FILE_BEGIN 49 %x INPUT_FILE_START
50
51 %x BLOCK_COMMENT_START
52 %x LINE_COMMENT_START
50 53
51 %{ 54 %{
52 55
53 #include <cctype> 56 #include <cctype>
54 #include <cstring> 57 #include <cstring>
125 #undef YY_FATAL_ERROR 128 #undef YY_FATAL_ERROR
126 #endif 129 #endif
127 #define YY_FATAL_ERROR(msg) \ 130 #define YY_FATAL_ERROR(msg) \
128 (yyget_extra (yyscanner))->fatal_error (msg) 131 (yyget_extra (yyscanner))->fatal_error (msg)
129 132
130 #define DISPLAY_TOK_AND_RETURN(tok) \
131 do \
132 { \
133 int tok_val = tok; \
134 if (Vdisplay_tokens) \
135 curr_lexer->display_token (tok_val); \
136 if (lexer_debug_flag) \
137 { \
138 std::cerr << "R: "; \
139 curr_lexer->display_token (tok_val); \
140 std::cerr << std::endl; \
141 } \
142 return tok_val; \
143 } \
144 while (0)
145
146 #define COUNT_TOK_AND_RETURN(tok) \
147 do \
148 { \
149 if (tok != '\n') \
150 { \
151 Vtoken_count++; \
152 curr_lexer->token_count++; \
153 } \
154 DISPLAY_TOK_AND_RETURN (tok); \
155 } \
156 while (0)
157
158 #define TOK_RETURN(tok) \
159 do \
160 { \
161 curr_lexer->current_input_column += yyleng; \
162 curr_lexer->quote_is_transpose = false; \
163 curr_lexer->convert_spaces_to_comma = true; \
164 COUNT_TOK_AND_RETURN (tok); \
165 } \
166 while (0)
167
168 #define TOK_PUSH_AND_RETURN(name, tok) \
169 do \
170 { \
171 curr_lexer->push_token \
172 (new token (name, curr_lexer->input_line_number, \
173 curr_lexer->current_input_column)); \
174 TOK_RETURN (tok); \
175 } \
176 while (0)
177
178 #define BIN_OP_RETURN_INTERNAL(tok, convert, bos, qit) \
179 do \
180 { \
181 curr_lexer->push_token \
182 (new token (curr_lexer->input_line_number, \
183 curr_lexer->current_input_column)); \
184 curr_lexer->current_input_column += yyleng; \
185 curr_lexer->quote_is_transpose = qit; \
186 curr_lexer->convert_spaces_to_comma = convert; \
187 curr_lexer->looking_for_object_index = false; \
188 curr_lexer->at_beginning_of_statement = bos; \
189 COUNT_TOK_AND_RETURN (tok); \
190 } \
191 while (0)
192
193 #define XBIN_OP_RETURN_INTERNAL(tok, convert, bos, qit) \
194 do \
195 { \
196 curr_lexer->gripe_matlab_incompatible_operator (yytext); \
197 BIN_OP_RETURN_INTERNAL (tok, convert, bos, qit); \
198 } \
199 while (0)
200
201 #define BIN_OP_RETURN(tok, convert, bos) \
202 do \
203 { \
204 BIN_OP_RETURN_INTERNAL (tok, convert, bos, false); \
205 } \
206 while (0)
207
208 #define XBIN_OP_RETURN(tok, convert, bos) \
209 do \
210 { \
211 curr_lexer->gripe_matlab_incompatible_operator (yytext); \
212 BIN_OP_RETURN (tok, convert, bos); \
213 } \
214 while (0)
215
216 #define LEXER_DEBUG(pattern) \
217 do \
218 { \
219 if (lexer_debug_flag) \
220 curr_lexer->lexer_debug (pattern, yytext); \
221 } \
222 while (0)
223
224 static bool Vdisplay_tokens = false; 133 static bool Vdisplay_tokens = false;
225 134
226 static unsigned int Vtoken_count = 0; 135 static unsigned int Vtoken_count = 0;
227 136
228 // Internal variable for lexer debugging state. 137 // Internal variable for lexer debugging state.
244 CONT ({EL}|{BS}) 153 CONT ({EL}|{BS})
245 Im [iIjJ] 154 Im [iIjJ]
246 CCHAR [#%] 155 CCHAR [#%]
247 COMMENT ({CCHAR}.*{NL}) 156 COMMENT ({CCHAR}.*{NL})
248 SNLCMT ({SNL}|{COMMENT}) 157 SNLCMT ({SNL}|{COMMENT})
249 NOT ((\~)|(\!))
250 POW ((\*\*)|(\^))
251 EPOW (\.{POW})
252 IDENT ([_$a-zA-Z][_$a-zA-Z0-9]*) 158 IDENT ([_$a-zA-Z][_$a-zA-Z0-9]*)
253 EXPON ([DdEe][+-]?{D}+) 159 EXPON ([DdEe][+-]?{D}+)
254 NUMBER (({D}+\.?{D}*{EXPON}?)|(\.{D}+{EXPON}?)|(0[xX][0-9a-fA-F]+)) 160 NUMBER (({D}+\.?{D}*{EXPON}?)|(\.{D}+{EXPON}?)|(0[xX][0-9a-fA-F]+))
161
162 ANY_INCLUDING_NL (.|{NL})
163
255 %% 164 %%
256 165
257 %{ 166 %{
258 // Make script and function files start with a bogus token. This makes 167 // Make script and function files start with a bogus token. This makes
259 // the parser go down a special path. 168 // the parser go down a special path.
260 %} 169 %}
261 170
262 <INPUT_FILE_BEGIN>. { 171 <INPUT_FILE_START>{ANY_INCLUDING_NL} {
263 LEXER_DEBUG ("<INPUT_FILE_BEGIN>."); 172 curr_lexer->lexer_debug ("<INPUT_FILE_START>{ANY_INCLUDING_NL}");
264 173
265 BEGIN (INITIAL);
266 curr_lexer->xunput (yytext[0]); 174 curr_lexer->xunput (yytext[0]);
267 175
268 // May be reset later if we see "function" or "classdef" appears 176 // May be reset later if we see "function" or "classdef" appears
269 // as the first token. 177 // as the first token.
270 curr_lexer->reading_script_file = true; 178 curr_lexer->reading_script_file = true;
271 179
272 DISPLAY_TOK_AND_RETURN (INPUT_FILE); 180 curr_lexer->pop_start_state ();
181
182 return curr_lexer->show_token (INPUT_FILE);
273 } 183 }
274 184
275 %{ 185 %{
276 // Help and other command-style functions. 186 // Help and other command-style functions.
277 %} 187 %}
278 188
279 <COMMAND_START>{NL} { 189 <COMMAND_START>{NL} {
280 LEXER_DEBUG ("<COMMAND_START>{NL}"); 190 curr_lexer->lexer_debug ("<COMMAND_START>{NL}");
281 191
282 BEGIN (INITIAL);
283 curr_lexer->input_line_number++; 192 curr_lexer->input_line_number++;
284 curr_lexer->current_input_column = 1; 193 curr_lexer->current_input_column = 1;
285 194
286 curr_lexer->quote_is_transpose = false; 195 curr_lexer->quote_is_transpose = false;
287 curr_lexer->convert_spaces_to_comma = true; 196 curr_lexer->convert_spaces_to_comma = true;
288 curr_lexer->looking_for_object_index = false; 197 curr_lexer->looking_for_object_index = false;
289 curr_lexer->at_beginning_of_statement = true; 198 curr_lexer->at_beginning_of_statement = true;
290 199
291 COUNT_TOK_AND_RETURN ('\n'); 200 curr_lexer->pop_start_state ();
201
202 return curr_lexer->count_token ('\n');
292 } 203 }
293 204
294 <COMMAND_START>[\;\,] { 205 <COMMAND_START>[\;\,] {
295 LEXER_DEBUG ("<COMMAND_START>[\\;\\,]"); 206 curr_lexer->lexer_debug ("<COMMAND_START>[\\;\\,]");
296 207
297 curr_lexer->looking_for_object_index = false; 208 curr_lexer->looking_for_object_index = false;
298 curr_lexer->at_beginning_of_statement = true; 209 curr_lexer->at_beginning_of_statement = true;
299 210
300 BEGIN (INITIAL); 211 curr_lexer->pop_start_state ();
301 212
302 if (strcmp (yytext, ",") == 0) 213 if (strcmp (yytext, ",") == 0)
303 TOK_RETURN (','); 214 return curr_lexer->handle_token (',');
304 else 215 else
305 TOK_RETURN (';'); 216 return curr_lexer->handle_token (';');
306 } 217 }
307 218
308 <COMMAND_START>[\"\'] { 219 <COMMAND_START>[\"\'] {
309 LEXER_DEBUG ("<COMMAND_START>[\\\"\\']"); 220 curr_lexer->lexer_debug ("<COMMAND_START>[\\\"\\']");
310 221
311 curr_lexer->at_beginning_of_statement = false; 222 curr_lexer->at_beginning_of_statement = false;
312 223
313 curr_lexer->current_input_column++; 224 curr_lexer->current_input_column++;
314 int tok = curr_lexer->handle_string (yytext[0]); 225 int tok = curr_lexer->handle_string (yytext[0]);
315 226
316 COUNT_TOK_AND_RETURN (tok); 227 return curr_lexer->count_token (tok);
317 } 228 }
318 229
319 <COMMAND_START>[^#% \t\r\n\;\,\"\'][^ \t\r\n\;\,]*{S}* { 230 <COMMAND_START>[^#% \t\r\n\;\,\"\'][^ \t\r\n\;\,]*{S}* {
320 LEXER_DEBUG ("<COMMAND_START>[^#% \\t\\r\\n\\;\\,\\\"\\'][^ \\t\\r\\n\\;\\,]*{S}*"); 231 curr_lexer->lexer_debug ("<COMMAND_START>[^#% \\t\\r\\n\\;\\,\\\"\\'][^ \\t\\r\\n\\;\\,]*{S}*");
321 232
322 std::string tok = strip_trailing_whitespace (yytext); 233 std::string tok = strip_trailing_whitespace (yytext);
323 234
324 curr_lexer->looking_for_object_index = false; 235 curr_lexer->looking_for_object_index = false;
325 curr_lexer->at_beginning_of_statement = false; 236 curr_lexer->at_beginning_of_statement = false;
326 237
327 TOK_PUSH_AND_RETURN (tok, SQ_STRING); 238 return curr_lexer->handle_token (tok, SQ_STRING);
328 } 239 }
329 240
330 %{ 241 %{
331 // For this and the next two rules, we're looking at ']', and we 242 // For this and the next two rules, we're looking at ']', and we
332 // need to know if the next token is '=' or '=='. 243 // need to know if the next token is '=' or '=='.
340 251
341 // FIXME -- we need to handle block comments here. 252 // FIXME -- we need to handle block comments here.
342 %} 253 %}
343 254
344 <MATRIX_START>{SNLCMT}*\]{S}* { 255 <MATRIX_START>{SNLCMT}*\]{S}* {
345 LEXER_DEBUG ("<MATRIX_START>{SNLCMT}*\\]{S}*"); 256 curr_lexer->lexer_debug ("<MATRIX_START>{SNLCMT}*\\]{S}*");
346 257
347 curr_lexer->scan_for_comments (yytext); 258 curr_lexer->scan_for_comments (yytext);
348 curr_lexer->fixup_column_count (yytext); 259 curr_lexer->fixup_column_count (yytext);
349 260
350 curr_lexer->looking_at_object_index.pop_front (); 261 curr_lexer->looking_at_object_index.pop_front ();
358 int tok_to_return = curr_lexer->handle_close_bracket (spc_gobbled, ']'); 269 int tok_to_return = curr_lexer->handle_close_bracket (spc_gobbled, ']');
359 270
360 if (spc_gobbled) 271 if (spc_gobbled)
361 curr_lexer->xunput (' '); 272 curr_lexer->xunput (' ');
362 273
363 COUNT_TOK_AND_RETURN (tok_to_return); 274 return curr_lexer->count_token (tok_to_return);
364 } 275 }
365 276
366 %{ 277 %{
367 // FIXME -- we need to handle block comments here. 278 // FIXME -- we need to handle block comments here.
368 %} 279 %}
369 280
370 <MATRIX_START>{SNLCMT}*\}{S}* { 281 <MATRIX_START>{SNLCMT}*\}{S}* {
371 LEXER_DEBUG ("<MATRIX_START>{SNLCMT}*\\}{S}*"); 282 curr_lexer->lexer_debug ("<MATRIX_START>{SNLCMT}*\\}{S}*");
372 283
373 curr_lexer->scan_for_comments (yytext); 284 curr_lexer->scan_for_comments (yytext);
374 curr_lexer->fixup_column_count (yytext); 285 curr_lexer->fixup_column_count (yytext);
375 286
376 curr_lexer->looking_at_object_index.pop_front (); 287 curr_lexer->looking_at_object_index.pop_front ();
384 int tok_to_return = curr_lexer->handle_close_bracket (spc_gobbled, '}'); 295 int tok_to_return = curr_lexer->handle_close_bracket (spc_gobbled, '}');
385 296
386 if (spc_gobbled) 297 if (spc_gobbled)
387 curr_lexer->xunput (' '); 298 curr_lexer->xunput (' ');
388 299
389 COUNT_TOK_AND_RETURN (tok_to_return); 300 return curr_lexer->count_token (tok_to_return);
390 } 301 }
391 302
392 %{ 303 %{
393 // Commas are element separators in matrix constants. If we don't 304 // Commas are element separators in matrix constants. If we don't
394 // check for continuations here we can end up inserting too many 305 // check for continuations here we can end up inserting too many
395 // commas. 306 // commas.
396 %} 307 %}
397 308
398 <MATRIX_START>{S}*\,{S}* { 309 <MATRIX_START>{S}*\,{S}* {
399 LEXER_DEBUG ("<MATRIX_START>{S}*\\,{S}*"); 310 curr_lexer->lexer_debug ("<MATRIX_START>{S}*\\,{S}*");
400 311
401 curr_lexer->current_input_column += yyleng; 312 curr_lexer->current_input_column += yyleng;
402 313
403 int tmp = curr_lexer->eat_continuation (); 314 int tmp = curr_lexer->eat_continuation ();
404 315
415 326
416 curr_lexer->xunput (';'); 327 curr_lexer->xunput (';');
417 } 328 }
418 } 329 }
419 330
420 COUNT_TOK_AND_RETURN (','); 331 return curr_lexer->count_token (',');
421 } 332 }
422 333
423 %{ 334 %{
424 // In some cases, spaces in matrix constants can turn into commas. 335 // In some cases, spaces in matrix constants can turn into commas.
425 // If commas are required, spaces are not important in matrix 336 // If commas are required, spaces are not important in matrix
426 // constants so we just eat them. If we don't check for continuations 337 // constants so we just eat them. If we don't check for continuations
427 // here we can end up inserting too many commas. 338 // here we can end up inserting too many commas.
428 %} 339 %}
429 340
430 <MATRIX_START>{S}+ { 341 <MATRIX_START>{S}+ {
431 LEXER_DEBUG ("<MATRIX_START>{S}+"); 342 curr_lexer->lexer_debug ("<MATRIX_START>{S}+");
432 343
433 curr_lexer->current_input_column += yyleng; 344 curr_lexer->current_input_column += yyleng;
434 345
435 curr_lexer->at_beginning_of_statement = false; 346 curr_lexer->at_beginning_of_statement = false;
436 347
457 curr_lexer->convert_spaces_to_comma = true; 368 curr_lexer->convert_spaces_to_comma = true;
458 curr_lexer->looking_for_object_index = false; 369 curr_lexer->looking_for_object_index = false;
459 370
460 curr_lexer->maybe_warn_separator_insert (','); 371 curr_lexer->maybe_warn_separator_insert (',');
461 372
462 COUNT_TOK_AND_RETURN (','); 373 return curr_lexer->count_token (',');
463 } 374 }
464 } 375 }
465 } 376 }
466 377
467 %{ 378 %{
471 382
472 // FIXME -- we need to handle block comments here. 383 // FIXME -- we need to handle block comments here.
473 %} 384 %}
474 385
475 <MATRIX_START>{SNLCMT}*;{SNLCMT}* { 386 <MATRIX_START>{SNLCMT}*;{SNLCMT}* {
476 LEXER_DEBUG ("<MATRIX_START>{SNLCMT}*;{SNLCMT}*"); 387 curr_lexer->lexer_debug ("<MATRIX_START>{SNLCMT}*;{SNLCMT}*");
477 388
478 curr_lexer->scan_for_comments (yytext); 389 curr_lexer->scan_for_comments (yytext);
479 curr_lexer->fixup_column_count (yytext); 390 curr_lexer->fixup_column_count (yytext);
480 curr_lexer->eat_whitespace (); 391 curr_lexer->eat_whitespace ();
481 392
482 curr_lexer->quote_is_transpose = false; 393 curr_lexer->quote_is_transpose = false;
483 curr_lexer->convert_spaces_to_comma = true; 394 curr_lexer->convert_spaces_to_comma = true;
484 curr_lexer->looking_for_object_index = false; 395 curr_lexer->looking_for_object_index = false;
485 curr_lexer->at_beginning_of_statement = false; 396 curr_lexer->at_beginning_of_statement = false;
486 397
487 COUNT_TOK_AND_RETURN (';'); 398 return curr_lexer->count_token (';');
488 } 399 }
489 400
490 %{ 401 %{
491 // In some cases, new lines can also become row separators. If we 402 // In some cases, new lines can also become row separators. If we
492 // don't eat whitespace here we can end up inserting too many 403 // don't eat whitespace here we can end up inserting too many
495 // FIXME -- we need to handle block comments here. 406 // FIXME -- we need to handle block comments here.
496 %} 407 %}
497 408
498 <MATRIX_START>{S}*{COMMENT}{SNLCMT}* | 409 <MATRIX_START>{S}*{COMMENT}{SNLCMT}* |
499 <MATRIX_START>{S}*{NL}{SNLCMT}* { 410 <MATRIX_START>{S}*{NL}{SNLCMT}* {
500 LEXER_DEBUG ("<MATRIX_START>{S}*{COMMENT}{SNLCMT}*|<MATRIX_START>{S}*{NL}{SNLCMT}*"); 411 curr_lexer->lexer_debug ("<MATRIX_START>{S}*{COMMENT}{SNLCMT}*|<MATRIX_START>{S}*{NL}{SNLCMT}*");
501 412
502 curr_lexer->scan_for_comments (yytext); 413 curr_lexer->scan_for_comments (yytext);
503 curr_lexer->fixup_column_count (yytext); 414 curr_lexer->fixup_column_count (yytext);
504 curr_lexer->eat_whitespace (); 415 curr_lexer->eat_whitespace ();
505 416
513 if (! curr_lexer->looking_at_object_index.front () 424 if (! curr_lexer->looking_at_object_index.front ()
514 && curr_lexer->nesting_level.is_bracket_or_brace ()) 425 && curr_lexer->nesting_level.is_bracket_or_brace ())
515 { 426 {
516 curr_lexer->maybe_warn_separator_insert (';'); 427 curr_lexer->maybe_warn_separator_insert (';');
517 428
518 COUNT_TOK_AND_RETURN (';'); 429 return curr_lexer->count_token (';');
519 } 430 }
520 } 431 }
521 432
522 \[{S}* { 433 \[{S}* {
523 LEXER_DEBUG ("\\[{S}*"); 434 curr_lexer->lexer_debug ("\\[{S}*");
524 435
525 curr_lexer->nesting_level.bracket (); 436 curr_lexer->nesting_level.bracket ();
526 437
527 curr_lexer->looking_at_object_index.push_front (false); 438 curr_lexer->looking_at_object_index.push_front (false);
528 439
540 451
541 curr_lexer->decrement_promptflag (); 452 curr_lexer->decrement_promptflag ();
542 curr_lexer->eat_whitespace (); 453 curr_lexer->eat_whitespace ();
543 454
544 curr_lexer->bracketflag++; 455 curr_lexer->bracketflag++;
545 BEGIN (MATRIX_START); 456
546 COUNT_TOK_AND_RETURN ('['); 457 curr_lexer->push_start_state (MATRIX_START);
458
459 return curr_lexer->count_token ('[');
547 } 460 }
548 461
549 \] { 462 \] {
550 LEXER_DEBUG ("\\]"); 463 curr_lexer->lexer_debug ("\\]");
551 464
552 curr_lexer->nesting_level.remove (); 465 curr_lexer->nesting_level.remove ();
553 466
554 curr_lexer->looking_at_object_index.pop_front (); 467 curr_lexer->looking_at_object_index.pop_front ();
555 468
556 curr_lexer->looking_for_object_index = true; 469 curr_lexer->looking_for_object_index = true;
557 curr_lexer->at_beginning_of_statement = false; 470 curr_lexer->at_beginning_of_statement = false;
558 471
559 TOK_RETURN (']'); 472 return curr_lexer->handle_token (']');
473 }
474
475 %{
476 // Gobble comments.
477 %}
478
479 %{
480 // Start of a block comment. If the comment marker appears immediately
481 // after a block of full-line comments, finish the full line comment
482 // block.
483 %}
484
485 ^{S}*{CCHAR}\{{S}*{NL} {
486 curr_lexer->lexer_debug ("^{S}*{CCHAR}\{{S}*{NL}");
487
488 int tok = 0;
489
490 if (curr_lexer->start_state () == LINE_COMMENT_START)
491 {
492 if (! curr_lexer->comment_text.empty ())
493 tok = curr_lexer->finish_comment (octave_comment_elt::full_line);
494
495 curr_lexer->pop_start_state ();
496 }
497
498 curr_lexer->push_start_state (BLOCK_COMMENT_START);
499
500 yyless (0);
501
502 if (tok > 0)
503 return curr_lexer->count_token (tok);
504 }
505
506 <BLOCK_COMMENT_START>^{S}*{CCHAR}\{{S}*{NL} {
507 curr_lexer->lexer_debug ("<BLOCK_COMMENT_START>^{S}*{CCHAR}\{{S}*{NL}");
508
509 curr_lexer->input_line_number++;
510 curr_lexer->current_input_column = 1;
511
512 if (curr_lexer->block_comment_nesting_level)
513 curr_lexer->comment_text = "\n";
514
515 curr_lexer->block_comment_nesting_level++;
516 }
517
518 %{
519 // End of a block comment. If this block comment is nested inside
520 // another, wait for the outermost block comment block to be closed
521 // before storing the comment.
522 %}
523
524 <BLOCK_COMMENT_START>^{S}*{CCHAR}\}{S}*{NL} {
525 curr_lexer->lexer_debug ("<BLOCK_COMMENT_START>^{S}*{CCHAR}\\}{S}*{NL}");
526
527 curr_lexer->input_line_number++;
528 curr_lexer->current_input_column = 1;
529
530 int tok = 0;
531
532 if (curr_lexer->block_comment_nesting_level > 1)
533 curr_lexer->comment_text = "\n";
534 else
535 tok = curr_lexer->finish_comment (octave_comment_elt::block);
536
537 curr_lexer->block_comment_nesting_level--;
538 curr_lexer->pop_start_state ();
539
540 if (tok > 0)
541 return curr_lexer->count_token (tok);
542 }
543
544 %{
545 // Body of a block comment.
546 %}
547
548 <BLOCK_COMMENT_START>.*{NL} {
549 curr_lexer->lexer_debug ("<BLOCK_COMMENT_START>.*{NL}");
550
551 curr_lexer->input_line_number++;
552 curr_lexer->current_input_column = 1;
553 curr_lexer->comment_text += yytext;
554 }
555
556 %{
557 // Full-line or end-of-line comment.
558 %}
559
560 {S}*{CCHAR}.*{NL} {
561 curr_lexer->lexer_debug ("{S}*{CCHAR}.*{NL}");
562
563 curr_lexer->push_start_state (LINE_COMMENT_START);
564 yyless (0);
565 }
566
567 <LINE_COMMENT_START>{S}*{CCHAR}.*{NL} {
568 curr_lexer->lexer_debug ("<LINE_COMMENT_START>{S}*{CCHAR}.*{NL}");
569
570 bool full_line_comment = curr_lexer->current_input_column == 1;
571 curr_lexer->input_line_number++;
572 curr_lexer->current_input_column = 1;
573
574 size_t len = yyleng;
575 size_t i = 0;
576 while (i < len)
577 {
578 char c = yytext[i];
579 if (c == '#' || c == '%' || c == ' ' || c == '\t')
580 i++;
581 else
582 break;
583 }
584
585 curr_lexer->comment_text += &yytext[i];
586
587 int tok = 0;
588
589 if (! full_line_comment)
590 {
591 tok = curr_lexer->finish_comment (octave_comment_elt::end_of_line);
592
593 curr_lexer->pop_start_state ();
594
595 if (curr_lexer->start_state () == COMMAND_START)
596 {
597 // Allow the actions for the end of a COMMAND line to be
598 // executed next.
599
600 tok = 0;
601 curr_lexer->xunput ('\n');
602 }
603 }
604
605 if (tok > 0)
606 return curr_lexer->count_token (tok);
607 }
608
609 %{
610 // End of a block of full-line comments.
611 %}
612
613 <LINE_COMMENT_START>{ANY_INCLUDING_NL} {
614 curr_lexer->lexer_debug ("<LINE_COMMENT_START>{ANY_INCLUDING_NL}");
615
616 curr_lexer->xunput (yytext[0]);
617
618 int tok = curr_lexer->finish_comment (octave_comment_elt::full_line);
619
620 curr_lexer->pop_start_state ();
621
622 if (tok > 0)
623 return curr_lexer->count_token (tok);
560 } 624 }
561 625
562 %{ 626 %{
563 // Imaginary numbers. 627 // Imaginary numbers.
564 %} 628 %}
565 629
566 {NUMBER}{Im} { 630 {NUMBER}{Im} {
567 LEXER_DEBUG ("{NUMBER}{Im}"); 631 curr_lexer->lexer_debug ("{NUMBER}{Im}");
568 632
569 curr_lexer->handle_number (); 633 curr_lexer->handle_number ();
570 COUNT_TOK_AND_RETURN (IMAG_NUM); 634 return curr_lexer->count_token (IMAG_NUM);
571 } 635 }
572 636
573 %{ 637 %{
574 // Real numbers. Don't grab the '.' part of a dot operator as part of 638 // Real numbers. Don't grab the '.' part of a dot operator as part of
575 // the constant. 639 // the constant.
576 %} 640 %}
577 641
578 {D}+/\.[\*/\\^\'] | 642 {D}+/\.[\*/\\^\'] |
579 {NUMBER} { 643 {NUMBER} {
580 LEXER_DEBUG ("{D}+/\\.[\\*/\\^\\']|{NUMBER}"); 644 curr_lexer->lexer_debug ("{D}+/\\.[\\*/\\^\\']|{NUMBER}");
581 curr_lexer->handle_number (); 645 curr_lexer->handle_number ();
582 COUNT_TOK_AND_RETURN (NUM); 646 return curr_lexer->count_token (NUM);
583 } 647 }
584 648
585 %{ 649 %{
586 // Eat whitespace. Whitespace inside matrix constants is handled by 650 // Eat whitespace. Whitespace inside matrix constants is handled by
587 // the <MATRIX_START> start state code above. 651 // the <MATRIX_START> start state code above.
595 // Continuation lines. Allow comments after continuations. 659 // Continuation lines. Allow comments after continuations.
596 %} 660 %}
597 661
598 {CONT}{S}*{NL} | 662 {CONT}{S}*{NL} |
599 {CONT}{S}*{COMMENT} { 663 {CONT}{S}*{COMMENT} {
600 LEXER_DEBUG ("{CONT}{S}*{NL}|{CONT}{S}*{COMMENT}"); 664 curr_lexer->lexer_debug ("{CONT}{S}*{NL}|{CONT}{S}*{COMMENT}");
601 665
602 if (yytext[0] == '\\') 666 if (yytext[0] == '\\')
603 curr_lexer->gripe_matlab_incompatible_continuation (); 667 curr_lexer->gripe_matlab_incompatible_continuation ();
604 curr_lexer->scan_for_comments (yytext); 668 curr_lexer->scan_for_comments (yytext);
605 curr_lexer->decrement_promptflag (); 669 curr_lexer->decrement_promptflag ();
619 // Identifiers. Truncate the token at the first space or tab but 683 // Identifiers. Truncate the token at the first space or tab but
620 // don't write directly on yytext. 684 // don't write directly on yytext.
621 %} 685 %}
622 686
623 {IDENT}{S}* { 687 {IDENT}{S}* {
624 LEXER_DEBUG ("{IDENT}{S}*"); 688 curr_lexer->lexer_debug ("{IDENT}{S}*");
625 689
626 int id_tok = curr_lexer->handle_identifier (); 690 int id_tok = curr_lexer->handle_identifier ();
627 691
628 if (id_tok >= 0) 692 if (id_tok >= 0)
629 COUNT_TOK_AND_RETURN (id_tok); 693 return curr_lexer->count_token (id_tok);
630 } 694 }
631 695
632 %{ 696 %{
633 // Superclass method identifiers. 697 // Superclass method identifiers.
634 %} 698 %}
635 699
636 {IDENT}@{IDENT}{S}* | 700 {IDENT}@{IDENT}{S}* |
637 {IDENT}@{IDENT}.{IDENT}{S}* { 701 {IDENT}@{IDENT}.{IDENT}{S}* {
638 LEXER_DEBUG ("{IDENT}@{IDENT}{S}*|{IDENT}@{IDENT}.{IDENT}{S}*"); 702 curr_lexer->lexer_debug ("{IDENT}@{IDENT}{S}*|{IDENT}@{IDENT}.{IDENT}{S}*");
639 703
640 int id_tok = curr_lexer->handle_superclass_identifier (); 704 int id_tok = curr_lexer->handle_superclass_identifier ();
641 705
642 if (id_tok >= 0) 706 if (id_tok >= 0)
643 { 707 {
644 curr_lexer->looking_for_object_index = true; 708 curr_lexer->looking_for_object_index = true;
645 709
646 COUNT_TOK_AND_RETURN (id_tok); 710 return curr_lexer->count_token (id_tok);
647 } 711 }
648 } 712 }
649 713
650 %{ 714 %{
651 // Metaclass query 715 // Metaclass query
652 %} 716 %}
653 717
654 \?{IDENT}{S}* | 718 \?{IDENT}{S}* |
655 \?{IDENT}\.{IDENT}{S}* { 719 \?{IDENT}\.{IDENT}{S}* {
656 LEXER_DEBUG ("\\?{IDENT}{S}*|\\?{IDENT}\\.{IDENT}{S}*"); 720 curr_lexer->lexer_debug ("\\?{IDENT}{S}*|\\?{IDENT}\\.{IDENT}{S}*");
657 721
658 int id_tok = curr_lexer->handle_meta_identifier (); 722 int id_tok = curr_lexer->handle_meta_identifier ();
659 723
660 if (id_tok >= 0) 724 if (id_tok >= 0)
661 { 725 {
662 curr_lexer->looking_for_object_index = true; 726 curr_lexer->looking_for_object_index = true;
663 727
664 COUNT_TOK_AND_RETURN (id_tok); 728 return curr_lexer->count_token (id_tok);
665 } 729 }
666 } 730 }
667 731
668 %{ 732 %{
669 // Function handles and superclass references 733 // Function handles and superclass references
670 %} 734 %}
671 735
672 "@" { 736 "@" {
673 LEXER_DEBUG ("@"); 737 curr_lexer->lexer_debug ("@");
674 738
675 curr_lexer->current_input_column++; 739 curr_lexer->current_input_column++;
676 740
677 curr_lexer->quote_is_transpose = false; 741 curr_lexer->quote_is_transpose = false;
678 curr_lexer->convert_spaces_to_comma = false; 742 curr_lexer->convert_spaces_to_comma = false;
679 curr_lexer->looking_at_function_handle++; 743 curr_lexer->looking_at_function_handle++;
680 curr_lexer->looking_for_object_index = false; 744 curr_lexer->looking_for_object_index = false;
681 curr_lexer->at_beginning_of_statement = false; 745 curr_lexer->at_beginning_of_statement = false;
682 746
683 COUNT_TOK_AND_RETURN ('@'); 747 return curr_lexer->count_token ('@');
684 748
685 } 749 }
686 750
687 %{ 751 %{
688 // A new line character. New line characters inside matrix constants 752 // A new line character. New line characters inside matrix constants
689 // are handled by the <MATRIX_START> start state code above. If closest 753 // are handled by the <MATRIX_START> start state code above. If closest
690 // nesting is inside parentheses, don't return a row separator. 754 // nesting is inside parentheses, don't return a row separator.
691 %} 755 %}
692 756
693 {NL} { 757 {NL} {
694 LEXER_DEBUG ("{NL}"); 758 curr_lexer->lexer_debug ("{NL}");
695 759
696 curr_lexer->input_line_number++; 760 curr_lexer->input_line_number++;
697 curr_lexer->current_input_column = 1; 761 curr_lexer->current_input_column = 1;
698 762
699 curr_lexer->quote_is_transpose = false; 763 curr_lexer->quote_is_transpose = false;
700 curr_lexer->convert_spaces_to_comma = true; 764 curr_lexer->convert_spaces_to_comma = true;
701 765
702 if (curr_lexer->nesting_level.none ()) 766 if (curr_lexer->nesting_level.none ())
703 { 767 {
704 curr_lexer->at_beginning_of_statement = true; 768 curr_lexer->at_beginning_of_statement = true;
705 COUNT_TOK_AND_RETURN ('\n'); 769 return curr_lexer->count_token ('\n');
706 } 770 }
707 else if (curr_lexer->nesting_level.is_paren ()) 771 else if (curr_lexer->nesting_level.is_paren ())
708 { 772 {
709 curr_lexer->at_beginning_of_statement = false; 773 curr_lexer->at_beginning_of_statement = false;
710 curr_lexer->gripe_matlab_incompatible ("bare newline inside parentheses"); 774 curr_lexer->gripe_matlab_incompatible ("bare newline inside parentheses");
717 // Single quote can either be the beginning of a string or a transpose 781 // Single quote can either be the beginning of a string or a transpose
718 // operator. 782 // operator.
719 %} 783 %}
720 784
721 "'" { 785 "'" {
722 LEXER_DEBUG ("'"); 786 curr_lexer->lexer_debug ("'");
723 787
724 curr_lexer->current_input_column++; 788 curr_lexer->current_input_column++;
725 curr_lexer->convert_spaces_to_comma = true; 789 curr_lexer->convert_spaces_to_comma = true;
726 790
727 if (curr_lexer->quote_is_transpose) 791 if (curr_lexer->quote_is_transpose)
728 { 792 {
729 curr_lexer->do_comma_insert_check (); 793 curr_lexer->do_comma_insert_check ();
730 COUNT_TOK_AND_RETURN (QUOTE); 794 return curr_lexer->count_token (QUOTE);
731 } 795 }
732 else 796 else
733 { 797 {
734 int tok = curr_lexer->handle_string ('\''); 798 int tok = curr_lexer->handle_string ('\'');
735 COUNT_TOK_AND_RETURN (tok); 799 return curr_lexer->count_token (tok);
736 } 800 }
737 } 801 }
738 802
739 %{ 803 %{
740 // Double quotes always begin strings. 804 // Double quotes always begin strings.
741 %} 805 %}
742 806
743 \" { 807 \" {
744 LEXER_DEBUG ("\""); 808 curr_lexer->lexer_debug ("\"");
745 809
746 curr_lexer->current_input_column++; 810 curr_lexer->current_input_column++;
747 int tok = curr_lexer->handle_string ('"'); 811 int tok = curr_lexer->handle_string ('"');
748 812
749 COUNT_TOK_AND_RETURN (tok); 813 return curr_lexer->count_token (tok);
750 } 814 }
751
752 %{
753 // Gobble comments.
754 %}
755
756 {CCHAR} {
757 LEXER_DEBUG ("{CCHAR}");
758
759 curr_lexer->looking_for_object_index = false;
760
761 curr_lexer->xunput (yytext[0]);
762
763 bool eof = false;
764 int tok = curr_lexer->process_comment (false, eof);
765
766 if (eof)
767 return curr_lexer->handle_end_of_input ();
768 else if (tok > 0)
769 COUNT_TOK_AND_RETURN (tok);
770 }
771
772 %{
773 // Block comments.
774 %}
775
776 ^{S}*{CCHAR}\{{S}*{NL} {
777 LEXER_DEBUG ("^{S}*{CCHAR}\\{{S}*{NL}");
778
779 curr_lexer->looking_for_object_index = false;
780
781 curr_lexer->input_line_number++;
782 curr_lexer->current_input_column = 1;
783 curr_lexer->block_comment_nesting_level++;
784 curr_lexer->decrement_promptflag ();
785
786 bool eof = false;
787 curr_lexer->process_comment (true, eof);
788 }
789 815
790 %{ 816 %{
791 // Other operators. 817 // Other operators.
792 %} 818 %}
793 819
794 ":" { LEXER_DEBUG (":"); BIN_OP_RETURN (':', false, false); } 820 ":" { return curr_lexer->handle_op (":", ':'); }
795 821 ".+" { return curr_lexer->handle_incompatible_op (".+", EPLUS); }
796 ".+" { LEXER_DEBUG (".+"); XBIN_OP_RETURN (EPLUS, false, false); } 822 ".-" { return curr_lexer->handle_incompatible_op (".-", EMINUS); }
797 ".-" { LEXER_DEBUG (".-"); XBIN_OP_RETURN (EMINUS, false, false); } 823 ".*" { return curr_lexer->handle_op (".*", EMUL); }
798 ".*" { LEXER_DEBUG (".*"); BIN_OP_RETURN (EMUL, false, false); } 824 "./" { return curr_lexer->handle_op ("./", EDIV); }
799 "./" { LEXER_DEBUG ("./"); BIN_OP_RETURN (EDIV, false, false); } 825 ".\\" { return curr_lexer->handle_op (".\\", ELEFTDIV); }
800 ".\\" { LEXER_DEBUG (".\\"); BIN_OP_RETURN (ELEFTDIV, false, false); } 826 ".^" { return curr_lexer->handle_op (".^", EPOW); }
801 ".^" { LEXER_DEBUG (".^"); BIN_OP_RETURN (EPOW, false, false); } 827 ".**" { return curr_lexer->handle_incompatible_op (".**", EPOW); }
802 ".**" { LEXER_DEBUG (".**"); XBIN_OP_RETURN (EPOW, false, false); } 828 "<=" { return curr_lexer->handle_op ("<=", EXPR_LE); }
803 ".'" { LEXER_DEBUG (".'"); curr_lexer->do_comma_insert_check (); BIN_OP_RETURN (TRANSPOSE, true, false); } 829 "==" { return curr_lexer->handle_op ("==", EXPR_EQ); }
804 "++" { LEXER_DEBUG ("++"); curr_lexer->do_comma_insert_check (); XBIN_OP_RETURN_INTERNAL (PLUS_PLUS, true, false, true); } 830 "~=" { return curr_lexer->handle_op ("~=", EXPR_NE); }
805 "--" { LEXER_DEBUG ("--"); curr_lexer->do_comma_insert_check (); XBIN_OP_RETURN_INTERNAL (MINUS_MINUS, true, false, true); } 831 "!=" { return curr_lexer->handle_incompatible_op ("!=", EXPR_NE); }
806 "<=" { LEXER_DEBUG ("<="); BIN_OP_RETURN (EXPR_LE, false, false); } 832 ">=" { return curr_lexer->handle_op (">=", EXPR_GE); }
807 "==" { LEXER_DEBUG ("=="); BIN_OP_RETURN (EXPR_EQ, false, false); } 833 "&" { return curr_lexer->handle_op ("&", EXPR_AND); }
808 "~=" { LEXER_DEBUG ("~="); BIN_OP_RETURN (EXPR_NE, false, false); } 834 "|" { return curr_lexer->handle_op ("|", EXPR_OR); }
809 "!=" { LEXER_DEBUG ("!="); XBIN_OP_RETURN (EXPR_NE, false, false); } 835 "<" { return curr_lexer->handle_op ("<", EXPR_LT); }
810 ">=" { LEXER_DEBUG (">="); BIN_OP_RETURN (EXPR_GE, false, false); } 836 ">" { return curr_lexer->handle_op (">", EXPR_GT); }
811 "&" { LEXER_DEBUG ("&"); BIN_OP_RETURN (EXPR_AND, false, false); } 837 "+" { return curr_lexer->handle_op ("+", '+'); }
812 "|" { LEXER_DEBUG ("|"); BIN_OP_RETURN (EXPR_OR, false, false); } 838 "-" { return curr_lexer->handle_op ("-", '-'); }
813 "<" { LEXER_DEBUG ("<"); BIN_OP_RETURN (EXPR_LT, false, false); } 839 "*" { return curr_lexer->handle_op ("*", '*'); }
814 ">" { LEXER_DEBUG (">"); BIN_OP_RETURN (EXPR_GT, false, false); } 840 "/" { return curr_lexer->handle_op ("/", '/'); }
815 "+" { LEXER_DEBUG ("+"); BIN_OP_RETURN ('+', false, false); } 841 "\\" { return curr_lexer->handle_op ("\\", LEFTDIV); }
816 "-" { LEXER_DEBUG ("-"); BIN_OP_RETURN ('-', false, false); } 842 "^" { return curr_lexer->handle_op ("^", POW); }
817 "*" { LEXER_DEBUG ("*"); BIN_OP_RETURN ('*', false, false); } 843 "**" { return curr_lexer->handle_incompatible_op ("**", POW); }
818 "/" { LEXER_DEBUG ("/"); BIN_OP_RETURN ('/', false, false); } 844 "=" { return curr_lexer->handle_op ("=", '=', true, false); }
819 "\\" { LEXER_DEBUG ("\\"); BIN_OP_RETURN (LEFTDIV, false, false); } 845 "&&" { return curr_lexer->handle_op ("&&", EXPR_AND_AND); }
820 ";" { LEXER_DEBUG (";"); BIN_OP_RETURN (';', true, true); } 846 "||" { return curr_lexer->handle_op ("||", EXPR_OR_OR); }
821 "," { LEXER_DEBUG (","); BIN_OP_RETURN (',', true, ! curr_lexer->looking_at_object_index.front ()); } 847 "<<" { return curr_lexer->handle_incompatible_op ("<<", LSHIFT); }
822 "^" { LEXER_DEBUG ("^"); BIN_OP_RETURN (POW, false, false); } 848 ">>" { return curr_lexer->handle_incompatible_op (">>", RSHIFT); }
823 "**" { LEXER_DEBUG ("**"); XBIN_OP_RETURN (POW, false, false); } 849 "~" { return curr_lexer->handle_op ("~", EXPR_NOT); }
824 "=" { LEXER_DEBUG ("="); BIN_OP_RETURN ('=', true, false); } 850 "!" { return curr_lexer->handle_incompatible_op ("!", EXPR_NOT); }
825 "&&" { LEXER_DEBUG ("&&"); BIN_OP_RETURN (EXPR_AND_AND, false, false); } 851 ";" { return curr_lexer->handle_op (";", ';', true, true); }
826 "||" { LEXER_DEBUG ("||"); BIN_OP_RETURN (EXPR_OR_OR, false, false); } 852
827 "<<" { LEXER_DEBUG ("<<"); XBIN_OP_RETURN (LSHIFT, false, false); } 853 "," {
828 ">>" { LEXER_DEBUG (">>"); XBIN_OP_RETURN (RSHIFT, false, false); } 854 return curr_lexer->handle_op
829 855 (",", ',', true, ! curr_lexer->looking_at_object_index.front ());
830 {NOT} { 856 }
831 LEXER_DEBUG ("{NOT}"); 857
832 858 ".'" {
833 if (yytext[0] == '~') 859 curr_lexer->do_comma_insert_check ();
834 BIN_OP_RETURN (EXPR_NOT, false, false); 860 return curr_lexer->handle_op (".'", TRANSPOSE, true, false);
835 else 861 }
836 XBIN_OP_RETURN (EXPR_NOT, false, false); 862
863 "++" {
864 curr_lexer->do_comma_insert_check ();
865 return curr_lexer->handle_incompatible_op
866 ("++", PLUS_PLUS, true, false, true);
867 }
868
869 "--" {
870 ;
871 curr_lexer->do_comma_insert_check ();
872 return curr_lexer->handle_incompatible_op
873 ("--", MINUS_MINUS, true, false, true);
837 } 874 }
838 875
839 "(" { 876 "(" {
840 LEXER_DEBUG ("("); 877 curr_lexer->lexer_debug ("(");
841 878
842 // If we are looking for an object index, then push TRUE for 879 // If we are looking for an object index, then push TRUE for
843 // looking_at_object_index. Otherwise, just push whatever state 880 // looking_at_object_index. Otherwise, just push whatever state
844 // is current (so that we can pop it off the stack when we find 881 // is current (so that we can pop it off the stack when we find
845 // the matching close paren). 882 // the matching close paren).
852 curr_lexer->at_beginning_of_statement = false; 889 curr_lexer->at_beginning_of_statement = false;
853 890
854 curr_lexer->nesting_level.paren (); 891 curr_lexer->nesting_level.paren ();
855 curr_lexer->decrement_promptflag (); 892 curr_lexer->decrement_promptflag ();
856 893
857 TOK_RETURN ('('); 894 return curr_lexer->handle_token ('(');
858 } 895 }
859 896
860 ")" { 897 ")" {
861 LEXER_DEBUG (")"); 898 curr_lexer->lexer_debug (")");
862 899
863 curr_lexer->nesting_level.remove (); 900 curr_lexer->nesting_level.remove ();
864 curr_lexer->current_input_column++; 901 curr_lexer->current_input_column++;
865 902
866 curr_lexer->looking_at_object_index.pop_front (); 903 curr_lexer->looking_at_object_index.pop_front ();
875 if (curr_lexer->looking_at_anon_fcn_args) 912 if (curr_lexer->looking_at_anon_fcn_args)
876 curr_lexer->looking_at_anon_fcn_args = false; 913 curr_lexer->looking_at_anon_fcn_args = false;
877 914
878 curr_lexer->do_comma_insert_check (); 915 curr_lexer->do_comma_insert_check ();
879 916
880 COUNT_TOK_AND_RETURN (')'); 917 return curr_lexer->count_token (')');
881 } 918 }
882 919
883 "." { 920 "." {
884 LEXER_DEBUG ("."); 921 curr_lexer->lexer_debug (".");
885 922
886 curr_lexer->looking_for_object_index = false; 923 curr_lexer->looking_for_object_index = false;
887 curr_lexer->at_beginning_of_statement = false; 924 curr_lexer->at_beginning_of_statement = false;
888 925
889 TOK_RETURN ('.'); 926 return curr_lexer->handle_token ('.');
890 } 927 }
891 928
892 "+=" { LEXER_DEBUG ("+="); XBIN_OP_RETURN (ADD_EQ, false, false); } 929 %{
893 "-=" { LEXER_DEBUG ("-="); XBIN_OP_RETURN (SUB_EQ, false, false); } 930 // op= operators.
894 "*=" { LEXER_DEBUG ("*="); XBIN_OP_RETURN (MUL_EQ, false, false); } 931 %}
895 "/=" { LEXER_DEBUG ("/="); XBIN_OP_RETURN (DIV_EQ, false, false); } 932
896 "\\=" { LEXER_DEBUG ("\\="); XBIN_OP_RETURN (LEFTDIV_EQ, false, false); } 933 "+=" { return curr_lexer->handle_incompatible_op ("+=", ADD_EQ); }
897 ".+=" { LEXER_DEBUG (".+="); XBIN_OP_RETURN (ADD_EQ, false, false); } 934 "-=" { return curr_lexer->handle_incompatible_op ("-=", SUB_EQ); }
898 ".-=" { LEXER_DEBUG (".-="); XBIN_OP_RETURN (SUB_EQ, false, false); } 935 "*=" { return curr_lexer->handle_incompatible_op ("*=", MUL_EQ); }
899 ".*=" { LEXER_DEBUG (".*="); XBIN_OP_RETURN (EMUL_EQ, false, false); } 936 "/=" { return curr_lexer->handle_incompatible_op ("/=", DIV_EQ); }
900 "./=" { LEXER_DEBUG ("./="); XBIN_OP_RETURN (EDIV_EQ, false, false); } 937 "\\=" { return curr_lexer->handle_incompatible_op ("\\=", LEFTDIV_EQ); }
901 ".\\=" { LEXER_DEBUG (".\\="); XBIN_OP_RETURN (ELEFTDIV_EQ, false, false); } 938 ".+=" { return curr_lexer->handle_incompatible_op (".+=", ADD_EQ); }
902 {POW}= { LEXER_DEBUG ("{POW}="); XBIN_OP_RETURN (POW_EQ, false, false); } 939 ".-=" { return curr_lexer->handle_incompatible_op (".-=", SUB_EQ); }
903 {EPOW}= { LEXER_DEBUG ("{EPOW}="); XBIN_OP_RETURN (EPOW_EQ, false, false); } 940 ".*=" { return curr_lexer->handle_incompatible_op (".*=", EMUL_EQ); }
904 "&=" { LEXER_DEBUG ("&="); XBIN_OP_RETURN (AND_EQ, false, false); } 941 "./=" { return curr_lexer->handle_incompatible_op ("./=", EDIV_EQ); }
905 "|=" { LEXER_DEBUG ("|="); XBIN_OP_RETURN (OR_EQ, false, false); } 942 ".\\=" { return curr_lexer->handle_incompatible_op (".\\=", ELEFTDIV_EQ); }
906 "<<=" { LEXER_DEBUG ("<<="); XBIN_OP_RETURN (LSHIFT_EQ, false, false); } 943 "^=" { return curr_lexer->handle_incompatible_op ("^=", POW_EQ); }
907 ">>=" { LEXER_DEBUG (">>="); XBIN_OP_RETURN (RSHIFT_EQ, false, false); } 944 "**=" { return curr_lexer->handle_incompatible_op ("^=", POW_EQ); }
945 ".^=" { return curr_lexer->handle_incompatible_op (".^=", EPOW_EQ); }
946 ".**=" { return curr_lexer->handle_incompatible_op (".^=", EPOW_EQ); }
947 "&=" { return curr_lexer->handle_incompatible_op ("&=", AND_EQ); }
948 "|=" { return curr_lexer->handle_incompatible_op ("|=", OR_EQ); }
949 "<<=" { return curr_lexer->handle_incompatible_op ("<<=", LSHIFT_EQ); }
950 ">>=" { return curr_lexer->handle_incompatible_op (">>=", RSHIFT_EQ); }
908 951
909 \{{S}* { 952 \{{S}* {
910 LEXER_DEBUG ("\\{{S}*"); 953 curr_lexer->lexer_debug ("\\{{S}*");
911 954
912 curr_lexer->nesting_level.brace (); 955 curr_lexer->nesting_level.brace ();
913 956
914 curr_lexer->looking_at_object_index.push_front 957 curr_lexer->looking_at_object_index.push_front
915 (curr_lexer->looking_for_object_index); 958 (curr_lexer->looking_for_object_index);
922 965
923 curr_lexer->decrement_promptflag (); 966 curr_lexer->decrement_promptflag ();
924 curr_lexer->eat_whitespace (); 967 curr_lexer->eat_whitespace ();
925 968
926 curr_lexer->braceflag++; 969 curr_lexer->braceflag++;
927 BEGIN (MATRIX_START); 970
928 COUNT_TOK_AND_RETURN ('{'); 971 curr_lexer->push_start_state (MATRIX_START);
972
973 return curr_lexer->count_token ('{');
929 } 974 }
930 975
931 "}" { 976 "}" {
932 LEXER_DEBUG ("}"); 977 curr_lexer->lexer_debug ("}");
933 978
934 curr_lexer->looking_at_object_index.pop_front (); 979 curr_lexer->looking_at_object_index.pop_front ();
935 980
936 curr_lexer->looking_for_object_index = true; 981 curr_lexer->looking_for_object_index = true;
937 curr_lexer->at_beginning_of_statement = false; 982 curr_lexer->at_beginning_of_statement = false;
938 983
939 curr_lexer->nesting_level.remove (); 984 curr_lexer->nesting_level.remove ();
940 985
941 TOK_RETURN ('}'); 986 return curr_lexer->handle_token ('}');
942 } 987 }
943 988
944 %{ 989 %{
945 // Unrecognized input is a lexical error. 990 // Unrecognized input is a lexical error.
946 %} 991 %}
947 992
948 . { 993 . {
949 LEXER_DEBUG ("."); 994 curr_lexer->lexer_debug (".");
950 995
951 curr_lexer->xunput (yytext[0]); 996 curr_lexer->xunput (yytext[0]);
952 997
953 int c = curr_lexer->text_yyinput (); 998 int c = curr_lexer->text_yyinput ();
954 999
1292 char *buf; 1337 char *buf;
1293 }; 1338 };
1294 1339
1295 lexical_feedback::~lexical_feedback (void) 1340 lexical_feedback::~lexical_feedback (void)
1296 { 1341 {
1297 reset_token_stack (); 1342 tokens.clear ();
1298 } 1343 }
1299 1344
1300 void 1345 void
1301 lexical_feedback::init (void) 1346 lexical_feedback::init (void)
1302 { 1347 {
1338 defining_func = 0; 1383 defining_func = 0;
1339 looking_at_function_handle = 0; 1384 looking_at_function_handle = 0;
1340 block_comment_nesting_level = 0; 1385 block_comment_nesting_level = 0;
1341 token_count = 0; 1386 token_count = 0;
1342 current_input_line = ""; 1387 current_input_line = "";
1388 comment_text = "";
1343 help_text = ""; 1389 help_text = "";
1344 fcn_file_name = ""; 1390 fcn_file_name = "";
1345 fcn_file_full_name = ""; 1391 fcn_file_full_name = "";
1346 looking_at_object_index.clear (); 1392 looking_at_object_index.clear ();
1347 looking_at_object_index.push_front (false); 1393 looking_at_object_index.push_front (false);
1351 1397
1352 pending_local_variables.clear (); 1398 pending_local_variables.clear ();
1353 1399
1354 nesting_level.reset (); 1400 nesting_level.reset ();
1355 1401
1356 reset_token_stack (); 1402 tokens.clear ();
1357 } 1403 }
1358 1404
1359 void 1405 static bool
1360 lexical_feedback::reset_token_stack (void) 1406 looks_like_copyright (const std::string& s)
1361 { 1407 {
1362 // Clear out the stack of token info used to track line and 1408 bool retval = false;
1363 // column numbers. 1409
1364 1410 if (! s.empty ())
1365 while (! token_stack.empty ()) 1411 {
1366 { 1412 size_t offset = s.find_first_not_of (" \t");
1367 delete token_stack.top (); 1413
1368 token_stack.pop (); 1414 retval = (s.substr (offset, 9) == "Copyright" || s.substr (offset, 6) == "Author");
1369 } 1415 }
1416
1417 return retval;
1418 }
1419
1420 int
1421 lexical_feedback::finish_comment (octave_comment_elt::comment_type typ)
1422 {
1423 bool copyright = looks_like_copyright (comment_text);
1424
1425 if (nesting_level.none () && help_text.empty ()
1426 && ! comment_text.empty () && ! copyright)
1427 help_text = comment_text;
1428
1429 if (copyright)
1430 typ = octave_comment_elt::copyright;
1431
1432 octave_comment_buffer::append (comment_text, typ);
1433
1434 comment_text = "";
1435
1436 quote_is_transpose = false;
1437 convert_spaces_to_comma = true;
1438 at_beginning_of_statement = true;
1439
1440 if (nesting_level.none ())
1441 return '\n';
1442 else if (nesting_level.is_bracket_or_brace ())
1443 // FIXME -- this result will be different if the comment follows a
1444 // continuation token.
1445 return ';';
1446 else
1447 return 0;
1370 } 1448 }
1371 1449
1372 void 1450 void
1373 octave_lexer::input_buffer::fill (const std::string& input, bool eof_arg) 1451 octave_lexer::input_buffer::fill (const std::string& input, bool eof_arg)
1374 { 1452 {
1424 yylex_init (&scanner); 1502 yylex_init (&scanner);
1425 1503
1426 // Make octave_lexer object available through yyextra in 1504 // Make octave_lexer object available through yyextra in
1427 // flex-generated lexer. 1505 // flex-generated lexer.
1428 yyset_extra (this, scanner); 1506 yyset_extra (this, scanner);
1507
1508 clear_start_state ();
1429 } 1509 }
1430 1510
1431 // Inside Flex-generated functions, yyg is the scanner cast to its real 1511 // Inside Flex-generated functions, yyg is the scanner cast to its real
1432 // type. The BEGIN macro uses yyg and we want to use that in 1512 // type. Some flex macros that we use in octave_lexer member functions
1433 // octave_lexer member functions. If we could set the start state 1513 // (for example, BEGIN) use yyg. If we could perform the actions of
1434 // by calling a function instead of using the BEGIN macro, we could 1514 // these macros with functions instead, we could eliminate the
1435 // eliminate the OCTAVE_YYG macro. 1515 // OCTAVE_YYG macro.
1436 1516
1437 #define OCTAVE_YYG \ 1517 #define OCTAVE_YYG \
1438 struct yyguts_t *yyg = static_cast<struct yyguts_t*> (scanner) 1518 struct yyguts_t *yyg = static_cast<struct yyguts_t*> (scanner)
1439 1519
1440 void 1520 void
1441 octave_lexer::reset (void) 1521 octave_lexer::reset (void)
1442 { 1522 {
1443 OCTAVE_YYG;
1444
1445 // Start off on the right foot. 1523 // Start off on the right foot.
1446 BEGIN (INITIAL); 1524 clear_start_state ();
1447 1525
1448 parser_symtab_context.clear (); 1526 parser_symtab_context.clear ();
1449 1527
1450 // We do want a prompt by default. 1528 // We do want a prompt by default.
1451 promptflag (1); 1529 promptflag (1);
1467 } 1545 }
1468 1546
1469 void 1547 void
1470 octave_lexer::prep_for_file (void) 1548 octave_lexer::prep_for_file (void)
1471 { 1549 {
1472 OCTAVE_YYG; 1550 reading_script_file = true;
1473 1551
1474 BEGIN (INPUT_FILE_BEGIN); 1552 push_start_state (INPUT_FILE_START);
1475 } 1553 }
1476 1554
1477 int 1555 int
1478 octave_lexer::read (char *buf, unsigned max_size) 1556 octave_lexer::read (char *buf, unsigned max_size)
1479 { 1557 {
1500 } 1578 }
1501 1579
1502 int 1580 int
1503 octave_lexer::handle_end_of_input (void) 1581 octave_lexer::handle_end_of_input (void)
1504 { 1582 {
1505 // FIXME -- we need this because of the way TOK_RETURN is defined. DO 1583 lexer_debug ("<<EOF>>");
1506 // something better than that...
1507 OCTAVE_YYG;
1508
1509 LEXER_DEBUG ("<<EOF>>");
1510 1584
1511 if (block_comment_nesting_level != 0) 1585 if (block_comment_nesting_level != 0)
1512 { 1586 {
1513 warning ("block comment open at end of input"); 1587 warning ("block comment open at end of input");
1514 1588
1516 && ! fcn_file_name.empty ()) 1590 && ! fcn_file_name.empty ())
1517 warning ("near line %d of file '%s.m'", 1591 warning ("near line %d of file '%s.m'",
1518 input_line_number, fcn_file_name.c_str ()); 1592 input_line_number, fcn_file_name.c_str ());
1519 } 1593 }
1520 1594
1521 TOK_RETURN (END_OF_INPUT); 1595 return handle_token (END_OF_INPUT);
1522 } 1596 }
1523 1597
1524 char * 1598 char *
1525 octave_lexer::flex_yytext (void) 1599 octave_lexer::flex_yytext (void)
1526 { 1600 {
1889 octave_lexer::is_variable (const std::string& name) 1963 octave_lexer::is_variable (const std::string& name)
1890 { 1964 {
1891 return (symbol_table::is_variable (name) 1965 return (symbol_table::is_variable (name)
1892 || (pending_local_variables.find (name) 1966 || (pending_local_variables.find (name)
1893 != pending_local_variables.end ())); 1967 != pending_local_variables.end ()));
1894 }
1895
1896 std::string
1897 octave_lexer::grab_block_comment (stream_reader& reader, bool& eof)
1898 {
1899 std::string buf;
1900
1901 bool at_bol = true;
1902 bool look_for_marker = false;
1903
1904 bool warned_incompatible = false;
1905
1906 int c = 0;
1907
1908 while ((c = reader.getc ()) != EOF)
1909 {
1910 current_input_column++;
1911
1912 if (look_for_marker)
1913 {
1914 at_bol = false;
1915 look_for_marker = false;
1916
1917 if (c == '{' || c == '}')
1918 {
1919 std::string tmp_buf (1, static_cast<char> (c));
1920
1921 int type = c;
1922
1923 bool done = false;
1924
1925 while ((c = reader.getc ()) != EOF && ! done)
1926 {
1927 current_input_column++;
1928
1929 switch (c)
1930 {
1931 case ' ':
1932 case '\t':
1933 tmp_buf += static_cast<char> (c);
1934 break;
1935
1936 case '\n':
1937 {
1938 current_input_column = 0;
1939 at_bol = true;
1940 done = true;
1941
1942 if (type == '{')
1943 {
1944 block_comment_nesting_level++;
1945 decrement_promptflag ();
1946 }
1947 else
1948 {
1949 block_comment_nesting_level--;
1950 increment_promptflag ();
1951
1952 if (block_comment_nesting_level == 0)
1953 {
1954 buf += grab_comment_block (reader, true, eof);
1955
1956 return buf;
1957 }
1958 }
1959 }
1960 break;
1961
1962 default:
1963 at_bol = false;
1964 tmp_buf += static_cast<char> (c);
1965 buf += tmp_buf;
1966 done = true;
1967 break;
1968 }
1969 }
1970 }
1971 }
1972
1973 if (at_bol && (c == '%' || c == '#'))
1974 {
1975 if (c == '#' && ! warned_incompatible)
1976 {
1977 warned_incompatible = true;
1978 maybe_gripe_matlab_incompatible_comment (c);
1979 }
1980
1981 at_bol = false;
1982 look_for_marker = true;
1983 }
1984 else
1985 {
1986 buf += static_cast<char> (c);
1987
1988 if (c == '\n')
1989 {
1990 current_input_column = 0;
1991 at_bol = true;
1992 }
1993 }
1994 }
1995
1996 if (c == EOF)
1997 eof = true;
1998
1999 return buf;
2000 }
2001
2002 std::string
2003 octave_lexer::grab_comment_block (stream_reader& reader, bool at_bol,
2004 bool& eof)
2005 {
2006 std::string buf;
2007
2008 // TRUE means we are at the beginning of a comment block.
2009 bool begin_comment = false;
2010
2011 // TRUE means we are currently reading a comment block.
2012 bool in_comment = false;
2013
2014 bool warned_incompatible = false;
2015
2016 int c = 0;
2017
2018 while ((c = reader.getc ()) != EOF)
2019 {
2020 current_input_column++;
2021
2022 if (begin_comment)
2023 {
2024 if (c == '%' || c == '#')
2025 {
2026 at_bol = false;
2027 continue;
2028 }
2029 else if (at_bol && c == '{')
2030 {
2031 std::string tmp_buf (1, static_cast<char> (c));
2032
2033 bool done = false;
2034
2035 while ((c = reader.getc ()) != EOF && ! done)
2036 {
2037 current_input_column++;
2038
2039 switch (c)
2040 {
2041 case ' ':
2042 case '\t':
2043 tmp_buf += static_cast<char> (c);
2044 break;
2045
2046 case '\n':
2047 {
2048 current_input_column = 0;
2049 at_bol = true;
2050 done = true;
2051
2052 block_comment_nesting_level++;
2053 decrement_promptflag ();
2054
2055 buf += grab_block_comment (reader, eof);
2056
2057 in_comment = false;
2058
2059 if (eof)
2060 goto done;
2061 }
2062 break;
2063
2064 default:
2065 at_bol = false;
2066 tmp_buf += static_cast<char> (c);
2067 buf += tmp_buf;
2068 done = true;
2069 break;
2070 }
2071 }
2072 }
2073 else
2074 {
2075 at_bol = false;
2076 begin_comment = false;
2077 }
2078 }
2079
2080 if (in_comment)
2081 {
2082 buf += static_cast<char> (c);
2083
2084 if (c == '\n')
2085 {
2086 at_bol = true;
2087 current_input_column = 0;
2088 in_comment = false;
2089
2090 // FIXME -- bailing out here prevents things like
2091 //
2092 // octave> # comment
2093 // octave> x = 1
2094 //
2095 // from failing at the command line, while still
2096 // allowing blocks of comments to be grabbed properly
2097 // for function doc strings. But only the first line of
2098 // a mult-line doc string will be picked up for
2099 // functions defined on the command line. We need a
2100 // better way of collecting these comments...
2101 if (! (reading_fcn_file || reading_script_file))
2102 goto done;
2103 }
2104 }
2105 else
2106 {
2107 switch (c)
2108 {
2109 case ' ':
2110 case '\t':
2111 break;
2112
2113 case '#':
2114 if (! warned_incompatible)
2115 {
2116 warned_incompatible = true;
2117 maybe_gripe_matlab_incompatible_comment (c);
2118 }
2119 // fall through...
2120
2121 case '%':
2122 in_comment = true;
2123 begin_comment = true;
2124 break;
2125
2126 default:
2127 current_input_column--;
2128 reader.ungetc (c);
2129 goto done;
2130 }
2131 }
2132 }
2133
2134 done:
2135
2136 if (c == EOF)
2137 eof = true;
2138
2139 return buf;
2140 }
2141
2142 static bool
2143 looks_like_copyright (const std::string& s)
2144 {
2145 bool retval = false;
2146
2147 if (! s.empty ())
2148 {
2149 size_t offset = s.find_first_not_of (" \t");
2150
2151 retval = (s.substr (offset, 9) == "Copyright" || s.substr (offset, 6) == "Author");
2152 }
2153
2154 return retval;
2155 }
2156
2157 int
2158 octave_lexer::process_comment (bool start_in_block, bool& eof)
2159 {
2160 OCTAVE_YYG;
2161
2162 eof = false;
2163
2164 char *yytxt = flex_yytext ();
2165 flex_stream_reader flex_reader (this, yytxt);
2166
2167 // process_comment is only supposed to be called when we are not
2168 // initially looking at a block comment.
2169
2170 std::string txt = start_in_block
2171 ? grab_block_comment (flex_reader, eof)
2172 : grab_comment_block (flex_reader, false, eof);
2173
2174 if (lexer_debug_flag)
2175 std::cerr << "C: " << txt << std::endl;
2176
2177 if (nesting_level.none () && help_text.empty () && ! txt.empty ()
2178 && ! looks_like_copyright (txt))
2179 help_text = txt;
2180
2181 octave_comment_buffer::append (txt);
2182
2183 current_input_column = 1;
2184 quote_is_transpose = false;
2185 convert_spaces_to_comma = true;
2186 at_beginning_of_statement = true;
2187
2188 if (YY_START == COMMAND_START)
2189 BEGIN (INITIAL);
2190
2191 if (nesting_level.none ())
2192 return '\n';
2193 else if (nesting_level.is_bracket_or_brace ())
2194 return ';';
2195 else
2196 return 0;
2197 } 1968 }
2198 1969
2199 // Recognize separators. If the separator is a CRLF pair, it is 1970 // Recognize separators. If the separator is a CRLF pair, it is
2200 // replaced by a single LF. 1971 // replaced by a single LF.
2201 1972
2910 } 2681 }
2911 2682
2912 int 2683 int
2913 octave_lexer::handle_close_bracket (bool spc_gobbled, int bracket_type) 2684 octave_lexer::handle_close_bracket (bool spc_gobbled, int bracket_type)
2914 { 2685 {
2915 OCTAVE_YYG;
2916
2917 int retval = bracket_type; 2686 int retval = bracket_type;
2918 2687
2919 if (! nesting_level.none ()) 2688 if (! nesting_level.none ())
2920 { 2689 {
2921 nesting_level.remove (); 2690 nesting_level.remove ();
2926 braceflag--; 2695 braceflag--;
2927 else 2696 else
2928 panic_impossible (); 2697 panic_impossible ();
2929 } 2698 }
2930 2699
2931 if (bracketflag == 0 && braceflag == 0) 2700 pop_start_state ();
2932 BEGIN (INITIAL);
2933 2701
2934 if (bracket_type == ']' 2702 if (bracket_type == ']'
2935 && next_token_is_assign_op () 2703 && next_token_is_assign_op ()
2936 && ! looking_at_return_list) 2704 && ! looking_at_return_list)
2937 { 2705 {
3364 // should be ignored. 3132 // should be ignored.
3365 3133
3366 int 3134 int
3367 octave_lexer::handle_identifier (void) 3135 octave_lexer::handle_identifier (void)
3368 { 3136 {
3369 OCTAVE_YYG;
3370
3371 bool at_bos = at_beginning_of_statement; 3137 bool at_bos = at_beginning_of_statement;
3372 3138
3373 char *yytxt = flex_yytext (); 3139 char *yytxt = flex_yytext ();
3374 3140
3375 std::string tok = strip_trailing_whitespace (yytxt); 3141 std::string tok = strip_trailing_whitespace (yytxt);
3483 if (! is_variable (tok)) 3249 if (! is_variable (tok))
3484 { 3250 {
3485 if (at_bos && spc_gobbled && can_be_command (tok) 3251 if (at_bos && spc_gobbled && can_be_command (tok)
3486 && looks_like_command_arg ()) 3252 && looks_like_command_arg ())
3487 { 3253 {
3488 BEGIN (COMMAND_START); 3254 push_start_state (COMMAND_START);
3489 } 3255 }
3490 else if (next_tok_is_eq 3256 else if (next_tok_is_eq
3491 || looking_at_decl_list 3257 || looking_at_decl_list
3492 || looking_at_return_list 3258 || looking_at_return_list
3493 || (looking_at_parameter_list 3259 || (looking_at_parameter_list
3513 // After seeing an identifer, it is ok to convert spaces to a comma 3279 // After seeing an identifer, it is ok to convert spaces to a comma
3514 // (if needed). 3280 // (if needed).
3515 3281
3516 convert_spaces_to_comma = true; 3282 convert_spaces_to_comma = true;
3517 3283
3518 if (! (next_tok_is_eq || YY_START == COMMAND_START)) 3284 if (! (next_tok_is_eq || start_state () == COMMAND_START))
3519 { 3285 {
3520 quote_is_transpose = true; 3286 quote_is_transpose = true;
3521 3287
3522 do_comma_insert_check (); 3288 do_comma_insert_check ();
3523 3289
3603 void 3369 void
3604 octave_lexer::push_token (token *tok) 3370 octave_lexer::push_token (token *tok)
3605 { 3371 {
3606 YYSTYPE *lval = yyget_lval (scanner); 3372 YYSTYPE *lval = yyget_lval (scanner);
3607 lval->tok_val = tok; 3373 lval->tok_val = tok;
3608 token_stack.push (tok); 3374 tokens.push (tok);
3609 } 3375 }
3610 3376
3611 token * 3377 token *
3612 octave_lexer::current_token (void) 3378 octave_lexer::current_token (void)
3613 { 3379 {
3750 } 3516 }
3751 break; 3517 break;
3752 } 3518 }
3753 } 3519 }
3754 3520
3755 static void 3521 void
3756 display_state (int state) 3522 octave_lexer::fatal_error (const char *msg)
3523 {
3524 error (msg);
3525
3526 OCTAVE_QUIT;
3527
3528 yy_fatal_error (msg, scanner);
3529 }
3530
3531 void
3532 octave_lexer::lexer_debug (const char *pattern)
3533 {
3534 if (lexer_debug_flag)
3535 {
3536 std::cerr << std::endl;
3537
3538 display_start_state ();
3539
3540 std::cerr << "P: " << pattern << std::endl;
3541 std::cerr << "T: " << flex_yytext () << std::endl;
3542 }
3543 }
3544
3545 void
3546 octave_lexer::push_start_state (int state)
3547 {
3548 OCTAVE_YYG;
3549
3550 start_state_stack.push (state);
3551
3552 BEGIN (start_state ());
3553 }
3554
3555 void
3556 octave_lexer::pop_start_state (void)
3557 {
3558 OCTAVE_YYG;
3559
3560 start_state_stack.pop ();
3561
3562 BEGIN (start_state ());
3563 }
3564
3565 void
3566 octave_lexer::clear_start_state (void)
3567 {
3568 while (! start_state_stack.empty ())
3569 start_state_stack.pop ();
3570
3571 push_start_state (INITIAL);
3572 }
3573
3574 void
3575 octave_lexer::display_start_state (void) const
3757 { 3576 {
3758 std::cerr << "S: "; 3577 std::cerr << "S: ";
3759 3578
3760 switch (state) 3579 switch (start_state ())
3761 { 3580 {
3762 case INITIAL: 3581 case INITIAL:
3763 std::cerr << "INITIAL" << std::endl; 3582 std::cerr << "INITIAL" << std::endl;
3764 break; 3583 break;
3765 3584
3769 3588
3770 case MATRIX_START: 3589 case MATRIX_START:
3771 std::cerr << "MATRIX_START" << std::endl; 3590 std::cerr << "MATRIX_START" << std::endl;
3772 break; 3591 break;
3773 3592
3774 case INPUT_FILE_BEGIN: 3593 case INPUT_FILE_START:
3775 std::cerr << "INPUT_FILE_BEGIN" << std::endl; 3594 std::cerr << "INPUT_FILE_BEGIN" << std::endl;
3595 break;
3596
3597 case BLOCK_COMMENT_START:
3598 std::cerr << "BLOCK_COMMENT_START" << std::endl;
3599 break;
3600
3601 case LINE_COMMENT_START:
3602 std::cerr << "LINE_COMMENT_START" << std::endl;
3776 break; 3603 break;
3777 3604
3778 default: 3605 default:
3779 std::cerr << "UNKNOWN START STATE!" << std::endl; 3606 std::cerr << "UNKNOWN START STATE!" << std::endl;
3780 break; 3607 break;
3781 } 3608 }
3782 } 3609 }
3783 3610
3784 void 3611 int
3785 octave_lexer::fatal_error (const char *msg) 3612 octave_lexer::handle_op (const char *pattern, int tok, bool convert,
3786 { 3613 bool bos, bool qit)
3787 error (msg); 3614 {
3788 3615 return handle_op_internal (pattern, tok, convert, bos, qit, true);
3789 OCTAVE_QUIT; 3616 }
3790 3617
3791 yy_fatal_error (msg, scanner); 3618 int
3792 } 3619 octave_lexer::handle_incompatible_op (const char *pattern, int tok,
3793 3620 bool convert, bool bos, bool qit)
3794 void 3621 {
3795 octave_lexer::lexer_debug (const char *pattern, const char *text) 3622 return handle_op_internal (pattern, tok, convert, bos, qit, false);
3796 { 3623 }
3797 OCTAVE_YYG; 3624
3798 3625 int
3799 std::cerr << std::endl; 3626 octave_lexer::handle_op_internal (const char *pattern, int tok, bool convert,
3800 3627 bool bos, bool qit, bool compat)
3801 display_state (YY_START); 3628 {
3802 3629 lexer_debug (pattern);
3803 std::cerr << "P: " << pattern << std::endl; 3630
3804 std::cerr << "T: " << text << std::endl; 3631 if (! compat)
3805 } 3632 gripe_matlab_incompatible_operator (flex_yytext ());
3633
3634 push_token (new token (input_line_number, current_input_column));
3635
3636 current_input_column += flex_yyleng ();
3637 quote_is_transpose = qit;
3638 convert_spaces_to_comma = convert;
3639 looking_for_object_index = false;
3640 at_beginning_of_statement = bos;
3641
3642 return count_token (tok);
3643 }
3644
3645 int
3646 octave_lexer::handle_token (const std::string& name, int tok)
3647 {
3648 token *tok_val = new token (name, input_line_number, current_input_column);
3649
3650 return handle_token (tok, tok_val);
3651 }
3652
3653 int
3654 octave_lexer::handle_token (int tok, token *tok_val)
3655 {
3656 if (! tok_val)
3657 tok_val = new token (input_line_number, current_input_column);
3658
3659 push_token (tok_val);
3660
3661 current_input_column += flex_yyleng ();
3662 quote_is_transpose = false;
3663 convert_spaces_to_comma = true;
3664
3665 return count_token (tok);
3666 }
3667
3668 int
3669 octave_lexer::count_token (int tok)
3670 {
3671 if (tok != '\n')
3672 {
3673 Vtoken_count++;
3674 token_count++;
3675 }
3676
3677 return show_token (tok);
3678 }
3679
3680 int
3681 octave_lexer::show_token (int tok)
3682 {
3683 if (Vdisplay_tokens)
3684 display_token (tok);
3685
3686 if (lexer_debug_flag)
3687 {
3688 std::cerr << "R: ";
3689 display_token (tok);
3690 std::cerr << std::endl;
3691 }
3692
3693 return tok;
3694 }