Mercurial > hg > octave-lyh
comparison libinterp/parse-tree/lex.ll @ 16155:0259254a3ccc classdef
maint: periodic merge of default to classdef
* lex.h, lex.ll, parse.h, oct-parse.yy: Resolve conflicts by adapting
classdef changes to new octave_parser and lexical_feedback classes.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Thu, 28 Feb 2013 02:04:24 -0500 |
parents | 6ea536cb7360 aa5e1e8dce66 |
children | a8f9eb92fa6e |
comparison
equal
deleted
inserted
replaced
16050:fc3cb570ac46 | 16155:0259254a3ccc |
---|---|
18 along with Octave; see the file COPYING. If not, see | 18 along with Octave; see the file COPYING. If not, see |
19 <http://www.gnu.org/licenses/>. | 19 <http://www.gnu.org/licenses/>. |
20 | 20 |
21 */ | 21 */ |
22 | 22 |
23 /* | |
24 We are using the pure parser interface and the reentrant lexer | |
25 interface but the Octave parser and lexer are NOT properly | |
26 reentrant because both still use many global variables. It should be | |
27 safe to create a parser object and call it while anotehr parser | |
28 object is active (to parse a callback function while the main | |
29 interactive parser is waiting for input, for example) if you take | |
30 care to properly save and restore (typically with an unwind_protect | |
31 object) relevant global values before and after the nested call. | |
32 */ | |
33 | |
23 %option prefix = "octave_" | 34 %option prefix = "octave_" |
35 %option noyywrap | |
36 %option reentrant | |
37 %option bison-bridge | |
24 | 38 |
25 %top { | 39 %top { |
26 #ifdef HAVE_CONFIG_H | 40 #ifdef HAVE_CONFIG_H |
27 #include <config.h> | 41 #include <config.h> |
28 #endif | 42 #endif |
52 | 66 |
53 #include "cmd-edit.h" | 67 #include "cmd-edit.h" |
54 #include "quit.h" | 68 #include "quit.h" |
55 #include "lo-mappers.h" | 69 #include "lo-mappers.h" |
56 | 70 |
57 // These would be alphabetical, but y.tab.h must be included before | 71 // These would be alphabetical, but oct-parse.h must be included before |
58 // oct-gperf.h and y.tab.h must be included after token.h and the tree | 72 // oct-gperf.h and oct-parse.h must be included after token.h and the tree |
59 // class declarations. We can't include y.tab.h in oct-gperf.h | 73 // class declarations. We can't include oct-parse.h in oct-gperf.h |
60 // because it may not be protected to allow it to be included multiple | 74 // because it may not be protected to allow it to be included multiple |
61 // times. | 75 // times. |
62 | 76 |
63 #include "Cell.h" | 77 #include "Cell.h" |
64 #include "comment-list.h" | 78 #include "comment-list.h" |
94 && defined (YY_FLEX_MAJOR_VERSION) && YY_FLEX_MAJOR_VERSION >= 2 \ | 108 && defined (YY_FLEX_MAJOR_VERSION) && YY_FLEX_MAJOR_VERSION >= 2 \ |
95 && defined (YY_FLEX_MINOR_VERSION) && YY_FLEX_MINOR_VERSION >= 5) | 109 && defined (YY_FLEX_MINOR_VERSION) && YY_FLEX_MINOR_VERSION >= 5) |
96 #error lex.l requires flex version 2.5.4 or later | 110 #error lex.l requires flex version 2.5.4 or later |
97 #endif | 111 #endif |
98 | 112 |
99 #define yylval octave_lval | 113 #define YY_EXTRA_TYPE lexical_feedback * |
114 #define curr_lexer yyextra | |
100 | 115 |
101 // Arrange to get input via readline. | 116 // Arrange to get input via readline. |
102 | 117 |
103 #ifdef YY_INPUT | 118 #ifdef YY_INPUT |
104 #undef YY_INPUT | 119 #undef YY_INPUT |
105 #endif | 120 #endif |
106 #define YY_INPUT(buf, result, max_size) \ | 121 #define YY_INPUT(buf, result, max_size) \ |
107 if ((result = octave_read (buf, max_size)) < 0) \ | 122 result = curr_lexer->octave_read (buf, max_size) |
108 YY_FATAL_ERROR ("octave_read () in flex scanner failed"); | |
109 | 123 |
110 // Try to avoid crashing out completely on fatal scanner errors. | 124 // Try to avoid crashing out completely on fatal scanner errors. |
111 // The call to yy_fatal_error should never happen, but it avoids a | |
112 // 'static function defined but not used' warning from gcc. | |
113 | 125 |
114 #ifdef YY_FATAL_ERROR | 126 #ifdef YY_FATAL_ERROR |
115 #undef YY_FATAL_ERROR | 127 #undef YY_FATAL_ERROR |
116 #endif | 128 #endif |
117 #define YY_FATAL_ERROR(msg) \ | 129 #define YY_FATAL_ERROR(msg) \ |
118 do \ | 130 (yyget_extra (yyscanner))->fatal_error (msg) |
119 { \ | |
120 error (msg); \ | |
121 OCTAVE_QUIT; \ | |
122 yy_fatal_error (msg); \ | |
123 } \ | |
124 while (0) | |
125 | 131 |
126 #define DISPLAY_TOK_AND_RETURN(tok) \ | 132 #define DISPLAY_TOK_AND_RETURN(tok) \ |
127 do \ | 133 do \ |
128 { \ | 134 { \ |
129 int tok_val = tok; \ | 135 int tok_val = tok; \ |
130 if (Vdisplay_tokens) \ | 136 if (Vdisplay_tokens) \ |
131 display_token (tok_val); \ | 137 curr_lexer->display_token (tok_val); \ |
132 if (lexer_debug_flag) \ | 138 if (lexer_debug_flag) \ |
133 { \ | 139 { \ |
134 std::cerr << "R: "; \ | 140 std::cerr << "R: "; \ |
135 display_token (tok_val); \ | 141 curr_lexer->display_token (tok_val); \ |
136 std::cerr << std::endl; \ | 142 std::cerr << std::endl; \ |
137 } \ | 143 } \ |
138 return tok_val; \ | 144 return tok_val; \ |
139 } \ | 145 } \ |
140 while (0) | 146 while (0) |
148 while (0) | 154 while (0) |
149 | 155 |
150 #define TOK_RETURN(tok) \ | 156 #define TOK_RETURN(tok) \ |
151 do \ | 157 do \ |
152 { \ | 158 { \ |
153 current_input_column += yyleng; \ | 159 curr_lexer->current_input_column += yyleng; \ |
154 lexer_flags.quote_is_transpose = false; \ | 160 curr_lexer->quote_is_transpose = false; \ |
155 lexer_flags.convert_spaces_to_comma = true; \ | 161 curr_lexer->convert_spaces_to_comma = true; \ |
156 COUNT_TOK_AND_RETURN (tok); \ | 162 COUNT_TOK_AND_RETURN (tok); \ |
157 } \ | 163 } \ |
158 while (0) | 164 while (0) |
159 | 165 |
160 #define TOK_PUSH_AND_RETURN(name, tok) \ | 166 #define TOK_PUSH_AND_RETURN(name, tok) \ |
161 do \ | 167 do \ |
162 { \ | 168 { \ |
163 yylval.tok_val = new token (name, input_line_number, \ | 169 curr_lexer->push_token \ |
164 current_input_column); \ | 170 (new token (name, curr_lexer->input_line_number, \ |
165 token_stack.push (yylval.tok_val); \ | 171 curr_lexer->current_input_column)); \ |
166 TOK_RETURN (tok); \ | 172 TOK_RETURN (tok); \ |
167 } \ | 173 } \ |
168 while (0) | 174 while (0) |
169 | 175 |
170 #define BIN_OP_RETURN_INTERNAL(tok, convert, bos, qit) \ | 176 #define BIN_OP_RETURN_INTERNAL(tok, convert, bos, qit) \ |
171 do \ | 177 do \ |
172 { \ | 178 { \ |
173 yylval.tok_val = new token (input_line_number, current_input_column); \ | 179 curr_lexer->push_token \ |
174 token_stack.push (yylval.tok_val); \ | 180 (new token (curr_lexer->input_line_number, \ |
175 current_input_column += yyleng; \ | 181 curr_lexer->current_input_column)); \ |
176 lexer_flags.quote_is_transpose = qit; \ | 182 curr_lexer->current_input_column += yyleng; \ |
177 lexer_flags.convert_spaces_to_comma = convert; \ | 183 curr_lexer->quote_is_transpose = qit; \ |
178 lexer_flags.looking_for_object_index = false; \ | 184 curr_lexer->convert_spaces_to_comma = convert; \ |
179 lexer_flags.at_beginning_of_statement = bos; \ | 185 curr_lexer->looking_for_object_index = false; \ |
186 curr_lexer->at_beginning_of_statement = bos; \ | |
180 COUNT_TOK_AND_RETURN (tok); \ | 187 COUNT_TOK_AND_RETURN (tok); \ |
181 } \ | 188 } \ |
182 while (0) | 189 while (0) |
183 | 190 |
184 #define XBIN_OP_RETURN_INTERNAL(tok, convert, bos, qit) \ | 191 #define XBIN_OP_RETURN_INTERNAL(tok, convert, bos, qit) \ |
185 do \ | 192 do \ |
186 { \ | 193 { \ |
187 gripe_matlab_incompatible_operator (yytext); \ | 194 curr_lexer->gripe_matlab_incompatible_operator (yytext); \ |
188 BIN_OP_RETURN_INTERNAL (tok, convert, bos, qit); \ | 195 BIN_OP_RETURN_INTERNAL (tok, convert, bos, qit); \ |
189 } \ | 196 } \ |
190 while (0) | 197 while (0) |
191 | 198 |
192 #define BIN_OP_RETURN(tok, convert, bos) \ | 199 #define BIN_OP_RETURN(tok, convert, bos) \ |
197 while (0) | 204 while (0) |
198 | 205 |
199 #define XBIN_OP_RETURN(tok, convert, bos) \ | 206 #define XBIN_OP_RETURN(tok, convert, bos) \ |
200 do \ | 207 do \ |
201 { \ | 208 { \ |
202 gripe_matlab_incompatible_operator (yytext); \ | 209 curr_lexer->gripe_matlab_incompatible_operator (yytext); \ |
203 BIN_OP_RETURN (tok, convert, bos); \ | 210 BIN_OP_RETURN (tok, convert, bos); \ |
204 } \ | 211 } \ |
205 while (0) | 212 while (0) |
206 | 213 |
207 #define LEXER_DEBUG(pattern) \ | 214 #define LEXER_DEBUG(pattern) \ |
208 do \ | 215 do \ |
209 { \ | 216 { \ |
210 if (lexer_debug_flag) \ | 217 if (lexer_debug_flag) \ |
211 lexer_debug (pattern, yytext); \ | 218 curr_lexer->lexer_debug (pattern, yytext); \ |
212 } \ | 219 } \ |
213 while (0) | 220 while (0) |
214 | 221 |
215 // TRUE means that we have encountered EOF on the input stream. | |
216 bool parser_end_of_input = false; | |
217 | |
218 // Flags that need to be shared between the lexer and parser. | |
219 lexical_feedback lexer_flags; | |
220 | |
221 // Stack to hold tokens so that we can delete them when the parser is | |
222 // reset and avoid growing forever just because we are stashing some | |
223 // information. This has to appear before lex.h is included, because | |
224 // one of the macros defined there uses token_stack. | |
225 // | |
226 // FIXME -- this should really be static, but that causes | |
227 // problems on some systems. | |
228 std::stack <token*> token_stack; | |
229 | |
230 // Did eat_whitespace() eat a space or tab, or a newline, or both? | |
231 | |
232 typedef int yum_yum; | |
233 | |
234 const yum_yum ATE_NOTHING = 0; | |
235 const yum_yum ATE_SPACE_OR_TAB = 1; | |
236 const yum_yum ATE_NEWLINE = 2; | |
237 | |
238 // Is the closest nesting level a square bracket, squiggly brace or a paren? | |
239 | |
240 class bracket_brace_paren_nesting_level | |
241 { | |
242 public: | |
243 | |
244 bracket_brace_paren_nesting_level (void) : context () { } | |
245 | |
246 ~bracket_brace_paren_nesting_level (void) { } | |
247 | |
248 void bracket (void) { context.push (BRACKET); } | |
249 bool is_bracket (void) | |
250 { return ! context.empty () && context.top () == BRACKET; } | |
251 | |
252 void brace (void) { context.push (BRACE); } | |
253 bool is_brace (void) | |
254 { return ! context.empty () && context.top () == BRACE; } | |
255 | |
256 void paren (void) { context.push (PAREN); } | |
257 bool is_paren (void) | |
258 { return ! context.empty () && context.top () == PAREN; } | |
259 | |
260 bool is_bracket_or_brace (void) | |
261 { return (! context.empty () | |
262 && (context.top () == BRACKET || context.top () == BRACE)); } | |
263 | |
264 bool none (void) { return context.empty (); } | |
265 | |
266 void remove (void) { if (! context.empty ()) context.pop (); } | |
267 | |
268 void clear (void) { while (! context.empty ()) context.pop (); } | |
269 | |
270 private: | |
271 | |
272 std::stack<int> context; | |
273 | |
274 static const int BRACKET; | |
275 static const int BRACE; | |
276 static const int PAREN; | |
277 | |
278 bracket_brace_paren_nesting_level (const bracket_brace_paren_nesting_level&); | |
279 | |
280 bracket_brace_paren_nesting_level& | |
281 operator = (const bracket_brace_paren_nesting_level&); | |
282 }; | |
283 | |
284 const int bracket_brace_paren_nesting_level::BRACKET = 1; | |
285 const int bracket_brace_paren_nesting_level::BRACE = 2; | |
286 const int bracket_brace_paren_nesting_level::PAREN = 3; | |
287 | |
288 static bracket_brace_paren_nesting_level nesting_level; | |
289 | |
290 static bool Vdisplay_tokens = false; | 222 static bool Vdisplay_tokens = false; |
291 | 223 |
292 static unsigned int Vtoken_count = 0; | 224 static unsigned int Vtoken_count = 0; |
293 | |
294 // The start state that was in effect when the beginning of a block | |
295 // comment was noticed. | |
296 static int block_comment_nesting_level = 0; | |
297 | 225 |
298 // Internal variable for lexer debugging state. | 226 // Internal variable for lexer debugging state. |
299 static bool lexer_debug_flag = false; | 227 static bool lexer_debug_flag = false; |
300 | 228 |
301 // Forward declarations for functions defined at the bottom of this | 229 // Forward declarations for functions defined at the bottom of this |
302 // file. | 230 // file that are needed inside the lexer actions. |
303 | 231 |
304 static int text_yyinput (void); | |
305 static void xunput (char c, char *buf); | |
306 static void fixup_column_count (char *s); | |
307 static void do_comma_insert_check (void); | |
308 static int is_keyword_token (const std::string& s); | |
309 static int process_comment (bool start_in_block, bool& eof); | |
310 static bool match_any (char c, const char *s); | |
311 static bool next_token_is_sep_op (void); | |
312 static bool next_token_is_bin_op (bool spc_prev); | |
313 static bool next_token_is_postfix_unary_op (bool spc_prev); | |
314 static std::string strip_trailing_whitespace (char *s); | 232 static std::string strip_trailing_whitespace (char *s); |
315 static void handle_number (void); | |
316 static int handle_string (char delim); | |
317 static int handle_close_bracket (bool spc_gobbled, int bracket_type); | |
318 static int handle_superclass_identifier (void); | |
319 static int handle_meta_identifier (void); | |
320 static int handle_identifier (void); | |
321 static bool have_continuation (bool trailing_comments_ok = true); | |
322 static bool have_ellipsis_continuation (bool trailing_comments_ok = true); | |
323 static void scan_for_comments (const char *); | |
324 static yum_yum eat_whitespace (void); | |
325 static yum_yum eat_continuation (void); | |
326 static void maybe_warn_separator_insert (char sep); | |
327 static void gripe_single_quote_string (void); | |
328 static void gripe_matlab_incompatible (const std::string& msg); | |
329 static void maybe_gripe_matlab_incompatible_comment (char c); | |
330 static void gripe_matlab_incompatible_continuation (void); | |
331 static void gripe_matlab_incompatible_operator (const std::string& op); | |
332 static void display_token (int tok); | |
333 static void lexer_debug (const char *pattern, const char *text); | |
334 | 233 |
335 %} | 234 %} |
336 | 235 |
337 D [0-9] | 236 D [0-9] |
338 S [ \t] | 237 S [ \t] |
360 | 259 |
361 <SCRIPT_FILE_BEGIN>. { | 260 <SCRIPT_FILE_BEGIN>. { |
362 LEXER_DEBUG ("<SCRIPT_FILE_BEGIN>."); | 261 LEXER_DEBUG ("<SCRIPT_FILE_BEGIN>."); |
363 | 262 |
364 BEGIN (INITIAL); | 263 BEGIN (INITIAL); |
365 xunput (yytext[0], yytext); | 264 curr_lexer->xunput (yytext[0]); |
366 COUNT_TOK_AND_RETURN (SCRIPT_FILE); | 265 COUNT_TOK_AND_RETURN (SCRIPT_FILE); |
367 } | 266 } |
368 | 267 |
369 <FUNCTION_FILE_BEGIN>. { | 268 <FUNCTION_FILE_BEGIN>. { |
370 LEXER_DEBUG ("<FUNCTION_FILE_BEGIN>."); | 269 LEXER_DEBUG ("<FUNCTION_FILE_BEGIN>."); |
371 | 270 |
372 BEGIN (INITIAL); | 271 BEGIN (INITIAL); |
373 xunput (yytext[0], yytext); | 272 curr_lexer->xunput (yytext[0]); |
374 COUNT_TOK_AND_RETURN (FUNCTION_FILE); | 273 COUNT_TOK_AND_RETURN (FUNCTION_FILE); |
375 } | 274 } |
376 | 275 |
377 <CLASSDEF_FILE_BEGIN>. { | 276 <CLASSDEF_FILE_BEGIN>. { |
378 LEXER_DEBUG ("<CLASSDEF_FILE_BEGIN>."); | 277 LEXER_DEBUG ("<CLASSDEF_FILE_BEGIN>."); |
379 | 278 |
380 BEGIN (INITIAL); | 279 BEGIN (INITIAL); |
381 xunput (yytext[0], yytext); | 280 curr_lexer->xunput (yytext[0], yytext); |
382 COUNT_TOK_AND_RETURN (CLASSDEF_FILE); | 281 COUNT_TOK_AND_RETURN (CLASSDEF_FILE); |
383 } | 282 } |
384 | 283 |
385 %{ | 284 %{ |
386 // Help and other command-style functions. | 285 // Help and other command-style functions. |
388 | 287 |
389 <COMMAND_START>{NL} { | 288 <COMMAND_START>{NL} { |
390 LEXER_DEBUG ("<COMMAND_START>{NL}"); | 289 LEXER_DEBUG ("<COMMAND_START>{NL}"); |
391 | 290 |
392 BEGIN (INITIAL); | 291 BEGIN (INITIAL); |
393 input_line_number++; | 292 curr_lexer->input_line_number++; |
394 current_input_column = 1; | 293 curr_lexer->current_input_column = 1; |
395 | 294 |
396 lexer_flags.quote_is_transpose = false; | 295 curr_lexer->quote_is_transpose = false; |
397 lexer_flags.convert_spaces_to_comma = true; | 296 curr_lexer->convert_spaces_to_comma = true; |
398 lexer_flags.looking_for_object_index = false; | 297 curr_lexer->looking_for_object_index = false; |
399 lexer_flags.at_beginning_of_statement = true; | 298 curr_lexer->at_beginning_of_statement = true; |
400 | 299 |
401 COUNT_TOK_AND_RETURN ('\n'); | 300 COUNT_TOK_AND_RETURN ('\n'); |
402 } | 301 } |
403 | 302 |
404 <COMMAND_START>[\;\,] { | 303 <COMMAND_START>[\;\,] { |
405 LEXER_DEBUG ("<COMMAND_START>[\\;\\,]"); | 304 LEXER_DEBUG ("<COMMAND_START>[\\;\\,]"); |
406 | 305 |
407 lexer_flags.looking_for_object_index = false; | 306 curr_lexer->looking_for_object_index = false; |
408 lexer_flags.at_beginning_of_statement = true; | 307 curr_lexer->at_beginning_of_statement = true; |
409 | 308 |
410 BEGIN (INITIAL); | 309 BEGIN (INITIAL); |
411 | 310 |
412 if (strcmp (yytext, ",") == 0) | 311 if (strcmp (yytext, ",") == 0) |
413 TOK_RETURN (','); | 312 TOK_RETURN (','); |
416 } | 315 } |
417 | 316 |
418 <COMMAND_START>[\"\'] { | 317 <COMMAND_START>[\"\'] { |
419 LEXER_DEBUG ("<COMMAND_START>[\\\"\\']"); | 318 LEXER_DEBUG ("<COMMAND_START>[\\\"\\']"); |
420 | 319 |
421 lexer_flags.at_beginning_of_statement = false; | 320 curr_lexer->at_beginning_of_statement = false; |
422 | 321 |
423 current_input_column++; | 322 curr_lexer->current_input_column++; |
424 int tok = handle_string (yytext[0]); | 323 int tok = curr_lexer->handle_string (yytext[0]); |
425 | 324 |
426 COUNT_TOK_AND_RETURN (tok); | 325 COUNT_TOK_AND_RETURN (tok); |
427 } | 326 } |
428 | 327 |
429 <COMMAND_START>[^#% \t\r\n\;\,\"\'][^ \t\r\n\;\,]*{S}* { | 328 <COMMAND_START>[^#% \t\r\n\;\,\"\'][^ \t\r\n\;\,]*{S}* { |
430 LEXER_DEBUG ("<COMMAND_START>[^#% \\t\\r\\n\\;\\,\\\"\\'][^ \\t\\r\\n\\;\\,]*{S}*"); | 329 LEXER_DEBUG ("<COMMAND_START>[^#% \\t\\r\\n\\;\\,\\\"\\'][^ \\t\\r\\n\\;\\,]*{S}*"); |
431 | 330 |
432 std::string tok = strip_trailing_whitespace (yytext); | 331 std::string tok = strip_trailing_whitespace (yytext); |
433 | 332 |
434 lexer_flags.looking_for_object_index = false; | 333 curr_lexer->looking_for_object_index = false; |
435 lexer_flags.at_beginning_of_statement = false; | 334 curr_lexer->at_beginning_of_statement = false; |
436 | 335 |
437 TOK_PUSH_AND_RETURN (tok, SQ_STRING); | 336 TOK_PUSH_AND_RETURN (tok, SQ_STRING); |
438 } | 337 } |
439 | 338 |
440 %{ | 339 %{ |
452 %} | 351 %} |
453 | 352 |
454 <MATRIX_START>{SNLCMT}*\]{S}* { | 353 <MATRIX_START>{SNLCMT}*\]{S}* { |
455 LEXER_DEBUG ("<MATRIX_START>{SNLCMT}*\\]{S}*"); | 354 LEXER_DEBUG ("<MATRIX_START>{SNLCMT}*\\]{S}*"); |
456 | 355 |
457 scan_for_comments (yytext); | 356 curr_lexer->scan_for_comments (yytext); |
458 fixup_column_count (yytext); | 357 curr_lexer->fixup_column_count (yytext); |
459 | 358 |
460 lexer_flags.looking_at_object_index.pop_front (); | 359 curr_lexer->looking_at_object_index.pop_front (); |
461 | 360 |
462 lexer_flags.looking_for_object_index = true; | 361 curr_lexer->looking_for_object_index = true; |
463 lexer_flags.at_beginning_of_statement = false; | 362 curr_lexer->at_beginning_of_statement = false; |
464 | 363 |
465 int c = yytext[yyleng-1]; | 364 int c = yytext[yyleng-1]; |
466 int cont_is_spc = eat_continuation (); | 365 bool cont_is_spc = (curr_lexer->eat_continuation () != lexical_feedback::NO_WHITESPACE); |
467 bool spc_gobbled = (cont_is_spc || c == ' ' || c == '\t'); | 366 bool spc_gobbled = (cont_is_spc || c == ' ' || c == '\t'); |
468 int tok_to_return = handle_close_bracket (spc_gobbled, ']'); | 367 int tok_to_return = curr_lexer->handle_close_bracket (spc_gobbled, ']'); |
469 | 368 |
470 if (spc_gobbled) | 369 if (spc_gobbled) |
471 xunput (' ', yytext); | 370 curr_lexer->xunput (' '); |
472 | 371 |
473 COUNT_TOK_AND_RETURN (tok_to_return); | 372 COUNT_TOK_AND_RETURN (tok_to_return); |
474 } | 373 } |
475 | 374 |
476 %{ | 375 %{ |
478 %} | 377 %} |
479 | 378 |
480 <MATRIX_START>{SNLCMT}*\}{S}* { | 379 <MATRIX_START>{SNLCMT}*\}{S}* { |
481 LEXER_DEBUG ("<MATRIX_START>{SNLCMT}*\\}{S}*"); | 380 LEXER_DEBUG ("<MATRIX_START>{SNLCMT}*\\}{S}*"); |
482 | 381 |
483 scan_for_comments (yytext); | 382 curr_lexer->scan_for_comments (yytext); |
484 fixup_column_count (yytext); | 383 curr_lexer->fixup_column_count (yytext); |
485 | 384 |
486 lexer_flags.looking_at_object_index.pop_front (); | 385 curr_lexer->looking_at_object_index.pop_front (); |
487 | 386 |
488 lexer_flags.looking_for_object_index = true; | 387 curr_lexer->looking_for_object_index = true; |
489 lexer_flags.at_beginning_of_statement = false; | 388 curr_lexer->at_beginning_of_statement = false; |
490 | 389 |
491 int c = yytext[yyleng-1]; | 390 int c = yytext[yyleng-1]; |
492 int cont_is_spc = eat_continuation (); | 391 bool cont_is_spc = (curr_lexer->eat_continuation () != lexical_feedback::NO_WHITESPACE); |
493 bool spc_gobbled = (cont_is_spc || c == ' ' || c == '\t'); | 392 bool spc_gobbled = (cont_is_spc || c == ' ' || c == '\t'); |
494 int tok_to_return = handle_close_bracket (spc_gobbled, '}'); | 393 int tok_to_return = curr_lexer->handle_close_bracket (spc_gobbled, '}'); |
495 | 394 |
496 if (spc_gobbled) | 395 if (spc_gobbled) |
497 xunput (' ', yytext); | 396 curr_lexer->xunput (' '); |
498 | 397 |
499 COUNT_TOK_AND_RETURN (tok_to_return); | 398 COUNT_TOK_AND_RETURN (tok_to_return); |
500 } | 399 } |
501 | 400 |
502 %{ | 401 %{ |
506 %} | 405 %} |
507 | 406 |
508 <MATRIX_START>{S}*\,{S}* { | 407 <MATRIX_START>{S}*\,{S}* { |
509 LEXER_DEBUG ("<MATRIX_START>{S}*\\,{S}*"); | 408 LEXER_DEBUG ("<MATRIX_START>{S}*\\,{S}*"); |
510 | 409 |
511 current_input_column += yyleng; | 410 curr_lexer->current_input_column += yyleng; |
512 | 411 |
513 int tmp = eat_continuation (); | 412 int tmp = curr_lexer->eat_continuation (); |
514 | 413 |
515 lexer_flags.quote_is_transpose = false; | 414 curr_lexer->quote_is_transpose = false; |
516 lexer_flags.convert_spaces_to_comma = true; | 415 curr_lexer->convert_spaces_to_comma = true; |
517 lexer_flags.looking_for_object_index = false; | 416 curr_lexer->looking_for_object_index = false; |
518 lexer_flags.at_beginning_of_statement = false; | 417 curr_lexer->at_beginning_of_statement = false; |
519 | 418 |
520 if (! lexer_flags.looking_at_object_index.front ()) | 419 if (! curr_lexer->looking_at_object_index.front ()) |
521 { | 420 { |
522 if ((tmp & ATE_NEWLINE) == ATE_NEWLINE) | 421 if ((tmp & lexical_feedback::NEWLINE) == lexical_feedback::NEWLINE) |
523 { | 422 { |
524 maybe_warn_separator_insert (';'); | 423 curr_lexer->maybe_warn_separator_insert (';'); |
525 | 424 |
526 xunput (';', yytext); | 425 curr_lexer->xunput (';'); |
527 } | 426 } |
528 } | 427 } |
529 | 428 |
530 COUNT_TOK_AND_RETURN (','); | 429 COUNT_TOK_AND_RETURN (','); |
531 } | 430 } |
538 %} | 437 %} |
539 | 438 |
540 <MATRIX_START>{S}+ { | 439 <MATRIX_START>{S}+ { |
541 LEXER_DEBUG ("<MATRIX_START>{S}+"); | 440 LEXER_DEBUG ("<MATRIX_START>{S}+"); |
542 | 441 |
543 current_input_column += yyleng; | 442 curr_lexer->current_input_column += yyleng; |
544 | 443 |
545 lexer_flags.at_beginning_of_statement = false; | 444 curr_lexer->at_beginning_of_statement = false; |
546 | 445 |
547 int tmp = eat_continuation (); | 446 int tmp = curr_lexer->eat_continuation (); |
548 | 447 |
549 if (! lexer_flags.looking_at_object_index.front ()) | 448 if (! curr_lexer->looking_at_object_index.front ()) |
550 { | 449 { |
551 bool bin_op = next_token_is_bin_op (true); | 450 bool bin_op = curr_lexer->next_token_is_bin_op (true); |
552 bool postfix_un_op = next_token_is_postfix_unary_op (true); | 451 bool postfix_un_op = curr_lexer->next_token_is_postfix_unary_op (true); |
553 bool sep_op = next_token_is_sep_op (); | 452 bool sep_op = curr_lexer->next_token_is_sep_op (); |
554 | 453 |
555 if (! (postfix_un_op || bin_op || sep_op) | 454 if (! (postfix_un_op || bin_op || sep_op) |
556 && nesting_level.is_bracket_or_brace () | 455 && curr_lexer->nesting_level.is_bracket_or_brace () |
557 && lexer_flags.convert_spaces_to_comma) | 456 && curr_lexer->convert_spaces_to_comma) |
558 { | 457 { |
559 if ((tmp & ATE_NEWLINE) == ATE_NEWLINE) | 458 if ((tmp & lexical_feedback::NEWLINE) == lexical_feedback::NEWLINE) |
560 { | 459 { |
561 maybe_warn_separator_insert (';'); | 460 curr_lexer->maybe_warn_separator_insert (';'); |
562 | 461 |
563 xunput (';', yytext); | 462 curr_lexer->xunput (';'); |
564 } | 463 } |
565 | 464 |
566 lexer_flags.quote_is_transpose = false; | 465 curr_lexer->quote_is_transpose = false; |
567 lexer_flags.convert_spaces_to_comma = true; | 466 curr_lexer->convert_spaces_to_comma = true; |
568 lexer_flags.looking_for_object_index = false; | 467 curr_lexer->looking_for_object_index = false; |
569 | 468 |
570 maybe_warn_separator_insert (','); | 469 curr_lexer->maybe_warn_separator_insert (','); |
571 | 470 |
572 COUNT_TOK_AND_RETURN (','); | 471 COUNT_TOK_AND_RETURN (','); |
573 } | 472 } |
574 } | 473 } |
575 } | 474 } |
583 %} | 482 %} |
584 | 483 |
585 <MATRIX_START>{SNLCMT}*;{SNLCMT}* { | 484 <MATRIX_START>{SNLCMT}*;{SNLCMT}* { |
586 LEXER_DEBUG ("<MATRIX_START>{SNLCMT}*;{SNLCMT}*"); | 485 LEXER_DEBUG ("<MATRIX_START>{SNLCMT}*;{SNLCMT}*"); |
587 | 486 |
588 scan_for_comments (yytext); | 487 curr_lexer->scan_for_comments (yytext); |
589 fixup_column_count (yytext); | 488 curr_lexer->fixup_column_count (yytext); |
590 eat_whitespace (); | 489 curr_lexer->eat_whitespace (); |
591 | 490 |
592 lexer_flags.quote_is_transpose = false; | 491 curr_lexer->quote_is_transpose = false; |
593 lexer_flags.convert_spaces_to_comma = true; | 492 curr_lexer->convert_spaces_to_comma = true; |
594 lexer_flags.looking_for_object_index = false; | 493 curr_lexer->looking_for_object_index = false; |
595 lexer_flags.at_beginning_of_statement = false; | 494 curr_lexer->at_beginning_of_statement = false; |
596 | 495 |
597 COUNT_TOK_AND_RETURN (';'); | 496 COUNT_TOK_AND_RETURN (';'); |
598 } | 497 } |
599 | 498 |
600 %{ | 499 %{ |
607 | 506 |
608 <MATRIX_START>{S}*{COMMENT}{SNLCMT}* | | 507 <MATRIX_START>{S}*{COMMENT}{SNLCMT}* | |
609 <MATRIX_START>{S}*{NL}{SNLCMT}* { | 508 <MATRIX_START>{S}*{NL}{SNLCMT}* { |
610 LEXER_DEBUG ("<MATRIX_START>{S}*{COMMENT}{SNLCMT}*|<MATRIX_START>{S}*{NL}{SNLCMT}*"); | 509 LEXER_DEBUG ("<MATRIX_START>{S}*{COMMENT}{SNLCMT}*|<MATRIX_START>{S}*{NL}{SNLCMT}*"); |
611 | 510 |
612 scan_for_comments (yytext); | 511 curr_lexer->scan_for_comments (yytext); |
613 fixup_column_count (yytext); | 512 curr_lexer->fixup_column_count (yytext); |
614 eat_whitespace (); | 513 curr_lexer->eat_whitespace (); |
615 | 514 |
616 lexer_flags.quote_is_transpose = false; | 515 curr_lexer->quote_is_transpose = false; |
617 lexer_flags.convert_spaces_to_comma = true; | 516 curr_lexer->convert_spaces_to_comma = true; |
618 lexer_flags.at_beginning_of_statement = false; | 517 curr_lexer->at_beginning_of_statement = false; |
619 | 518 |
620 if (nesting_level.none ()) | 519 if (curr_lexer->nesting_level.none ()) |
621 return LEXICAL_ERROR; | 520 return LEXICAL_ERROR; |
622 | 521 |
623 if (! lexer_flags.looking_at_object_index.front () | 522 if (! curr_lexer->looking_at_object_index.front () |
624 && nesting_level.is_bracket_or_brace ()) | 523 && curr_lexer->nesting_level.is_bracket_or_brace ()) |
625 { | 524 { |
626 maybe_warn_separator_insert (';'); | 525 curr_lexer->maybe_warn_separator_insert (';'); |
627 | 526 |
628 COUNT_TOK_AND_RETURN (';'); | 527 COUNT_TOK_AND_RETURN (';'); |
629 } | 528 } |
630 } | 529 } |
631 | 530 |
632 \[{S}* { | 531 \[{S}* { |
633 LEXER_DEBUG ("\\[{S}*"); | 532 LEXER_DEBUG ("\\[{S}*"); |
634 | 533 |
635 nesting_level.bracket (); | 534 curr_lexer->nesting_level.bracket (); |
636 | 535 |
637 lexer_flags.looking_at_object_index.push_front (false); | 536 curr_lexer->looking_at_object_index.push_front (false); |
638 | 537 |
639 current_input_column += yyleng; | 538 curr_lexer->current_input_column += yyleng; |
640 lexer_flags.quote_is_transpose = false; | 539 curr_lexer->quote_is_transpose = false; |
641 lexer_flags.convert_spaces_to_comma = true; | 540 curr_lexer->convert_spaces_to_comma = true; |
642 lexer_flags.looking_for_object_index = false; | 541 curr_lexer->looking_for_object_index = false; |
643 lexer_flags.at_beginning_of_statement = false; | 542 curr_lexer->at_beginning_of_statement = false; |
644 | 543 |
645 if (lexer_flags.defining_func | 544 if (curr_lexer->defining_func |
646 && ! lexer_flags.parsed_function_name.top ()) | 545 && ! curr_lexer->parsed_function_name.top ()) |
647 lexer_flags.looking_at_return_list = true; | 546 curr_lexer->looking_at_return_list = true; |
648 else | 547 else |
649 lexer_flags.looking_at_matrix_or_assign_lhs = true; | 548 curr_lexer->looking_at_matrix_or_assign_lhs = true; |
650 | 549 |
651 promptflag--; | 550 promptflag--; |
652 eat_whitespace (); | 551 curr_lexer->eat_whitespace (); |
653 | 552 |
654 lexer_flags.bracketflag++; | 553 curr_lexer->bracketflag++; |
655 BEGIN (MATRIX_START); | 554 BEGIN (MATRIX_START); |
656 COUNT_TOK_AND_RETURN ('['); | 555 COUNT_TOK_AND_RETURN ('['); |
657 } | 556 } |
658 | 557 |
659 \] { | 558 \] { |
660 LEXER_DEBUG ("\\]"); | 559 LEXER_DEBUG ("\\]"); |
661 | 560 |
662 nesting_level.remove (); | 561 curr_lexer->nesting_level.remove (); |
663 | 562 |
664 lexer_flags.looking_at_object_index.pop_front (); | 563 curr_lexer->looking_at_object_index.pop_front (); |
665 | 564 |
666 lexer_flags.looking_for_object_index = true; | 565 curr_lexer->looking_for_object_index = true; |
667 lexer_flags.at_beginning_of_statement = false; | 566 curr_lexer->at_beginning_of_statement = false; |
668 | 567 |
669 TOK_RETURN (']'); | 568 TOK_RETURN (']'); |
670 } | 569 } |
671 | 570 |
672 %{ | 571 %{ |
674 %} | 573 %} |
675 | 574 |
676 {NUMBER}{Im} { | 575 {NUMBER}{Im} { |
677 LEXER_DEBUG ("{NUMBER}{Im}"); | 576 LEXER_DEBUG ("{NUMBER}{Im}"); |
678 | 577 |
679 handle_number (); | 578 curr_lexer->handle_number (); |
680 COUNT_TOK_AND_RETURN (IMAG_NUM); | 579 COUNT_TOK_AND_RETURN (IMAG_NUM); |
681 } | 580 } |
682 | 581 |
683 %{ | 582 %{ |
684 // Real numbers. Don't grab the '.' part of a dot operator as part of | 583 // Real numbers. Don't grab the '.' part of a dot operator as part of |
686 %} | 585 %} |
687 | 586 |
688 {D}+/\.[\*/\\^\'] | | 587 {D}+/\.[\*/\\^\'] | |
689 {NUMBER} { | 588 {NUMBER} { |
690 LEXER_DEBUG ("{D}+/\\.[\\*/\\^\\']|{NUMBER}"); | 589 LEXER_DEBUG ("{D}+/\\.[\\*/\\^\\']|{NUMBER}"); |
691 handle_number (); | 590 curr_lexer->handle_number (); |
692 COUNT_TOK_AND_RETURN (NUM); | 591 COUNT_TOK_AND_RETURN (NUM); |
693 } | 592 } |
694 | 593 |
695 %{ | 594 %{ |
696 // Eat whitespace. Whitespace inside matrix constants is handled by | 595 // Eat whitespace. Whitespace inside matrix constants is handled by |
697 // the <MATRIX_START> start state code above. | 596 // the <MATRIX_START> start state code above. |
698 %} | 597 %} |
699 | 598 |
700 {S}* { | 599 {S}* { |
701 current_input_column += yyleng; | 600 curr_lexer->current_input_column += yyleng; |
702 } | 601 } |
703 | 602 |
704 %{ | 603 %{ |
705 // Continuation lines. Allow comments after continuations. | 604 // Continuation lines. Allow comments after continuations. |
706 %} | 605 %} |
708 {CONT}{S}*{NL} | | 607 {CONT}{S}*{NL} | |
709 {CONT}{S}*{COMMENT} { | 608 {CONT}{S}*{COMMENT} { |
710 LEXER_DEBUG ("{CONT}{S}*{NL}|{CONT}{S}*{COMMENT}"); | 609 LEXER_DEBUG ("{CONT}{S}*{NL}|{CONT}{S}*{COMMENT}"); |
711 | 610 |
712 if (yytext[0] == '\\') | 611 if (yytext[0] == '\\') |
713 gripe_matlab_incompatible_continuation (); | 612 curr_lexer->gripe_matlab_incompatible_continuation (); |
714 scan_for_comments (yytext); | 613 curr_lexer->scan_for_comments (yytext); |
715 promptflag--; | 614 promptflag--; |
716 input_line_number++; | 615 curr_lexer->input_line_number++; |
717 current_input_column = 1; | 616 curr_lexer->current_input_column = 1; |
718 } | 617 } |
719 | 618 |
720 %{ | 619 %{ |
721 // End of file. | 620 // End of file. |
722 %} | 621 %} |
723 | 622 |
724 <<EOF>> { | 623 <<EOF>> { |
725 LEXER_DEBUG ("<<EOF>>"); | 624 LEXER_DEBUG ("<<EOF>>"); |
726 | 625 |
727 if (block_comment_nesting_level != 0) | 626 if (curr_lexer->block_comment_nesting_level != 0) |
728 { | 627 { |
729 warning ("block comment open at end of input"); | 628 warning ("block comment open at end of input"); |
730 | 629 |
731 if ((reading_fcn_file || reading_script_file || reading_classdef_file) | 630 if ((reading_fcn_file || reading_script_file || reading_classdef_file) |
732 && ! curr_fcn_file_name.empty ()) | 631 && ! curr_fcn_file_name.empty ()) |
733 warning ("near line %d of file '%s.m'", | 632 warning ("near line %d of file '%s.m'", |
734 input_line_number, curr_fcn_file_name.c_str ()); | 633 curr_lexer->input_line_number, curr_fcn_file_name.c_str ()); |
735 } | 634 } |
736 | 635 |
737 TOK_RETURN (END_OF_INPUT); | 636 TOK_RETURN (END_OF_INPUT); |
738 } | 637 } |
739 | 638 |
743 %} | 642 %} |
744 | 643 |
745 {IDENT}{S}* { | 644 {IDENT}{S}* { |
746 LEXER_DEBUG ("{IDENT}{S}*"); | 645 LEXER_DEBUG ("{IDENT}{S}*"); |
747 | 646 |
748 int id_tok = handle_identifier (); | 647 int id_tok = curr_lexer->handle_identifier (); |
749 | 648 |
750 if (id_tok >= 0) | 649 if (id_tok >= 0) |
751 COUNT_TOK_AND_RETURN (id_tok); | 650 COUNT_TOK_AND_RETURN (id_tok); |
752 } | 651 } |
753 | 652 |
757 | 656 |
758 {IDENT}@{IDENT}{S}* | | 657 {IDENT}@{IDENT}{S}* | |
759 {IDENT}@{IDENT}.{IDENT}{S}* { | 658 {IDENT}@{IDENT}.{IDENT}{S}* { |
760 LEXER_DEBUG ("{IDENT}@{IDENT}{S}*|{IDENT}@{IDENT}.{IDENT}{S}*"); | 659 LEXER_DEBUG ("{IDENT}@{IDENT}{S}*|{IDENT}@{IDENT}.{IDENT}{S}*"); |
761 | 660 |
762 int id_tok = handle_superclass_identifier (); | 661 int id_tok = curr_lexer->handle_superclass_identifier (); |
763 | 662 |
764 if (id_tok >= 0) | 663 if (id_tok >= 0) |
765 { | 664 { |
766 lexer_flags.looking_for_object_index = true; | 665 curr_lexer->looking_for_object_index = true; |
767 | 666 |
768 COUNT_TOK_AND_RETURN (id_tok); | 667 COUNT_TOK_AND_RETURN (id_tok); |
769 } | 668 } |
770 } | 669 } |
771 | 670 |
775 | 674 |
776 \?{IDENT}{S}* | | 675 \?{IDENT}{S}* | |
777 \?{IDENT}\.{IDENT}{S}* { | 676 \?{IDENT}\.{IDENT}{S}* { |
778 LEXER_DEBUG ("\\?{IDENT}{S}*|\\?{IDENT}\\.{IDENT}{S}*"); | 677 LEXER_DEBUG ("\\?{IDENT}{S}*|\\?{IDENT}\\.{IDENT}{S}*"); |
779 | 678 |
780 int id_tok = handle_meta_identifier (); | 679 int id_tok = curr_lexer->handle_meta_identifier (); |
781 | 680 |
782 if (id_tok >= 0) | 681 if (id_tok >= 0) |
783 { | 682 { |
784 lexer_flags.looking_for_object_index = true; | 683 curr_lexer->looking_for_object_index = true; |
785 | 684 |
786 COUNT_TOK_AND_RETURN (id_tok); | 685 COUNT_TOK_AND_RETURN (id_tok); |
787 } | 686 } |
788 } | 687 } |
789 | 688 |
792 %} | 691 %} |
793 | 692 |
794 "@" { | 693 "@" { |
795 LEXER_DEBUG ("@"); | 694 LEXER_DEBUG ("@"); |
796 | 695 |
797 current_input_column++; | 696 curr_lexer->current_input_column++; |
798 | 697 |
799 lexer_flags.quote_is_transpose = false; | 698 curr_lexer->quote_is_transpose = false; |
800 lexer_flags.convert_spaces_to_comma = false; | 699 curr_lexer->convert_spaces_to_comma = false; |
801 lexer_flags.looking_at_function_handle++; | 700 curr_lexer->looking_at_function_handle++; |
802 lexer_flags.looking_for_object_index = false; | 701 curr_lexer->looking_for_object_index = false; |
803 lexer_flags.at_beginning_of_statement = false; | 702 curr_lexer->at_beginning_of_statement = false; |
804 | 703 |
805 COUNT_TOK_AND_RETURN ('@'); | 704 COUNT_TOK_AND_RETURN ('@'); |
806 | 705 |
807 } | 706 } |
808 | 707 |
813 %} | 712 %} |
814 | 713 |
815 {NL} { | 714 {NL} { |
816 LEXER_DEBUG ("{NL}"); | 715 LEXER_DEBUG ("{NL}"); |
817 | 716 |
818 input_line_number++; | 717 curr_lexer->input_line_number++; |
819 current_input_column = 1; | 718 curr_lexer->current_input_column = 1; |
820 | 719 |
821 lexer_flags.quote_is_transpose = false; | 720 curr_lexer->quote_is_transpose = false; |
822 lexer_flags.convert_spaces_to_comma = true; | 721 curr_lexer->convert_spaces_to_comma = true; |
823 | 722 |
824 if (nesting_level.none ()) | 723 if (curr_lexer->nesting_level.none ()) |
825 { | 724 { |
826 lexer_flags.at_beginning_of_statement = true; | 725 curr_lexer->at_beginning_of_statement = true; |
827 COUNT_TOK_AND_RETURN ('\n'); | 726 COUNT_TOK_AND_RETURN ('\n'); |
828 } | 727 } |
829 else if (nesting_level.is_paren ()) | 728 else if (curr_lexer->nesting_level.is_paren ()) |
830 { | 729 { |
831 lexer_flags.at_beginning_of_statement = false; | 730 curr_lexer->at_beginning_of_statement = false; |
832 gripe_matlab_incompatible ("bare newline inside parentheses"); | 731 curr_lexer->gripe_matlab_incompatible ("bare newline inside parentheses"); |
833 } | 732 } |
834 else if (nesting_level.is_bracket_or_brace ()) | 733 else if (curr_lexer->nesting_level.is_bracket_or_brace ()) |
835 return LEXICAL_ERROR; | 734 return LEXICAL_ERROR; |
836 } | 735 } |
837 | 736 |
838 %{ | 737 %{ |
839 // Single quote can either be the beginning of a string or a transpose | 738 // Single quote can either be the beginning of a string or a transpose |
841 %} | 740 %} |
842 | 741 |
843 "'" { | 742 "'" { |
844 LEXER_DEBUG ("'"); | 743 LEXER_DEBUG ("'"); |
845 | 744 |
846 current_input_column++; | 745 curr_lexer->current_input_column++; |
847 lexer_flags.convert_spaces_to_comma = true; | 746 curr_lexer->convert_spaces_to_comma = true; |
848 | 747 |
849 if (lexer_flags.quote_is_transpose) | 748 if (curr_lexer->quote_is_transpose) |
850 { | 749 { |
851 do_comma_insert_check (); | 750 curr_lexer->do_comma_insert_check (); |
852 COUNT_TOK_AND_RETURN (QUOTE); | 751 COUNT_TOK_AND_RETURN (QUOTE); |
853 } | 752 } |
854 else | 753 else |
855 { | 754 { |
856 int tok = handle_string ('\''); | 755 int tok = curr_lexer->handle_string ('\''); |
857 COUNT_TOK_AND_RETURN (tok); | 756 COUNT_TOK_AND_RETURN (tok); |
858 } | 757 } |
859 } | 758 } |
860 | 759 |
861 %{ | 760 %{ |
863 %} | 762 %} |
864 | 763 |
865 \" { | 764 \" { |
866 LEXER_DEBUG ("\""); | 765 LEXER_DEBUG ("\""); |
867 | 766 |
868 current_input_column++; | 767 curr_lexer->current_input_column++; |
869 int tok = handle_string ('"'); | 768 int tok = curr_lexer->handle_string ('"'); |
870 | 769 |
871 COUNT_TOK_AND_RETURN (tok); | 770 COUNT_TOK_AND_RETURN (tok); |
872 } | 771 } |
873 | 772 |
874 %{ | 773 %{ |
876 %} | 775 %} |
877 | 776 |
878 {CCHAR} { | 777 {CCHAR} { |
879 LEXER_DEBUG ("{CCHAR}"); | 778 LEXER_DEBUG ("{CCHAR}"); |
880 | 779 |
881 lexer_flags.looking_for_object_index = false; | 780 curr_lexer->looking_for_object_index = false; |
882 | 781 |
883 xunput (yytext[0], yytext); | 782 curr_lexer->xunput (yytext[0]); |
884 | 783 |
885 bool eof = false; | 784 bool eof = false; |
886 int tok = process_comment (false, eof); | 785 int tok = curr_lexer->process_comment (false, eof); |
887 | 786 |
888 if (eof) | 787 if (eof) |
889 TOK_RETURN (END_OF_INPUT); | 788 TOK_RETURN (END_OF_INPUT); |
890 else if (tok > 0) | 789 else if (tok > 0) |
891 COUNT_TOK_AND_RETURN (tok); | 790 COUNT_TOK_AND_RETURN (tok); |
896 %} | 795 %} |
897 | 796 |
898 ^{S}*{CCHAR}\{{S}*{NL} { | 797 ^{S}*{CCHAR}\{{S}*{NL} { |
899 LEXER_DEBUG ("^{S}*{CCHAR}\\{{S}*{NL}"); | 798 LEXER_DEBUG ("^{S}*{CCHAR}\\{{S}*{NL}"); |
900 | 799 |
901 lexer_flags.looking_for_object_index = false; | 800 curr_lexer->looking_for_object_index = false; |
902 | 801 |
903 input_line_number++; | 802 curr_lexer->input_line_number++; |
904 current_input_column = 1; | 803 curr_lexer->current_input_column = 1; |
905 block_comment_nesting_level++; | 804 curr_lexer->block_comment_nesting_level++; |
906 promptflag--; | 805 promptflag--; |
907 | 806 |
908 bool eof = false; | 807 bool eof = false; |
909 process_comment (true, eof); | 808 curr_lexer->process_comment (true, eof); |
910 } | 809 } |
911 | 810 |
912 %{ | 811 %{ |
913 // Other operators. | 812 // Other operators. |
914 %} | 813 %} |
920 ".*" { LEXER_DEBUG (".*"); BIN_OP_RETURN (EMUL, false, false); } | 819 ".*" { LEXER_DEBUG (".*"); BIN_OP_RETURN (EMUL, false, false); } |
921 "./" { LEXER_DEBUG ("./"); BIN_OP_RETURN (EDIV, false, false); } | 820 "./" { LEXER_DEBUG ("./"); BIN_OP_RETURN (EDIV, false, false); } |
922 ".\\" { LEXER_DEBUG (".\\"); BIN_OP_RETURN (ELEFTDIV, false, false); } | 821 ".\\" { LEXER_DEBUG (".\\"); BIN_OP_RETURN (ELEFTDIV, false, false); } |
923 ".^" { LEXER_DEBUG (".^"); BIN_OP_RETURN (EPOW, false, false); } | 822 ".^" { LEXER_DEBUG (".^"); BIN_OP_RETURN (EPOW, false, false); } |
924 ".**" { LEXER_DEBUG (".**"); XBIN_OP_RETURN (EPOW, false, false); } | 823 ".**" { LEXER_DEBUG (".**"); XBIN_OP_RETURN (EPOW, false, false); } |
925 ".'" { LEXER_DEBUG (".'"); do_comma_insert_check (); BIN_OP_RETURN (TRANSPOSE, true, false); } | 824 ".'" { LEXER_DEBUG (".'"); curr_lexer->do_comma_insert_check (); BIN_OP_RETURN (TRANSPOSE, true, false); } |
926 "++" { LEXER_DEBUG ("++"); do_comma_insert_check (); XBIN_OP_RETURN_INTERNAL (PLUS_PLUS, true, false, true); } | 825 "++" { LEXER_DEBUG ("++"); curr_lexer->do_comma_insert_check (); XBIN_OP_RETURN_INTERNAL (PLUS_PLUS, true, false, true); } |
927 "--" { LEXER_DEBUG ("--"); do_comma_insert_check (); XBIN_OP_RETURN_INTERNAL (MINUS_MINUS, true, false, true); } | 826 "--" { LEXER_DEBUG ("--"); curr_lexer->do_comma_insert_check (); XBIN_OP_RETURN_INTERNAL (MINUS_MINUS, true, false, true); } |
928 "<=" { LEXER_DEBUG ("<="); BIN_OP_RETURN (EXPR_LE, false, false); } | 827 "<=" { LEXER_DEBUG ("<="); BIN_OP_RETURN (EXPR_LE, false, false); } |
929 "==" { LEXER_DEBUG ("=="); BIN_OP_RETURN (EXPR_EQ, false, false); } | 828 "==" { LEXER_DEBUG ("=="); BIN_OP_RETURN (EXPR_EQ, false, false); } |
930 "~=" { LEXER_DEBUG ("~="); BIN_OP_RETURN (EXPR_NE, false, false); } | 829 "~=" { LEXER_DEBUG ("~="); BIN_OP_RETURN (EXPR_NE, false, false); } |
931 "!=" { LEXER_DEBUG ("!="); XBIN_OP_RETURN (EXPR_NE, false, false); } | 830 "!=" { LEXER_DEBUG ("!="); XBIN_OP_RETURN (EXPR_NE, false, false); } |
932 ">=" { LEXER_DEBUG (">="); BIN_OP_RETURN (EXPR_GE, false, false); } | 831 ">=" { LEXER_DEBUG (">="); BIN_OP_RETURN (EXPR_GE, false, false); } |
938 "-" { LEXER_DEBUG ("-"); BIN_OP_RETURN ('-', false, false); } | 837 "-" { LEXER_DEBUG ("-"); BIN_OP_RETURN ('-', false, false); } |
939 "*" { LEXER_DEBUG ("*"); BIN_OP_RETURN ('*', false, false); } | 838 "*" { LEXER_DEBUG ("*"); BIN_OP_RETURN ('*', false, false); } |
940 "/" { LEXER_DEBUG ("/"); BIN_OP_RETURN ('/', false, false); } | 839 "/" { LEXER_DEBUG ("/"); BIN_OP_RETURN ('/', false, false); } |
941 "\\" { LEXER_DEBUG ("\\"); BIN_OP_RETURN (LEFTDIV, false, false); } | 840 "\\" { LEXER_DEBUG ("\\"); BIN_OP_RETURN (LEFTDIV, false, false); } |
942 ";" { LEXER_DEBUG (";"); BIN_OP_RETURN (';', true, true); } | 841 ";" { LEXER_DEBUG (";"); BIN_OP_RETURN (';', true, true); } |
943 "," { LEXER_DEBUG (","); BIN_OP_RETURN (',', true, ! lexer_flags.looking_at_object_index.front ()); } | 842 "," { LEXER_DEBUG (","); BIN_OP_RETURN (',', true, ! curr_lexer->looking_at_object_index.front ()); } |
944 "^" { LEXER_DEBUG ("^"); BIN_OP_RETURN (POW, false, false); } | 843 "^" { LEXER_DEBUG ("^"); BIN_OP_RETURN (POW, false, false); } |
945 "**" { LEXER_DEBUG ("**"); XBIN_OP_RETURN (POW, false, false); } | 844 "**" { LEXER_DEBUG ("**"); XBIN_OP_RETURN (POW, false, false); } |
946 "=" { LEXER_DEBUG ("="); BIN_OP_RETURN ('=', true, false); } | 845 "=" { LEXER_DEBUG ("="); BIN_OP_RETURN ('=', true, false); } |
947 "&&" { LEXER_DEBUG ("&&"); BIN_OP_RETURN (EXPR_AND_AND, false, false); } | 846 "&&" { LEXER_DEBUG ("&&"); BIN_OP_RETURN (EXPR_AND_AND, false, false); } |
948 "||" { LEXER_DEBUG ("||"); BIN_OP_RETURN (EXPR_OR_OR, false, false); } | 847 "||" { LEXER_DEBUG ("||"); BIN_OP_RETURN (EXPR_OR_OR, false, false); } |
964 // If we are looking for an object index, then push TRUE for | 863 // If we are looking for an object index, then push TRUE for |
965 // looking_at_object_index. Otherwise, just push whatever state | 864 // looking_at_object_index. Otherwise, just push whatever state |
966 // is current (so that we can pop it off the stack when we find | 865 // is current (so that we can pop it off the stack when we find |
967 // the matching close paren). | 866 // the matching close paren). |
968 | 867 |
969 lexer_flags.looking_at_object_index.push_front | 868 curr_lexer->looking_at_object_index.push_front |
970 (lexer_flags.looking_for_object_index); | 869 (curr_lexer->looking_for_object_index); |
971 | 870 |
972 lexer_flags.looking_at_indirect_ref = false; | 871 curr_lexer->looking_at_indirect_ref = false; |
973 lexer_flags.looking_for_object_index = false; | 872 curr_lexer->looking_for_object_index = false; |
974 lexer_flags.at_beginning_of_statement = false; | 873 curr_lexer->at_beginning_of_statement = false; |
975 | 874 |
976 nesting_level.paren (); | 875 curr_lexer->nesting_level.paren (); |
977 promptflag--; | 876 promptflag--; |
978 | 877 |
979 TOK_RETURN ('('); | 878 TOK_RETURN ('('); |
980 } | 879 } |
981 | 880 |
982 ")" { | 881 ")" { |
983 LEXER_DEBUG (")"); | 882 LEXER_DEBUG (")"); |
984 | 883 |
985 nesting_level.remove (); | 884 curr_lexer->nesting_level.remove (); |
986 current_input_column++; | 885 curr_lexer->current_input_column++; |
987 | 886 |
988 lexer_flags.looking_at_object_index.pop_front (); | 887 curr_lexer->looking_at_object_index.pop_front (); |
989 | 888 |
990 lexer_flags.quote_is_transpose = true; | 889 curr_lexer->quote_is_transpose = true; |
991 lexer_flags.convert_spaces_to_comma | 890 curr_lexer->convert_spaces_to_comma |
992 = (nesting_level.is_bracket_or_brace () | 891 = (curr_lexer->nesting_level.is_bracket_or_brace () |
993 && ! lexer_flags.looking_at_anon_fcn_args); | 892 && ! curr_lexer->looking_at_anon_fcn_args); |
994 lexer_flags.looking_for_object_index = true; | 893 curr_lexer->looking_for_object_index = true; |
995 lexer_flags.at_beginning_of_statement = false; | 894 curr_lexer->at_beginning_of_statement = false; |
996 | 895 |
997 if (lexer_flags.looking_at_anon_fcn_args) | 896 if (curr_lexer->looking_at_anon_fcn_args) |
998 lexer_flags.looking_at_anon_fcn_args = false; | 897 curr_lexer->looking_at_anon_fcn_args = false; |
999 | 898 |
1000 do_comma_insert_check (); | 899 curr_lexer->do_comma_insert_check (); |
1001 | 900 |
1002 COUNT_TOK_AND_RETURN (')'); | 901 COUNT_TOK_AND_RETURN (')'); |
1003 } | 902 } |
1004 | 903 |
1005 "." { | 904 "." { |
1006 LEXER_DEBUG ("."); | 905 LEXER_DEBUG ("."); |
1007 | 906 |
1008 lexer_flags.looking_for_object_index = false; | 907 curr_lexer->looking_for_object_index = false; |
1009 lexer_flags.at_beginning_of_statement = false; | 908 curr_lexer->at_beginning_of_statement = false; |
1010 | 909 |
1011 TOK_RETURN ('.'); | 910 TOK_RETURN ('.'); |
1012 } | 911 } |
1013 | 912 |
1014 "+=" { LEXER_DEBUG ("+="); XBIN_OP_RETURN (ADD_EQ, false, false); } | 913 "+=" { LEXER_DEBUG ("+="); XBIN_OP_RETURN (ADD_EQ, false, false); } |
1029 ">>=" { LEXER_DEBUG (">>="); XBIN_OP_RETURN (RSHIFT_EQ, false, false); } | 928 ">>=" { LEXER_DEBUG (">>="); XBIN_OP_RETURN (RSHIFT_EQ, false, false); } |
1030 | 929 |
1031 \{{S}* { | 930 \{{S}* { |
1032 LEXER_DEBUG ("\\{{S}*"); | 931 LEXER_DEBUG ("\\{{S}*"); |
1033 | 932 |
1034 nesting_level.brace (); | 933 curr_lexer->nesting_level.brace (); |
1035 | 934 |
1036 lexer_flags.looking_at_object_index.push_front | 935 curr_lexer->looking_at_object_index.push_front |
1037 (lexer_flags.looking_for_object_index); | 936 (curr_lexer->looking_for_object_index); |
1038 | 937 |
1039 current_input_column += yyleng; | 938 curr_lexer->current_input_column += yyleng; |
1040 lexer_flags.quote_is_transpose = false; | 939 curr_lexer->quote_is_transpose = false; |
1041 lexer_flags.convert_spaces_to_comma = true; | 940 curr_lexer->convert_spaces_to_comma = true; |
1042 lexer_flags.looking_for_object_index = false; | 941 curr_lexer->looking_for_object_index = false; |
1043 lexer_flags.at_beginning_of_statement = false; | 942 curr_lexer->at_beginning_of_statement = false; |
1044 | 943 |
1045 promptflag--; | 944 promptflag--; |
1046 eat_whitespace (); | 945 curr_lexer->eat_whitespace (); |
1047 | 946 |
1048 lexer_flags.braceflag++; | 947 curr_lexer->braceflag++; |
1049 BEGIN (MATRIX_START); | 948 BEGIN (MATRIX_START); |
1050 COUNT_TOK_AND_RETURN ('{'); | 949 COUNT_TOK_AND_RETURN ('{'); |
1051 } | 950 } |
1052 | 951 |
1053 "}" { | 952 "}" { |
1054 LEXER_DEBUG ("}"); | 953 LEXER_DEBUG ("}"); |
1055 | 954 |
1056 lexer_flags.looking_at_object_index.pop_front (); | 955 curr_lexer->looking_at_object_index.pop_front (); |
1057 | 956 |
1058 lexer_flags.looking_for_object_index = true; | 957 curr_lexer->looking_for_object_index = true; |
1059 lexer_flags.at_beginning_of_statement = false; | 958 curr_lexer->at_beginning_of_statement = false; |
1060 | 959 |
1061 nesting_level.remove (); | 960 curr_lexer->nesting_level.remove (); |
1062 | 961 |
1063 TOK_RETURN ('}'); | 962 TOK_RETURN ('}'); |
1064 } | 963 } |
1065 | 964 |
1066 %{ | 965 %{ |
1068 %} | 967 %} |
1069 | 968 |
1070 . { | 969 . { |
1071 LEXER_DEBUG ("."); | 970 LEXER_DEBUG ("."); |
1072 | 971 |
1073 xunput (yytext[0], yytext); | 972 curr_lexer->xunput (yytext[0]); |
1074 | 973 |
1075 int c = text_yyinput (); | 974 int c = curr_lexer->text_yyinput (); |
1076 | 975 |
1077 if (c != EOF) | 976 if (c != EOF) |
1078 { | 977 { |
1079 current_input_column++; | 978 curr_lexer->current_input_column++; |
1080 | 979 |
1081 error ("invalid character '%s' (ASCII %d) near line %d, column %d", | 980 error ("invalid character '%s' (ASCII %d) near line %d, column %d", |
1082 undo_string_escape (static_cast<char> (c)), c, | 981 undo_string_escape (static_cast<char> (c)), c, |
1083 input_line_number, current_input_column); | 982 curr_lexer->input_line_number, curr_lexer->current_input_column); |
1084 | 983 |
1085 return LEXICAL_ERROR; | 984 return LEXICAL_ERROR; |
1086 } | 985 } |
1087 else | 986 else |
1088 TOK_RETURN (END_OF_INPUT); | 987 TOK_RETURN (END_OF_INPUT); |
1089 } | 988 } |
1090 | 989 |
1091 %% | 990 %% |
1092 | |
1093 // GAG. | |
1094 // | |
1095 // If we're reading a matrix and the next character is '[', make sure | |
1096 // that we insert a comma ahead of it. | |
1097 | |
1098 void | |
1099 do_comma_insert_check (void) | |
1100 { | |
1101 int spc_gobbled = eat_continuation (); | |
1102 | |
1103 int c = text_yyinput (); | |
1104 | |
1105 xunput (c, yytext); | |
1106 | |
1107 if (spc_gobbled) | |
1108 xunput (' ', yytext); | |
1109 | |
1110 lexer_flags.do_comma_insert = (! lexer_flags.looking_at_object_index.front () | |
1111 && lexer_flags.bracketflag && c == '['); | |
1112 } | |
1113 | |
1114 // Fix things up for errors or interrupts. The parser is never called | |
1115 // recursively, so it is always safe to reinitialize its state before | |
1116 // doing any parsing. | |
1117 | |
1118 void | |
1119 reset_parser (void) | |
1120 { | |
1121 // Start off on the right foot. | |
1122 BEGIN (INITIAL); | |
1123 | |
1124 parser_end_of_input = false; | |
1125 | |
1126 parser_symtab_context.clear (); | |
1127 | |
1128 // We do want a prompt by default. | |
1129 promptflag = 1; | |
1130 | |
1131 // We are not in a block comment. | |
1132 block_comment_nesting_level = 0; | |
1133 | |
1134 // Error may have occurred inside some brackets, braces, or parentheses. | |
1135 nesting_level.clear (); | |
1136 | |
1137 // Clear out the stack of token info used to track line and column | |
1138 // numbers. | |
1139 while (! token_stack.empty ()) | |
1140 { | |
1141 delete token_stack.top (); | |
1142 token_stack.pop (); | |
1143 } | |
1144 | |
1145 // Can be reset by defining a function. | |
1146 if (! (reading_script_file || reading_fcn_file || reading_classdef_file)) | |
1147 { | |
1148 current_input_column = 1; | |
1149 input_line_number = command_editor::current_command_number (); | |
1150 } | |
1151 | |
1152 // Only ask for input from stdin if we are expecting interactive | |
1153 // input. | |
1154 | |
1155 if (! quitting_gracefully | |
1156 && (interactive || forced_interactive) | |
1157 && ! (reading_fcn_file | |
1158 || reading_classdef_file | |
1159 || reading_script_file | |
1160 || get_input_from_eval_string | |
1161 || input_from_startup_file)) | |
1162 yyrestart (stdin); | |
1163 | |
1164 // Clear the buffer for help text. | |
1165 while (! help_buf.empty ()) | |
1166 help_buf.pop (); | |
1167 | |
1168 // Reset other flags. | |
1169 lexer_flags.init (); | |
1170 } | |
1171 | 991 |
1172 static void | 992 static void |
1173 display_character (char c) | 993 display_character (char c) |
1174 { | 994 { |
1175 if (isgraph (c)) | 995 if (isgraph (c)) |
1313 std::cerr << "DEL"; | 1133 std::cerr << "DEL"; |
1314 break; | 1134 break; |
1315 } | 1135 } |
1316 } | 1136 } |
1317 | 1137 |
1318 static int | 1138 void |
1319 text_yyinput (void) | 1139 cleanup_parser (void) |
1320 { | 1140 { |
1321 int c = yyinput (); | 1141 } |
1142 | |
1143 // Return 1 if the given character matches any character in the given | |
1144 // string. | |
1145 | |
1146 static bool | |
1147 match_any (char c, const char *s) | |
1148 { | |
1149 char tmp; | |
1150 while ((tmp = *s++) != '\0') | |
1151 { | |
1152 if (c == tmp) | |
1153 return true; | |
1154 } | |
1155 return false; | |
1156 } | |
1157 | |
1158 // Given information about the spacing surrounding an operator, | |
1159 // return 1 if it looks like it should be treated as a binary | |
1160 // operator. For example, | |
1161 // | |
1162 // [ 1 + 2 ] or [ 1+ 2] or [ 1+2 ] ==> binary | |
1163 // | |
1164 // [ 1 +2 ] ==> unary | |
1165 | |
1166 static bool | |
1167 looks_like_bin_op (bool spc_prev, int next_char) | |
1168 { | |
1169 bool spc_next = (next_char == ' ' || next_char == '\t'); | |
1170 | |
1171 return ((spc_prev && spc_next) || ! spc_prev); | |
1172 } | |
1173 | |
1174 bool | |
1175 is_keyword (const std::string& s) | |
1176 { | |
1177 // Parsing function names like "set.property_name" inside | |
1178 // classdef-style class definitions is simplified by handling the | |
1179 // "set" and "get" portions of the names using the same mechanism as | |
1180 // is used for keywords. However, they are not really keywords in | |
1181 // the language, so omit them from the list of possible keywords. | |
1182 | |
1183 return (octave_kw_hash::in_word_set (s.c_str (), s.length ()) != 0 | |
1184 && ! (s == "set" || s == "get")); | |
1185 } | |
1186 | |
1187 DEFUN (iskeyword, args, , | |
1188 "-*- texinfo -*-\n\ | |
1189 @deftypefn {Built-in Function} {} iskeyword ()\n\ | |
1190 @deftypefnx {Built-in Function} {} iskeyword (@var{name})\n\ | |
1191 Return true if @var{name} is an Octave keyword. If @var{name}\n\ | |
1192 is omitted, return a list of keywords.\n\ | |
1193 @seealso{isvarname, exist}\n\ | |
1194 @end deftypefn") | |
1195 { | |
1196 octave_value retval; | |
1197 | |
1198 int argc = args.length () + 1; | |
1199 | |
1200 string_vector argv = args.make_argv ("iskeyword"); | |
1201 | |
1202 if (error_state) | |
1203 return retval; | |
1204 | |
1205 if (argc == 1) | |
1206 { | |
1207 // Neither set and get are keywords. See the note in the | |
1208 // is_keyword function for additional details. | |
1209 | |
1210 string_vector lst (TOTAL_KEYWORDS); | |
1211 | |
1212 int j = 0; | |
1213 | |
1214 for (int i = 0; i < TOTAL_KEYWORDS; i++) | |
1215 { | |
1216 std::string tmp = wordlist[i].name; | |
1217 | |
1218 if (! (tmp == "set" || tmp == "get")) | |
1219 lst[j++] = tmp; | |
1220 } | |
1221 | |
1222 lst.resize (j); | |
1223 | |
1224 retval = Cell (lst.sort ()); | |
1225 } | |
1226 else if (argc == 2) | |
1227 { | |
1228 retval = is_keyword (argv[1]); | |
1229 } | |
1230 else | |
1231 print_usage (); | |
1232 | |
1233 return retval; | |
1234 } | |
1235 | |
1236 /* | |
1237 | |
1238 %!assert (iskeyword ("for")) | |
1239 %!assert (iskeyword ("fort"), false) | |
1240 %!assert (iskeyword ("fft"), false) | |
1241 | |
1242 */ | |
1243 | |
1244 // Used to delete trailing white space from tokens. | |
1245 | |
1246 static std::string | |
1247 strip_trailing_whitespace (char *s) | |
1248 { | |
1249 std::string retval = s; | |
1250 | |
1251 size_t pos = retval.find_first_of (" \t"); | |
1252 | |
1253 if (pos != std::string::npos) | |
1254 retval.resize (pos); | |
1255 | |
1256 return retval; | |
1257 } | |
1258 | |
1259 DEFUN (__display_tokens__, args, nargout, | |
1260 "-*- texinfo -*-\n\ | |
1261 @deftypefn {Built-in Function} {} __display_tokens__ ()\n\ | |
1262 Query or set the internal variable that determines whether Octave's\n\ | |
1263 lexer displays tokens as they are read.\n\ | |
1264 @end deftypefn") | |
1265 { | |
1266 return SET_INTERNAL_VARIABLE (display_tokens); | |
1267 } | |
1268 | |
1269 DEFUN (__token_count__, , , | |
1270 "-*- texinfo -*-\n\ | |
1271 @deftypefn {Built-in Function} {} __token_count__ ()\n\ | |
1272 Number of language tokens processed since Octave startup.\n\ | |
1273 @end deftypefn") | |
1274 { | |
1275 return octave_value (Vtoken_count); | |
1276 } | |
1277 | |
1278 DEFUN (__lexer_debug_flag__, args, nargout, | |
1279 "-*- texinfo -*-\n\ | |
1280 @deftypefn {Built-in Function} {@var{old_val} =} __lexer_debug_flag__ (@var{new_val}))\n\ | |
1281 Undocumented internal function.\n\ | |
1282 @end deftypefn") | |
1283 { | |
1284 octave_value retval; | |
1285 | |
1286 retval = set_internal_variable (lexer_debug_flag, args, nargout, | |
1287 "__lexer_debug_flag__"); | |
1288 | |
1289 return retval; | |
1290 } | |
1291 | |
1292 class | |
1293 flex_stream_reader : public stream_reader | |
1294 { | |
1295 public: | |
1296 flex_stream_reader (lexical_feedback *l, char *buf_arg) | |
1297 : stream_reader (), lexer (l), buf (buf_arg) | |
1298 { } | |
1299 | |
1300 int getc (void) { return lexer->text_yyinput (); } | |
1301 int ungetc (int c) { lexer->xunput (c, buf); return 0; } | |
1302 | |
1303 private: | |
1304 | |
1305 // No copying! | |
1306 | |
1307 flex_stream_reader (const flex_stream_reader&); | |
1308 | |
1309 flex_stream_reader& operator = (const flex_stream_reader&); | |
1310 | |
1311 lexical_feedback *lexer; | |
1312 | |
1313 char *buf; | |
1314 }; | |
1315 | |
1316 lexical_feedback::~lexical_feedback (void) | |
1317 { | |
1318 // Clear out the stack of token info used to track line and | |
1319 // column numbers. | |
1320 | |
1321 while (! token_stack.empty ()) | |
1322 { | |
1323 delete token_stack.top (); | |
1324 token_stack.pop (); | |
1325 } | |
1326 | |
1327 yylex_destroy (scanner); | |
1328 } | |
1329 | |
1330 void | |
1331 lexical_feedback::init (void) | |
1332 { | |
1333 // The closest paren, brace, or bracket nesting is not an object | |
1334 // index. | |
1335 looking_at_object_index.push_front (false); | |
1336 | |
1337 yylex_init (&scanner); | |
1338 | |
1339 // Make lexical_feedback object available through yyextra in | |
1340 // flex-generated lexer. | |
1341 yyset_extra (this, scanner); | |
1342 } | |
1343 | |
1344 // Inside Flex-generated functions, yyg is the scanner cast to its real | |
1345 // type. The BEGIN macro uses yyg and we want to use that in | |
1346 // lexical_feedback member functions. If we could set the start state | |
1347 // by calling a function instead of using the BEGIN macro, we could | |
1348 // eliminate the OCTAVE_YYG macro. | |
1349 | |
1350 #define OCTAVE_YYG \ | |
1351 struct yyguts_t *yyg = static_cast<struct yyguts_t*> (scanner) | |
1352 | |
1353 void | |
1354 lexical_feedback::reset (void) | |
1355 { | |
1356 OCTAVE_YYG; | |
1357 | |
1358 // Start off on the right foot. | |
1359 BEGIN (INITIAL); | |
1360 | |
1361 parser_symtab_context.clear (); | |
1362 | |
1363 // We do want a prompt by default. | |
1364 promptflag = 1; | |
1365 | |
1366 // Only ask for input from stdin if we are expecting interactive | |
1367 // input. | |
1368 | |
1369 if (! quitting_gracefully | |
1370 && (interactive || forced_interactive) | |
1371 && ! (reading_fcn_file | |
1372 || reading_classdef_file | |
1373 || reading_script_file | |
1374 || get_input_from_eval_string | |
1375 || input_from_startup_file)) | |
1376 yyrestart (stdin, scanner); | |
1377 | |
1378 // Clear the buffer for help text. | |
1379 while (! help_buf.empty ()) | |
1380 help_buf.pop (); | |
1381 } | |
1382 | |
1383 void | |
1384 lexical_feedback::prep_for_script_file (void) | |
1385 { | |
1386 OCTAVE_YYG; | |
1387 | |
1388 BEGIN (SCRIPT_FILE_BEGIN); | |
1389 } | |
1390 | |
1391 void | |
1392 lexical_feedback::prep_for_function_file (void) | |
1393 { | |
1394 OCTAVE_YYG; | |
1395 | |
1396 BEGIN (FUNCTION_FILE_BEGIN); | |
1397 } | |
1398 | |
1399 void | |
1400 lexical_feedback::prep_for_classdef_file (void) | |
1401 { | |
1402 OCTAVE_YYG; | |
1403 | |
1404 BEGIN (CLASSDEF_FILE_BEGIN); | |
1405 } | |
1406 | |
1407 int | |
1408 lexical_feedback::octave_read (char *buf, unsigned max_size) | |
1409 { | |
1410 static const char * const eol = "\n"; | |
1411 static std::string input_buf; | |
1412 static const char *pos = 0; | |
1413 static size_t chars_left = 0; | |
1414 static bool eof = false; | |
1415 | |
1416 int status = 0; | |
1417 | |
1418 if (chars_left == 0) | |
1419 { | |
1420 pos = 0; | |
1421 | |
1422 input_buf = get_user_input (eof); | |
1423 | |
1424 chars_left = input_buf.length (); | |
1425 | |
1426 pos = input_buf.c_str (); | |
1427 } | |
1428 | |
1429 if (chars_left > 0) | |
1430 { | |
1431 size_t len = max_size > chars_left ? chars_left : max_size; | |
1432 assert (len > 0); | |
1433 | |
1434 memcpy (buf, pos, len); | |
1435 | |
1436 chars_left -= len; | |
1437 pos += len; | |
1438 | |
1439 // Make sure input ends with a new line character. | |
1440 if (chars_left == 0 && buf[len-1] != '\n') | |
1441 { | |
1442 if (len < max_size) | |
1443 { | |
1444 // There is enough room to plug the newline character in | |
1445 // the buffer. | |
1446 buf[len++] = '\n'; | |
1447 } | |
1448 else | |
1449 { | |
1450 // There isn't enough room to plug the newline character | |
1451 // in the buffer so make sure it is returned on the next | |
1452 // octave_read call. | |
1453 pos = eol; | |
1454 chars_left = 1; | |
1455 } | |
1456 } | |
1457 | |
1458 status = len; | |
1459 } | |
1460 else | |
1461 { | |
1462 status = YY_NULL; | |
1463 | |
1464 if (! eof) | |
1465 fatal_error ("octave_read () in flex scanner failed"); | |
1466 } | |
1467 | |
1468 return status; | |
1469 } | |
1470 | |
1471 char * | |
1472 lexical_feedback::flex_yytext (void) | |
1473 { | |
1474 return yyget_text (scanner); | |
1475 } | |
1476 | |
1477 int | |
1478 lexical_feedback::flex_yyleng (void) | |
1479 { | |
1480 return yyget_leng (scanner); | |
1481 } | |
1482 | |
1483 // GAG. | |
1484 // | |
1485 // If we're reading a matrix and the next character is '[', make sure | |
1486 // that we insert a comma ahead of it. | |
1487 | |
1488 void | |
1489 lexical_feedback::do_comma_insert_check (void) | |
1490 { | |
1491 bool spc_gobbled = (eat_continuation () != lexical_feedback::NO_WHITESPACE); | |
1492 | |
1493 int c = text_yyinput (); | |
1494 | |
1495 xunput (c); | |
1496 | |
1497 if (spc_gobbled) | |
1498 xunput (' '); | |
1499 | |
1500 do_comma_insert = (! looking_at_object_index.front () | |
1501 && bracketflag && c == '['); | |
1502 } | |
1503 | |
1504 int | |
1505 lexical_feedback::text_yyinput (void) | |
1506 { | |
1507 int c = yyinput (scanner); | |
1322 | 1508 |
1323 if (lexer_debug_flag) | 1509 if (lexer_debug_flag) |
1324 { | 1510 { |
1325 std::cerr << "I: "; | 1511 std::cerr << "I: "; |
1326 display_character (c); | 1512 display_character (c); |
1329 | 1515 |
1330 // Convert CRLF into just LF and single CR into LF. | 1516 // Convert CRLF into just LF and single CR into LF. |
1331 | 1517 |
1332 if (c == '\r') | 1518 if (c == '\r') |
1333 { | 1519 { |
1334 c = yyinput (); | 1520 c = yyinput (scanner); |
1335 | 1521 |
1336 if (lexer_debug_flag) | 1522 if (lexer_debug_flag) |
1337 { | 1523 { |
1338 std::cerr << "I: "; | 1524 std::cerr << "I: "; |
1339 display_character (c); | 1525 display_character (c); |
1340 std::cerr << std::endl; | 1526 std::cerr << std::endl; |
1341 } | 1527 } |
1342 | 1528 |
1343 if (c != '\n') | 1529 if (c != '\n') |
1344 { | 1530 { |
1345 xunput (c, yytext); | 1531 xunput (c); |
1346 c = '\n'; | 1532 c = '\n'; |
1347 } | 1533 } |
1348 } | 1534 } |
1349 | 1535 |
1350 if (c == '\n') | 1536 if (c == '\n') |
1351 input_line_number++; | 1537 input_line_number++; |
1352 | 1538 |
1353 return c; | 1539 return c; |
1354 } | 1540 } |
1355 | 1541 |
1356 static void | 1542 void |
1357 xunput (char c, char *buf) | 1543 lexical_feedback::xunput (char c, char *buf) |
1358 { | 1544 { |
1359 if (lexer_debug_flag) | 1545 if (lexer_debug_flag) |
1360 { | 1546 { |
1361 std::cerr << "U: "; | 1547 std::cerr << "U: "; |
1362 display_character (c); | 1548 display_character (c); |
1364 } | 1550 } |
1365 | 1551 |
1366 if (c == '\n') | 1552 if (c == '\n') |
1367 input_line_number--; | 1553 input_line_number--; |
1368 | 1554 |
1369 yyunput (c, buf); | 1555 yyunput (c, buf, scanner); |
1556 } | |
1557 | |
1558 void | |
1559 lexical_feedback::xunput (char c) | |
1560 { | |
1561 char *yytxt = flex_yytext (); | |
1562 | |
1563 xunput (c, yytxt); | |
1370 } | 1564 } |
1371 | 1565 |
1372 // If we read some newlines, we need figure out what column we're | 1566 // If we read some newlines, we need figure out what column we're |
1373 // really looking at. | 1567 // really looking at. |
1374 | 1568 |
1375 static void | 1569 void |
1376 fixup_column_count (char *s) | 1570 lexical_feedback::fixup_column_count (char *s) |
1377 { | 1571 { |
1378 char c; | 1572 char c; |
1379 while ((c = *s++) != '\0') | 1573 while ((c = *s++) != '\0') |
1380 { | 1574 { |
1381 if (c == '\n') | 1575 if (c == '\n') |
1386 else | 1580 else |
1387 current_input_column++; | 1581 current_input_column++; |
1388 } | 1582 } |
1389 } | 1583 } |
1390 | 1584 |
1391 // Include these so that we don't have to link to libfl.a. | 1585 bool |
1392 | 1586 lexical_feedback::inside_any_object_index (void) |
1393 int | |
1394 yywrap (void) | |
1395 { | |
1396 return 1; | |
1397 } | |
1398 | |
1399 // Tell us all what the current buffer is. | |
1400 | |
1401 YY_BUFFER_STATE | |
1402 current_buffer (void) | |
1403 { | |
1404 return YY_CURRENT_BUFFER; | |
1405 } | |
1406 | |
1407 // Create a new buffer. | |
1408 | |
1409 YY_BUFFER_STATE | |
1410 create_buffer (FILE *f) | |
1411 { | |
1412 return yy_create_buffer (f, YY_BUF_SIZE); | |
1413 } | |
1414 | |
1415 // Start reading a new buffer. | |
1416 | |
1417 void | |
1418 switch_to_buffer (YY_BUFFER_STATE buf) | |
1419 { | |
1420 yy_switch_to_buffer (buf); | |
1421 } | |
1422 | |
1423 // Delete a buffer. | |
1424 | |
1425 void | |
1426 delete_buffer (YY_BUFFER_STATE buf) | |
1427 { | |
1428 yy_delete_buffer (buf); | |
1429 | |
1430 // Prevent invalid yyin from being used by yyrestart. | |
1431 if (! current_buffer ()) | |
1432 yyin = 0; | |
1433 } | |
1434 | |
1435 // Delete all buffers from the stack. | |
1436 void | |
1437 clear_all_buffers (void) | |
1438 { | |
1439 while (current_buffer ()) | |
1440 octave_pop_buffer_state (); | |
1441 } | |
1442 | |
1443 void | |
1444 cleanup_parser (void) | |
1445 { | |
1446 reset_parser (); | |
1447 | |
1448 clear_all_buffers (); | |
1449 } | |
1450 | |
1451 // Restore a buffer (for unwind-prot). | |
1452 | |
1453 void | |
1454 restore_input_buffer (void *buf) | |
1455 { | |
1456 switch_to_buffer (static_cast<YY_BUFFER_STATE> (buf)); | |
1457 } | |
1458 | |
1459 // Delete a buffer (for unwind-prot). | |
1460 | |
1461 void | |
1462 delete_input_buffer (void *buf) | |
1463 { | |
1464 delete_buffer (static_cast<YY_BUFFER_STATE> (buf)); | |
1465 } | |
1466 | |
1467 static bool | |
1468 inside_any_object_index (void) | |
1469 { | 1587 { |
1470 bool retval = false; | 1588 bool retval = false; |
1471 | 1589 |
1472 for (std::list<bool>::const_iterator i = lexer_flags.looking_at_object_index.begin (); | 1590 for (std::list<bool>::const_iterator i = looking_at_object_index.begin (); |
1473 i != lexer_flags.looking_at_object_index.end (); i++) | 1591 i != looking_at_object_index.end (); i++) |
1474 { | 1592 { |
1475 if (*i) | 1593 if (*i) |
1476 { | 1594 { |
1477 retval = true; | 1595 retval = true; |
1478 break; | 1596 break; |
1482 return retval; | 1600 return retval; |
1483 } | 1601 } |
1484 | 1602 |
1485 // Handle keywords. Return -1 if the keyword should be ignored. | 1603 // Handle keywords. Return -1 if the keyword should be ignored. |
1486 | 1604 |
1487 static int | 1605 int |
1488 is_keyword_token (const std::string& s) | 1606 lexical_feedback::is_keyword_token (const std::string& s) |
1489 { | 1607 { |
1490 int l = input_line_number; | 1608 int l = input_line_number; |
1491 int c = current_input_column; | 1609 int c = current_input_column; |
1492 | 1610 |
1493 int len = s.length (); | 1611 int len = s.length (); |
1494 | 1612 |
1495 const octave_kw *kw = octave_kw_hash::in_word_set (s.c_str (), len); | 1613 const octave_kw *kw = octave_kw_hash::in_word_set (s.c_str (), len); |
1496 | 1614 |
1497 if (kw) | 1615 if (kw) |
1498 { | 1616 { |
1499 yylval.tok_val = 0; | 1617 token *tok_val = 0; |
1500 | 1618 |
1501 switch (kw->kw_id) | 1619 switch (kw->kw_id) |
1502 { | 1620 { |
1503 case break_kw: | 1621 case break_kw: |
1504 case catch_kw: | 1622 case catch_kw: |
1505 case continue_kw: | 1623 case continue_kw: |
1506 case else_kw: | 1624 case else_kw: |
1507 case otherwise_kw: | 1625 case otherwise_kw: |
1508 case return_kw: | 1626 case return_kw: |
1509 case unwind_protect_cleanup_kw: | 1627 case unwind_protect_cleanup_kw: |
1510 lexer_flags.at_beginning_of_statement = true; | 1628 at_beginning_of_statement = true; |
1511 break; | 1629 break; |
1512 | 1630 |
1513 case static_kw: | 1631 case static_kw: |
1514 if ((reading_fcn_file || reading_script_file | 1632 if ((reading_fcn_file || reading_script_file |
1515 || reading_classdef_file) | 1633 || reading_classdef_file) |
1534 break; | 1652 break; |
1535 | 1653 |
1536 case end_kw: | 1654 case end_kw: |
1537 if (inside_any_object_index () | 1655 if (inside_any_object_index () |
1538 || (! reading_classdef_file | 1656 || (! reading_classdef_file |
1539 && (lexer_flags.defining_func | 1657 && (defining_func |
1540 && ! (lexer_flags.looking_at_return_list | 1658 && ! (looking_at_return_list |
1541 || lexer_flags.parsed_function_name.top ())))) | 1659 || parsed_function_name.top ())))) |
1542 return 0; | 1660 return 0; |
1543 | 1661 |
1544 yylval.tok_val = new token (token::simple_end, l, c); | 1662 tok_val = new token (token::simple_end, l, c); |
1545 lexer_flags.at_beginning_of_statement = true; | 1663 at_beginning_of_statement = true; |
1546 break; | 1664 break; |
1547 | 1665 |
1548 case end_try_catch_kw: | 1666 case end_try_catch_kw: |
1549 yylval.tok_val = new token (token::try_catch_end, l, c); | 1667 tok_val = new token (token::try_catch_end, l, c); |
1550 lexer_flags.at_beginning_of_statement = true; | 1668 at_beginning_of_statement = true; |
1551 break; | 1669 break; |
1552 | 1670 |
1553 case end_unwind_protect_kw: | 1671 case end_unwind_protect_kw: |
1554 yylval.tok_val = new token (token::unwind_protect_end, l, c); | 1672 tok_val = new token (token::unwind_protect_end, l, c); |
1555 lexer_flags.at_beginning_of_statement = true; | 1673 at_beginning_of_statement = true; |
1556 break; | 1674 break; |
1557 | 1675 |
1558 case endfor_kw: | 1676 case endfor_kw: |
1559 yylval.tok_val = new token (token::for_end, l, c); | 1677 tok_val = new token (token::for_end, l, c); |
1560 lexer_flags.at_beginning_of_statement = true; | 1678 at_beginning_of_statement = true; |
1561 break; | 1679 break; |
1562 | 1680 |
1563 case endfunction_kw: | 1681 case endfunction_kw: |
1564 yylval.tok_val = new token (token::function_end, l, c); | 1682 tok_val = new token (token::function_end, l, c); |
1565 lexer_flags.at_beginning_of_statement = true; | 1683 at_beginning_of_statement = true; |
1566 break; | 1684 break; |
1567 | 1685 |
1568 case endif_kw: | 1686 case endif_kw: |
1569 yylval.tok_val = new token (token::if_end, l, c); | 1687 tok_val = new token (token::if_end, l, c); |
1570 lexer_flags.at_beginning_of_statement = true; | 1688 at_beginning_of_statement = true; |
1571 break; | 1689 break; |
1572 | 1690 |
1573 case endparfor_kw: | 1691 case endparfor_kw: |
1574 yylval.tok_val = new token (token::parfor_end, l, c); | 1692 tok_val = new token (token::parfor_end, l, c); |
1575 lexer_flags.at_beginning_of_statement = true; | 1693 at_beginning_of_statement = true; |
1576 break; | 1694 break; |
1577 | 1695 |
1578 case endswitch_kw: | 1696 case endswitch_kw: |
1579 yylval.tok_val = new token (token::switch_end, l, c); | 1697 tok_val = new token (token::switch_end, l, c); |
1580 lexer_flags.at_beginning_of_statement = true; | 1698 at_beginning_of_statement = true; |
1581 break; | 1699 break; |
1582 | 1700 |
1583 case endwhile_kw: | 1701 case endwhile_kw: |
1584 yylval.tok_val = new token (token::while_end, l, c); | 1702 tok_val = new token (token::while_end, l, c); |
1585 lexer_flags.at_beginning_of_statement = true; | 1703 at_beginning_of_statement = true; |
1586 break; | 1704 break; |
1587 | 1705 |
1588 case endclassdef_kw: | 1706 case endclassdef_kw: |
1589 yylval.tok_val = new token (token::classdef_end, l, c); | 1707 tok_val = new token (token::classdef_end, l, c); |
1590 lexer_flags.at_beginning_of_statement = true; | 1708 at_beginning_of_statement = true; |
1591 break; | 1709 break; |
1592 | 1710 |
1593 case endenumeration_kw: | 1711 case endenumeration_kw: |
1594 yylval.tok_val = new token (token::enumeration_end, l, c); | 1712 tok_val = new token (token::enumeration_end, l, c); |
1595 lexer_flags.at_beginning_of_statement = true; | 1713 at_beginning_of_statement = true; |
1596 break; | 1714 break; |
1597 | 1715 |
1598 case endevents_kw: | 1716 case endevents_kw: |
1599 yylval.tok_val = new token (token::events_end, l, c); | 1717 tok_val = new token (token::events_end, l, c); |
1600 lexer_flags.at_beginning_of_statement = true; | 1718 at_beginning_of_statement = true; |
1601 break; | 1719 break; |
1602 | 1720 |
1603 case endmethods_kw: | 1721 case endmethods_kw: |
1604 yylval.tok_val = new token (token::methods_end, l, c); | 1722 tok_val = new token (token::methods_end, l, c); |
1605 lexer_flags.at_beginning_of_statement = true; | 1723 at_beginning_of_statement = true; |
1606 break; | 1724 break; |
1607 | 1725 |
1608 case endproperties_kw: | 1726 case endproperties_kw: |
1609 yylval.tok_val = new token (token::properties_end, l, c); | 1727 tok_val = new token (token::properties_end, l, c); |
1610 lexer_flags.at_beginning_of_statement = true; | 1728 at_beginning_of_statement = true; |
1611 break; | 1729 break; |
1612 | 1730 |
1613 | 1731 |
1614 case for_kw: | 1732 case for_kw: |
1615 case parfor_kw: | 1733 case parfor_kw: |
1616 case while_kw: | 1734 case while_kw: |
1617 promptflag--; | 1735 promptflag--; |
1618 lexer_flags.looping++; | 1736 looping++; |
1619 break; | 1737 break; |
1620 | 1738 |
1621 case do_kw: | 1739 case do_kw: |
1622 lexer_flags.at_beginning_of_statement = true; | 1740 at_beginning_of_statement = true; |
1623 promptflag--; | 1741 promptflag--; |
1624 lexer_flags.looping++; | 1742 looping++; |
1625 break; | 1743 break; |
1626 | 1744 |
1627 case try_kw: | 1745 case try_kw: |
1628 case unwind_protect_kw: | 1746 case unwind_protect_kw: |
1629 lexer_flags.at_beginning_of_statement = true; | 1747 at_beginning_of_statement = true; |
1630 promptflag--; | 1748 promptflag--; |
1631 break; | 1749 break; |
1632 | 1750 |
1633 case if_kw: | 1751 case if_kw: |
1634 case switch_kw: | 1752 case switch_kw: |
1637 | 1755 |
1638 case get_kw: | 1756 case get_kw: |
1639 case set_kw: | 1757 case set_kw: |
1640 // 'get' and 'set' are keywords in classdef method | 1758 // 'get' and 'set' are keywords in classdef method |
1641 // declarations. | 1759 // declarations. |
1642 if (! lexer_flags.maybe_classdef_get_set_method) | 1760 if (! maybe_classdef_get_set_method) |
1643 return 0; | 1761 return 0; |
1644 break; | 1762 break; |
1645 | 1763 |
1646 case enumeration_kw: | 1764 case enumeration_kw: |
1647 case events_kw: | 1765 case events_kw: |
1648 case methods_kw: | 1766 case methods_kw: |
1649 case properties_kw: | 1767 case properties_kw: |
1650 // 'properties', 'methods' and 'events' are keywords for | 1768 // 'properties', 'methods' and 'events' are keywords for |
1651 // classdef blocks. | 1769 // classdef blocks. |
1652 if (! lexer_flags.parsing_classdef) | 1770 if (! parsing_classdef) |
1653 return 0; | 1771 return 0; |
1654 // fall through ... | 1772 // fall through ... |
1655 | 1773 |
1656 case classdef_kw: | 1774 case classdef_kw: |
1657 // 'classdef' is always a keyword. | 1775 // 'classdef' is always a keyword. |
1659 break; | 1777 break; |
1660 | 1778 |
1661 case function_kw: | 1779 case function_kw: |
1662 promptflag--; | 1780 promptflag--; |
1663 | 1781 |
1664 lexer_flags.defining_func++; | 1782 defining_func++; |
1665 lexer_flags.parsed_function_name.push (false); | 1783 parsed_function_name.push (false); |
1666 | 1784 |
1667 if (! (reading_fcn_file || reading_script_file | 1785 if (! (reading_fcn_file || reading_script_file |
1668 || reading_classdef_file)) | 1786 || reading_classdef_file)) |
1669 input_line_number = 1; | 1787 input_line_number = 1; |
1670 break; | 1788 break; |
1672 case magic_file_kw: | 1790 case magic_file_kw: |
1673 { | 1791 { |
1674 if ((reading_fcn_file || reading_script_file | 1792 if ((reading_fcn_file || reading_script_file |
1675 || reading_classdef_file) | 1793 || reading_classdef_file) |
1676 && ! curr_fcn_file_full_name.empty ()) | 1794 && ! curr_fcn_file_full_name.empty ()) |
1677 yylval.tok_val = new token (curr_fcn_file_full_name, l, c); | 1795 tok_val = new token (curr_fcn_file_full_name, l, c); |
1678 else | 1796 else |
1679 yylval.tok_val = new token ("stdin", l, c); | 1797 tok_val = new token ("stdin", l, c); |
1680 } | 1798 } |
1681 break; | 1799 break; |
1682 | 1800 |
1683 case magic_line_kw: | 1801 case magic_line_kw: |
1684 yylval.tok_val = new token (static_cast<double> (l), "", l, c); | 1802 tok_val = new token (static_cast<double> (l), "", l, c); |
1685 break; | 1803 break; |
1686 | 1804 |
1687 default: | 1805 default: |
1688 panic_impossible (); | 1806 panic_impossible (); |
1689 } | 1807 } |
1690 | 1808 |
1691 if (! yylval.tok_val) | 1809 if (! tok_val) |
1692 yylval.tok_val = new token (l, c); | 1810 tok_val = new token (l, c); |
1693 | 1811 |
1694 token_stack.push (yylval.tok_val); | 1812 push_token (tok_val); |
1695 | 1813 |
1696 return kw->tok; | 1814 return kw->tok; |
1697 } | 1815 } |
1698 | 1816 |
1699 return 0; | 1817 return 0; |
1700 } | 1818 } |
1701 | 1819 |
1702 static bool | 1820 bool |
1703 is_variable (const std::string& name) | 1821 lexical_feedback::is_variable (const std::string& name) |
1704 { | 1822 { |
1705 return (symbol_table::is_variable (name) | 1823 return (symbol_table::is_variable (name) |
1706 || (lexer_flags.pending_local_variables.find (name) | 1824 || (pending_local_variables.find (name) |
1707 != lexer_flags.pending_local_variables.end ())); | 1825 != pending_local_variables.end ())); |
1708 } | 1826 } |
1709 | 1827 |
1710 static std::string | 1828 std::string |
1711 grab_block_comment (stream_reader& reader, bool& eof) | 1829 lexical_feedback::grab_block_comment (stream_reader& reader, bool& eof) |
1712 { | 1830 { |
1713 std::string buf; | 1831 std::string buf; |
1714 | 1832 |
1715 bool at_bol = true; | 1833 bool at_bol = true; |
1716 bool look_for_marker = false; | 1834 bool look_for_marker = false; |
1812 | 1930 |
1813 return buf; | 1931 return buf; |
1814 } | 1932 } |
1815 | 1933 |
1816 std::string | 1934 std::string |
1817 grab_comment_block (stream_reader& reader, bool at_bol, | 1935 lexical_feedback::grab_comment_block (stream_reader& reader, bool at_bol, |
1818 bool& eof) | 1936 bool& eof) |
1819 { | 1937 { |
1820 std::string buf; | 1938 std::string buf; |
1821 | 1939 |
1822 // TRUE means we are at the beginning of a comment block. | 1940 // TRUE means we are at the beginning of a comment block. |
1823 bool begin_comment = false; | 1941 bool begin_comment = false; |
1951 eof = true; | 2069 eof = true; |
1952 | 2070 |
1953 return buf; | 2071 return buf; |
1954 } | 2072 } |
1955 | 2073 |
1956 class | 2074 int |
1957 flex_stream_reader : public stream_reader | 2075 lexical_feedback::process_comment (bool start_in_block, bool& eof) |
1958 { | 2076 { |
1959 public: | 2077 OCTAVE_YYG; |
1960 flex_stream_reader (char *buf_arg) : stream_reader (), buf (buf_arg) { } | 2078 |
1961 | |
1962 int getc (void) { return ::text_yyinput (); } | |
1963 int ungetc (int c) { ::xunput (c, buf); return 0; } | |
1964 | |
1965 private: | |
1966 | |
1967 // No copying! | |
1968 | |
1969 flex_stream_reader (const flex_stream_reader&); | |
1970 | |
1971 flex_stream_reader& operator = (const flex_stream_reader&); | |
1972 | |
1973 char *buf; | |
1974 }; | |
1975 | |
1976 static int | |
1977 process_comment (bool start_in_block, bool& eof) | |
1978 { | |
1979 eof = false; | 2079 eof = false; |
1980 | 2080 |
1981 std::string help_txt; | 2081 std::string help_txt; |
1982 | 2082 |
1983 if (! help_buf.empty ()) | 2083 if (! help_buf.empty ()) |
1984 help_txt = help_buf.top (); | 2084 help_txt = help_buf.top (); |
1985 | 2085 |
1986 flex_stream_reader flex_reader (yytext); | 2086 char *yytxt = flex_yytext (); |
2087 flex_stream_reader flex_reader (this, yytxt); | |
1987 | 2088 |
1988 // process_comment is only supposed to be called when we are not | 2089 // process_comment is only supposed to be called when we are not |
1989 // initially looking at a block comment. | 2090 // initially looking at a block comment. |
1990 | 2091 |
1991 std::string txt = start_in_block | 2092 std::string txt = start_in_block |
2004 } | 2105 } |
2005 | 2106 |
2006 octave_comment_buffer::append (txt); | 2107 octave_comment_buffer::append (txt); |
2007 | 2108 |
2008 current_input_column = 1; | 2109 current_input_column = 1; |
2009 lexer_flags.quote_is_transpose = false; | 2110 quote_is_transpose = false; |
2010 lexer_flags.convert_spaces_to_comma = true; | 2111 convert_spaces_to_comma = true; |
2011 lexer_flags.at_beginning_of_statement = true; | 2112 at_beginning_of_statement = true; |
2012 | 2113 |
2013 if (YY_START == COMMAND_START) | 2114 if (YY_START == COMMAND_START) |
2014 BEGIN (INITIAL); | 2115 BEGIN (INITIAL); |
2015 | 2116 |
2016 if (nesting_level.none ()) | 2117 if (nesting_level.none ()) |
2019 return ';'; | 2120 return ';'; |
2020 else | 2121 else |
2021 return 0; | 2122 return 0; |
2022 } | 2123 } |
2023 | 2124 |
2024 // Return 1 if the given character matches any character in the given | |
2025 // string. | |
2026 | |
2027 static bool | |
2028 match_any (char c, const char *s) | |
2029 { | |
2030 char tmp; | |
2031 while ((tmp = *s++) != '\0') | |
2032 { | |
2033 if (c == tmp) | |
2034 return true; | |
2035 } | |
2036 return false; | |
2037 } | |
2038 | |
2039 // Given information about the spacing surrounding an operator, | |
2040 // return 1 if it looks like it should be treated as a binary | |
2041 // operator. For example, | |
2042 // | |
2043 // [ 1 + 2 ] or [ 1+ 2] or [ 1+2 ] ==> binary | |
2044 // | |
2045 // [ 1 +2 ] ==> unary | |
2046 | |
2047 static bool | |
2048 looks_like_bin_op (bool spc_prev, int next_char) | |
2049 { | |
2050 bool spc_next = (next_char == ' ' || next_char == '\t'); | |
2051 | |
2052 return ((spc_prev && spc_next) || ! spc_prev); | |
2053 } | |
2054 | |
2055 // Recognize separators. If the separator is a CRLF pair, it is | 2125 // Recognize separators. If the separator is a CRLF pair, it is |
2056 // replaced by a single LF. | 2126 // replaced by a single LF. |
2057 | 2127 |
2058 static bool | 2128 bool |
2059 next_token_is_sep_op (void) | 2129 lexical_feedback::next_token_is_sep_op (void) |
2060 { | 2130 { |
2061 bool retval = false; | 2131 bool retval = false; |
2062 | 2132 |
2063 int c = text_yyinput (); | 2133 int c = text_yyinput (); |
2064 | 2134 |
2065 retval = match_any (c, ",;\n]"); | 2135 retval = match_any (c, ",;\n]"); |
2066 | 2136 |
2067 xunput (c, yytext); | 2137 xunput (c); |
2068 | 2138 |
2069 return retval; | 2139 return retval; |
2070 } | 2140 } |
2071 | 2141 |
2072 // Try to determine if the next token should be treated as a postfix | 2142 // Try to determine if the next token should be treated as a postfix |
2073 // unary operator. This is ugly, but it seems to do the right thing. | 2143 // unary operator. This is ugly, but it seems to do the right thing. |
2074 | 2144 |
2075 static bool | 2145 bool |
2076 next_token_is_postfix_unary_op (bool spc_prev) | 2146 lexical_feedback::next_token_is_postfix_unary_op (bool spc_prev) |
2077 { | 2147 { |
2078 bool un_op = false; | 2148 bool un_op = false; |
2079 | 2149 |
2080 int c0 = text_yyinput (); | 2150 int c0 = text_yyinput (); |
2081 | 2151 |
2085 } | 2155 } |
2086 else if (c0 == '.') | 2156 else if (c0 == '.') |
2087 { | 2157 { |
2088 int c1 = text_yyinput (); | 2158 int c1 = text_yyinput (); |
2089 un_op = (c1 == '\''); | 2159 un_op = (c1 == '\''); |
2090 xunput (c1, yytext); | 2160 xunput (c1); |
2091 } | 2161 } |
2092 else if (c0 == '+') | 2162 else if (c0 == '+') |
2093 { | 2163 { |
2094 int c1 = text_yyinput (); | 2164 int c1 = text_yyinput (); |
2095 un_op = (c1 == '+'); | 2165 un_op = (c1 == '+'); |
2096 xunput (c1, yytext); | 2166 xunput (c1); |
2097 } | 2167 } |
2098 else if (c0 == '-') | 2168 else if (c0 == '-') |
2099 { | 2169 { |
2100 int c1 = text_yyinput (); | 2170 int c1 = text_yyinput (); |
2101 un_op = (c1 == '-'); | 2171 un_op = (c1 == '-'); |
2102 xunput (c1, yytext); | 2172 xunput (c1); |
2103 } | 2173 } |
2104 | 2174 |
2105 xunput (c0, yytext); | 2175 xunput (c0); |
2106 | 2176 |
2107 return un_op; | 2177 return un_op; |
2108 } | 2178 } |
2109 | 2179 |
2110 // Try to determine if the next token should be treated as a binary | 2180 // Try to determine if the next token should be treated as a binary |
2117 // | 2187 // |
2118 // Note that a line continuation directly following a + or - operator | 2188 // Note that a line continuation directly following a + or - operator |
2119 // (e.g., the characters '[' 'a' ' ' '+' '\' LFD 'b' ']') will be | 2189 // (e.g., the characters '[' 'a' ' ' '+' '\' LFD 'b' ']') will be |
2120 // parsed as a binary operator. | 2190 // parsed as a binary operator. |
2121 | 2191 |
2122 static bool | 2192 bool |
2123 next_token_is_bin_op (bool spc_prev) | 2193 lexical_feedback::next_token_is_bin_op (bool spc_prev) |
2124 { | 2194 { |
2125 bool bin_op = false; | 2195 bool bin_op = false; |
2126 | 2196 |
2127 int c0 = text_yyinput (); | 2197 int c0 = text_yyinput (); |
2128 | 2198 |
2149 // Could be either, spacing matters. | 2219 // Could be either, spacing matters. |
2150 bin_op = looks_like_bin_op (spc_prev, c1); | 2220 bin_op = looks_like_bin_op (spc_prev, c1); |
2151 break; | 2221 break; |
2152 } | 2222 } |
2153 | 2223 |
2154 xunput (c1, yytext); | 2224 xunput (c1); |
2155 } | 2225 } |
2156 break; | 2226 break; |
2157 | 2227 |
2158 case ':': | 2228 case ':': |
2159 case '/': | 2229 case '/': |
2173 bin_op = true; | 2243 bin_op = true; |
2174 else if (! isdigit (c1) && c1 != ' ' && c1 != '\t' && c1 != '.') | 2244 else if (! isdigit (c1) && c1 != ' ' && c1 != '\t' && c1 != '.') |
2175 // A structure element reference is a binary op. | 2245 // A structure element reference is a binary op. |
2176 bin_op = true; | 2246 bin_op = true; |
2177 | 2247 |
2178 xunput (c1, yytext); | 2248 xunput (c1); |
2179 } | 2249 } |
2180 break; | 2250 break; |
2181 | 2251 |
2182 // = == & && | || * ** | 2252 // = == & && | || * ** |
2183 case '=': | 2253 case '=': |
2203 | 2273 |
2204 // ~ and ! can be unary ops, so require following =. | 2274 // ~ and ! can be unary ops, so require following =. |
2205 if (c1 == '=') | 2275 if (c1 == '=') |
2206 bin_op = true; | 2276 bin_op = true; |
2207 | 2277 |
2208 xunput (c1, yytext); | 2278 xunput (c1); |
2209 } | 2279 } |
2210 break; | 2280 break; |
2211 | 2281 |
2212 default: | 2282 default: |
2213 break; | 2283 break; |
2214 } | 2284 } |
2215 | 2285 |
2216 xunput (c0, yytext); | 2286 xunput (c0); |
2217 | 2287 |
2218 return bin_op; | 2288 return bin_op; |
2219 } | 2289 } |
2220 | 2290 |
2221 // Used to delete trailing white space from tokens. | |
2222 | |
2223 static std::string | |
2224 strip_trailing_whitespace (char *s) | |
2225 { | |
2226 std::string retval = s; | |
2227 | |
2228 size_t pos = retval.find_first_of (" \t"); | |
2229 | |
2230 if (pos != std::string::npos) | |
2231 retval.resize (pos); | |
2232 | |
2233 return retval; | |
2234 } | |
2235 | |
2236 // FIXME -- we need to handle block comments here. | 2291 // FIXME -- we need to handle block comments here. |
2237 | 2292 |
2238 static void | 2293 void |
2239 scan_for_comments (const char *text) | 2294 lexical_feedback::scan_for_comments (const char *text) |
2240 { | 2295 { |
2241 std::string comment_buf; | 2296 std::string comment_buf; |
2242 | 2297 |
2243 bool in_comment = false; | 2298 bool in_comment = false; |
2244 bool beginning_of_comment = false; | 2299 bool beginning_of_comment = false; |
2291 if (! comment_buf.empty ()) | 2346 if (! comment_buf.empty ()) |
2292 octave_comment_buffer::append (comment_buf); | 2347 octave_comment_buffer::append (comment_buf); |
2293 } | 2348 } |
2294 | 2349 |
2295 // Discard whitespace, including comments and continuations. | 2350 // Discard whitespace, including comments and continuations. |
2296 // | |
2297 // Return value is logical OR of the following values: | |
2298 // | |
2299 // ATE_NOTHING : no spaces to eat | |
2300 // ATE_SPACE_OR_TAB : space or tab in input | |
2301 // ATE_NEWLINE : bare new line in input | |
2302 | 2351 |
2303 // FIXME -- we need to handle block comments here. | 2352 // FIXME -- we need to handle block comments here. |
2304 | 2353 |
2305 static yum_yum | 2354 int |
2306 eat_whitespace (void) | 2355 lexical_feedback::eat_whitespace (void) |
2307 { | 2356 { |
2308 yum_yum retval = ATE_NOTHING; | 2357 int retval = lexical_feedback::NO_WHITESPACE; |
2309 | 2358 |
2310 std::string comment_buf; | 2359 std::string comment_buf; |
2311 | 2360 |
2312 bool in_comment = false; | 2361 bool in_comment = false; |
2313 bool beginning_of_comment = false; | 2362 bool beginning_of_comment = false; |
2325 if (in_comment) | 2374 if (in_comment) |
2326 { | 2375 { |
2327 comment_buf += static_cast<char> (c); | 2376 comment_buf += static_cast<char> (c); |
2328 beginning_of_comment = false; | 2377 beginning_of_comment = false; |
2329 } | 2378 } |
2330 retval |= ATE_SPACE_OR_TAB; | 2379 retval |= lexical_feedback::SPACE_OR_TAB; |
2331 break; | 2380 break; |
2332 | 2381 |
2333 case '\n': | 2382 case '\n': |
2334 retval |= ATE_NEWLINE; | 2383 retval |= lexical_feedback::NEWLINE; |
2335 if (in_comment) | 2384 if (in_comment) |
2336 { | 2385 { |
2337 comment_buf += static_cast<char> (c); | 2386 comment_buf += static_cast<char> (c); |
2338 octave_comment_buffer::append (comment_buf); | 2387 octave_comment_buffer::append (comment_buf); |
2339 comment_buf.resize (0); | 2388 comment_buf.resize (0); |
2402 | 2451 |
2403 if (! comment_buf.empty ()) | 2452 if (! comment_buf.empty ()) |
2404 octave_comment_buffer::append (comment_buf); | 2453 octave_comment_buffer::append (comment_buf); |
2405 | 2454 |
2406 done: | 2455 done: |
2407 xunput (c, yytext); | 2456 xunput (c); |
2408 current_input_column--; | 2457 current_input_column--; |
2409 return retval; | 2458 return retval; |
2410 } | 2459 } |
2411 | 2460 |
2412 static inline bool | 2461 static inline bool |
2413 looks_like_hex (const char *s, int len) | 2462 looks_like_hex (const char *s, int len) |
2414 { | 2463 { |
2415 return (len > 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X')); | 2464 return (len > 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X')); |
2416 } | 2465 } |
2417 | 2466 |
2418 static void | 2467 void |
2419 handle_number (void) | 2468 lexical_feedback::handle_number (void) |
2420 { | 2469 { |
2421 double value = 0.0; | 2470 double value = 0.0; |
2422 int nread = 0; | 2471 int nread = 0; |
2423 | 2472 |
2424 if (looks_like_hex (yytext, strlen (yytext))) | 2473 char *yytxt = flex_yytext (); |
2474 | |
2475 if (looks_like_hex (yytxt, strlen (yytxt))) | |
2425 { | 2476 { |
2426 unsigned long ival; | 2477 unsigned long ival; |
2427 | 2478 |
2428 nread = sscanf (yytext, "%lx", &ival); | 2479 nread = sscanf (yytxt, "%lx", &ival); |
2429 | 2480 |
2430 value = static_cast<double> (ival); | 2481 value = static_cast<double> (ival); |
2431 } | 2482 } |
2432 else | 2483 else |
2433 { | 2484 { |
2434 char *tmp = strsave (yytext); | 2485 char *tmp = strsave (yytxt); |
2435 | 2486 |
2436 char *idx = strpbrk (tmp, "Dd"); | 2487 char *idx = strpbrk (tmp, "Dd"); |
2437 | 2488 |
2438 if (idx) | 2489 if (idx) |
2439 *idx = 'e'; | 2490 *idx = 'e'; |
2445 | 2496 |
2446 // If yytext doesn't contain a valid number, we are in deep doo doo. | 2497 // If yytext doesn't contain a valid number, we are in deep doo doo. |
2447 | 2498 |
2448 assert (nread == 1); | 2499 assert (nread == 1); |
2449 | 2500 |
2450 lexer_flags.quote_is_transpose = true; | 2501 quote_is_transpose = true; |
2451 lexer_flags.convert_spaces_to_comma = true; | 2502 convert_spaces_to_comma = true; |
2452 lexer_flags.looking_for_object_index = false; | 2503 looking_for_object_index = false; |
2453 lexer_flags.at_beginning_of_statement = false; | 2504 at_beginning_of_statement = false; |
2454 | 2505 |
2455 yylval.tok_val = new token (value, yytext, input_line_number, | 2506 push_token (new token (value, yytxt, input_line_number, |
2456 current_input_column); | 2507 current_input_column)); |
2457 | 2508 |
2458 token_stack.push (yylval.tok_val); | 2509 current_input_column += flex_yyleng (); |
2459 | |
2460 current_input_column += yyleng; | |
2461 | 2510 |
2462 do_comma_insert_check (); | 2511 do_comma_insert_check (); |
2463 } | 2512 } |
2464 | 2513 |
2465 // We have seen a backslash and need to find out if it should be | 2514 // We have seen a backslash and need to find out if it should be |
2471 // If non-whitespace characters are found before comment | 2520 // If non-whitespace characters are found before comment |
2472 // characters, return 0. Otherwise, return 1. | 2521 // characters, return 0. Otherwise, return 1. |
2473 | 2522 |
2474 // FIXME -- we need to handle block comments here. | 2523 // FIXME -- we need to handle block comments here. |
2475 | 2524 |
2476 static bool | 2525 bool |
2477 have_continuation (bool trailing_comments_ok) | 2526 lexical_feedback::have_continuation (bool trailing_comments_ok) |
2478 { | 2527 { |
2479 std::ostringstream buf; | 2528 std::ostringstream buf; |
2480 | 2529 |
2481 std::string comment_buf; | 2530 std::string comment_buf; |
2482 | 2531 |
2541 goto cleanup; | 2590 goto cleanup; |
2542 break; | 2591 break; |
2543 } | 2592 } |
2544 } | 2593 } |
2545 | 2594 |
2546 xunput (c, yytext); | 2595 xunput (c); |
2547 return false; | 2596 return false; |
2548 | 2597 |
2549 cleanup: | 2598 cleanup: |
2550 | 2599 |
2551 std::string s = buf.str (); | 2600 std::string s = buf.str (); |
2552 | 2601 |
2553 int len = s.length (); | 2602 int len = s.length (); |
2554 while (len--) | 2603 while (len--) |
2555 xunput (s[len], yytext); | 2604 xunput (s[len]); |
2556 | 2605 |
2557 return false; | 2606 return false; |
2558 } | 2607 } |
2559 | 2608 |
2560 // We have seen a '.' and need to see if it is the start of a | 2609 // We have seen a '.' and need to see if it is the start of a |
2561 // continuation. If so, this eats it, up to and including the new | 2610 // continuation. If so, this eats it, up to and including the new |
2562 // line character. | 2611 // line character. |
2563 | 2612 |
2564 static bool | 2613 bool |
2565 have_ellipsis_continuation (bool trailing_comments_ok) | 2614 lexical_feedback::have_ellipsis_continuation (bool trailing_comments_ok) |
2566 { | 2615 { |
2567 char c1 = text_yyinput (); | 2616 char c1 = text_yyinput (); |
2568 if (c1 == '.') | 2617 if (c1 == '.') |
2569 { | 2618 { |
2570 char c2 = text_yyinput (); | 2619 char c2 = text_yyinput (); |
2571 if (c2 == '.' && have_continuation (trailing_comments_ok)) | 2620 if (c2 == '.' && have_continuation (trailing_comments_ok)) |
2572 return true; | 2621 return true; |
2573 else | 2622 else |
2574 { | 2623 { |
2575 xunput (c2, yytext); | 2624 xunput (c2); |
2576 xunput (c1, yytext); | 2625 xunput (c1); |
2577 } | 2626 } |
2578 } | 2627 } |
2579 else | 2628 else |
2580 xunput (c1, yytext); | 2629 xunput (c1); |
2581 | 2630 |
2582 return false; | 2631 return false; |
2583 } | 2632 } |
2584 | 2633 |
2585 // See if we have a continuation line. If so, eat it and the leading | 2634 // See if we have a continuation line. If so, eat it and the leading |
2586 // whitespace on the next line. | 2635 // whitespace on the next line. |
2587 // | 2636 |
2588 // Return value is the same as described for eat_whitespace(). | 2637 int |
2589 | 2638 lexical_feedback::eat_continuation (void) |
2590 static yum_yum | 2639 { |
2591 eat_continuation (void) | 2640 int retval = lexical_feedback::NO_WHITESPACE; |
2592 { | |
2593 int retval = ATE_NOTHING; | |
2594 | 2641 |
2595 int c = text_yyinput (); | 2642 int c = text_yyinput (); |
2596 | 2643 |
2597 if ((c == '.' && have_ellipsis_continuation ()) | 2644 if ((c == '.' && have_ellipsis_continuation ()) |
2598 || (c == '\\' && have_continuation ())) | 2645 || (c == '\\' && have_continuation ())) |
2599 retval = eat_whitespace (); | 2646 retval = eat_whitespace (); |
2600 else | 2647 else |
2601 xunput (c, yytext); | 2648 xunput (c); |
2602 | 2649 |
2603 return retval; | 2650 return retval; |
2604 } | 2651 } |
2605 | 2652 |
2606 static int | 2653 int |
2607 handle_string (char delim) | 2654 lexical_feedback::handle_string (char delim) |
2608 { | 2655 { |
2609 std::ostringstream buf; | 2656 std::ostringstream buf; |
2610 | 2657 |
2611 int bos_line = input_line_number; | 2658 int bos_line = input_line_number; |
2612 int bos_col = current_input_column; | 2659 int bos_col = current_input_column; |
2659 buf << static_cast<char> (c); | 2706 buf << static_cast<char> (c); |
2660 } | 2707 } |
2661 else | 2708 else |
2662 { | 2709 { |
2663 std::string s; | 2710 std::string s; |
2664 xunput (c, yytext); | 2711 xunput (c); |
2665 | 2712 |
2666 if (delim == '\'') | 2713 if (delim == '\'') |
2667 s = buf.str (); | 2714 s = buf.str (); |
2668 else | 2715 else |
2669 s = do_string_escapes (buf.str ()); | 2716 s = do_string_escapes (buf.str ()); |
2670 | 2717 |
2671 lexer_flags.quote_is_transpose = true; | 2718 quote_is_transpose = true; |
2672 lexer_flags.convert_spaces_to_comma = true; | 2719 convert_spaces_to_comma = true; |
2673 | 2720 |
2674 yylval.tok_val = new token (s, bos_line, bos_col); | 2721 push_token (new token (s, bos_line, bos_col)); |
2675 token_stack.push (yylval.tok_val); | |
2676 | 2722 |
2677 if (delim == '"') | 2723 if (delim == '"') |
2678 gripe_matlab_incompatible ("\" used as string delimiter"); | 2724 gripe_matlab_incompatible ("\" used as string delimiter"); |
2679 else if (delim == '\'') | 2725 else if (delim == '\'') |
2680 gripe_single_quote_string (); | 2726 gripe_single_quote_string (); |
2681 | 2727 |
2682 lexer_flags.looking_for_object_index = true; | 2728 looking_for_object_index = true; |
2683 lexer_flags.at_beginning_of_statement = false; | 2729 at_beginning_of_statement = false; |
2684 | 2730 |
2685 return delim == '"' ? DQ_STRING : SQ_STRING; | 2731 return delim == '"' ? DQ_STRING : SQ_STRING; |
2686 } | 2732 } |
2687 } | 2733 } |
2688 } | 2734 } |
2695 } | 2741 } |
2696 | 2742 |
2697 return LEXICAL_ERROR; | 2743 return LEXICAL_ERROR; |
2698 } | 2744 } |
2699 | 2745 |
2700 static bool | 2746 bool |
2701 next_token_is_assign_op (void) | 2747 lexical_feedback::next_token_is_assign_op (void) |
2702 { | 2748 { |
2703 bool retval = false; | 2749 bool retval = false; |
2704 | 2750 |
2705 int c0 = text_yyinput (); | 2751 int c0 = text_yyinput (); |
2706 | 2752 |
2707 switch (c0) | 2753 switch (c0) |
2708 { | 2754 { |
2709 case '=': | 2755 case '=': |
2710 { | 2756 { |
2711 int c1 = text_yyinput (); | 2757 int c1 = text_yyinput (); |
2712 xunput (c1, yytext); | 2758 xunput (c1); |
2713 if (c1 != '=') | 2759 if (c1 != '=') |
2714 retval = true; | 2760 retval = true; |
2715 } | 2761 } |
2716 break; | 2762 break; |
2717 | 2763 |
2722 case '\\': | 2768 case '\\': |
2723 case '&': | 2769 case '&': |
2724 case '|': | 2770 case '|': |
2725 { | 2771 { |
2726 int c1 = text_yyinput (); | 2772 int c1 = text_yyinput (); |
2727 xunput (c1, yytext); | 2773 xunput (c1); |
2728 if (c1 == '=') | 2774 if (c1 == '=') |
2729 retval = true; | 2775 retval = true; |
2730 } | 2776 } |
2731 break; | 2777 break; |
2732 | 2778 |
2734 { | 2780 { |
2735 int c1 = text_yyinput (); | 2781 int c1 = text_yyinput (); |
2736 if (match_any (c1, "+-*/\\")) | 2782 if (match_any (c1, "+-*/\\")) |
2737 { | 2783 { |
2738 int c2 = text_yyinput (); | 2784 int c2 = text_yyinput (); |
2739 xunput (c2, yytext); | 2785 xunput (c2); |
2740 if (c2 == '=') | 2786 if (c2 == '=') |
2741 retval = true; | 2787 retval = true; |
2742 } | 2788 } |
2743 xunput (c1, yytext); | 2789 xunput (c1); |
2744 } | 2790 } |
2745 break; | 2791 break; |
2746 | 2792 |
2747 case '>': | 2793 case '>': |
2748 { | 2794 { |
2749 int c1 = text_yyinput (); | 2795 int c1 = text_yyinput (); |
2750 if (c1 == '>') | 2796 if (c1 == '>') |
2751 { | 2797 { |
2752 int c2 = text_yyinput (); | 2798 int c2 = text_yyinput (); |
2753 xunput (c2, yytext); | 2799 xunput (c2); |
2754 if (c2 == '=') | 2800 if (c2 == '=') |
2755 retval = true; | 2801 retval = true; |
2756 } | 2802 } |
2757 xunput (c1, yytext); | 2803 xunput (c1); |
2758 } | 2804 } |
2759 break; | 2805 break; |
2760 | 2806 |
2761 case '<': | 2807 case '<': |
2762 { | 2808 { |
2763 int c1 = text_yyinput (); | 2809 int c1 = text_yyinput (); |
2764 if (c1 == '<') | 2810 if (c1 == '<') |
2765 { | 2811 { |
2766 int c2 = text_yyinput (); | 2812 int c2 = text_yyinput (); |
2767 xunput (c2, yytext); | 2813 xunput (c2); |
2768 if (c2 == '=') | 2814 if (c2 == '=') |
2769 retval = true; | 2815 retval = true; |
2770 } | 2816 } |
2771 xunput (c1, yytext); | 2817 xunput (c1); |
2772 } | 2818 } |
2773 break; | 2819 break; |
2774 | 2820 |
2775 default: | 2821 default: |
2776 break; | 2822 break; |
2777 } | 2823 } |
2778 | 2824 |
2779 xunput (c0, yytext); | 2825 xunput (c0); |
2780 | 2826 |
2781 return retval; | 2827 return retval; |
2782 } | 2828 } |
2783 | 2829 |
2784 static bool | 2830 bool |
2785 next_token_is_index_op (void) | 2831 lexical_feedback::next_token_is_index_op (void) |
2786 { | 2832 { |
2787 int c = text_yyinput (); | 2833 int c = text_yyinput (); |
2788 xunput (c, yytext); | 2834 xunput (c); |
2789 return c == '(' || c == '{'; | 2835 return c == '(' || c == '{'; |
2790 } | 2836 } |
2791 | 2837 |
2792 static int | 2838 int |
2793 handle_close_bracket (bool spc_gobbled, int bracket_type) | 2839 lexical_feedback::handle_close_bracket (bool spc_gobbled, int bracket_type) |
2794 { | 2840 { |
2841 OCTAVE_YYG; | |
2842 | |
2795 int retval = bracket_type; | 2843 int retval = bracket_type; |
2796 | 2844 |
2797 if (! nesting_level.none ()) | 2845 if (! nesting_level.none ()) |
2798 { | 2846 { |
2799 nesting_level.remove (); | 2847 nesting_level.remove (); |
2800 | 2848 |
2801 if (bracket_type == ']') | 2849 if (bracket_type == ']') |
2802 lexer_flags.bracketflag--; | 2850 bracketflag--; |
2803 else if (bracket_type == '}') | 2851 else if (bracket_type == '}') |
2804 lexer_flags.braceflag--; | 2852 braceflag--; |
2805 else | 2853 else |
2806 panic_impossible (); | 2854 panic_impossible (); |
2807 } | 2855 } |
2808 | 2856 |
2809 if (lexer_flags.bracketflag == 0 && lexer_flags.braceflag == 0) | 2857 if (bracketflag == 0 && braceflag == 0) |
2810 BEGIN (INITIAL); | 2858 BEGIN (INITIAL); |
2811 | 2859 |
2812 if (bracket_type == ']' | 2860 if (bracket_type == ']' |
2813 && next_token_is_assign_op () | 2861 && next_token_is_assign_op () |
2814 && ! lexer_flags.looking_at_return_list) | 2862 && ! looking_at_return_list) |
2815 { | 2863 { |
2816 retval = CLOSE_BRACE; | 2864 retval = CLOSE_BRACE; |
2817 } | 2865 } |
2818 else if ((lexer_flags.bracketflag || lexer_flags.braceflag) | 2866 else if ((bracketflag || braceflag) |
2819 && lexer_flags.convert_spaces_to_comma | 2867 && convert_spaces_to_comma |
2820 && (nesting_level.is_bracket () | 2868 && (nesting_level.is_bracket () |
2821 || (nesting_level.is_brace () | 2869 || (nesting_level.is_brace () |
2822 && ! lexer_flags.looking_at_object_index.front ()))) | 2870 && ! looking_at_object_index.front ()))) |
2823 { | 2871 { |
2824 bool index_op = next_token_is_index_op (); | 2872 bool index_op = next_token_is_index_op (); |
2825 | 2873 |
2826 // Don't insert comma if we are looking at something like | 2874 // Don't insert comma if we are looking at something like |
2827 // | 2875 // |
2841 | 2889 |
2842 if (! (postfix_un_op || bin_op || sep_op)) | 2890 if (! (postfix_un_op || bin_op || sep_op)) |
2843 { | 2891 { |
2844 maybe_warn_separator_insert (','); | 2892 maybe_warn_separator_insert (','); |
2845 | 2893 |
2846 xunput (',', yytext); | 2894 xunput (','); |
2847 return retval; | 2895 return retval; |
2848 } | 2896 } |
2849 } | 2897 } |
2850 } | 2898 } |
2851 | 2899 |
2852 lexer_flags.quote_is_transpose = true; | 2900 quote_is_transpose = true; |
2853 lexer_flags.convert_spaces_to_comma = true; | 2901 convert_spaces_to_comma = true; |
2854 | 2902 |
2855 return retval; | 2903 return retval; |
2856 } | 2904 } |
2857 | 2905 |
2858 static void | 2906 void |
2859 maybe_unput_comma (int spc_gobbled) | 2907 lexical_feedback::maybe_unput_comma (int spc_gobbled) |
2860 { | 2908 { |
2861 if (nesting_level.is_bracket () | 2909 if (nesting_level.is_bracket () |
2862 || (nesting_level.is_brace () | 2910 || (nesting_level.is_brace () |
2863 && ! lexer_flags.looking_at_object_index.front ())) | 2911 && ! looking_at_object_index.front ())) |
2864 { | 2912 { |
2865 int bin_op = next_token_is_bin_op (spc_gobbled); | 2913 int bin_op = next_token_is_bin_op (spc_gobbled); |
2866 | 2914 |
2867 int postfix_un_op = next_token_is_postfix_unary_op (spc_gobbled); | 2915 int postfix_un_op = next_token_is_postfix_unary_op (spc_gobbled); |
2868 | 2916 |
2869 int c1 = text_yyinput (); | 2917 int c1 = text_yyinput (); |
2870 int c2 = text_yyinput (); | 2918 int c2 = text_yyinput (); |
2871 | 2919 |
2872 xunput (c2, yytext); | 2920 xunput (c2); |
2873 xunput (c1, yytext); | 2921 xunput (c1); |
2874 | 2922 |
2875 int sep_op = next_token_is_sep_op (); | 2923 int sep_op = next_token_is_sep_op (); |
2876 | 2924 |
2877 int dot_op = (c1 == '.' | 2925 int dot_op = (c1 == '.' |
2878 && (isalpha (c2) || isspace (c2) || c2 == '_')); | 2926 && (isalpha (c2) || isspace (c2) || c2 == '_')); |
2888 if (index_op && ! spc_gobbled) | 2936 if (index_op && ! spc_gobbled) |
2889 return; | 2937 return; |
2890 | 2938 |
2891 maybe_warn_separator_insert (','); | 2939 maybe_warn_separator_insert (','); |
2892 | 2940 |
2893 xunput (',', yytext); | 2941 xunput (','); |
2894 } | 2942 } |
2895 } | 2943 } |
2896 | 2944 |
2897 static bool | 2945 bool |
2898 next_token_can_follow_bin_op (void) | 2946 lexical_feedback::next_token_can_follow_bin_op (void) |
2899 { | 2947 { |
2900 std::stack<char> buf; | 2948 std::stack<char> buf; |
2901 | 2949 |
2902 int c = EOF; | 2950 int c = EOF; |
2903 | 2951 |
2913 } | 2961 } |
2914 | 2962 |
2915 // Restore input. | 2963 // Restore input. |
2916 while (! buf.empty ()) | 2964 while (! buf.empty ()) |
2917 { | 2965 { |
2918 xunput (buf.top (), yytext); | 2966 xunput (buf.top ()); |
2919 | 2967 |
2920 buf.pop (); | 2968 buf.pop (); |
2921 } | 2969 } |
2922 | 2970 |
2923 return (isalnum (c) || match_any (c, "!\"'(-[_{~")); | 2971 return (isalnum (c) || match_any (c, "!\"'(-[_{~")); |
2934 || tok == "J" || tok == "j" | 2982 || tok == "J" || tok == "j" |
2935 || tok == "Inf" || tok == "inf" | 2983 || tok == "Inf" || tok == "inf" |
2936 || tok == "NaN" || tok == "nan"); | 2984 || tok == "NaN" || tok == "nan"); |
2937 } | 2985 } |
2938 | 2986 |
2939 static bool | 2987 bool |
2940 looks_like_command_arg (void) | 2988 lexical_feedback::looks_like_command_arg (void) |
2941 { | 2989 { |
2942 bool retval = true; | 2990 bool retval = true; |
2943 | 2991 |
2944 int c0 = text_yyinput (); | 2992 int c0 = text_yyinput (); |
2945 | 2993 |
2956 | 3004 |
2957 if (! match_any (c2, ",;\n") && (c2 == ' ' || c2 == '\t') | 3005 if (! match_any (c2, ",;\n") && (c2 == ' ' || c2 == '\t') |
2958 && next_token_can_follow_bin_op ()) | 3006 && next_token_can_follow_bin_op ()) |
2959 retval = false; | 3007 retval = false; |
2960 | 3008 |
2961 xunput (c2, yytext); | 3009 xunput (c2); |
2962 } | 3010 } |
2963 else | 3011 else |
2964 retval = false; | 3012 retval = false; |
2965 | 3013 |
2966 xunput (c1, yytext); | 3014 xunput (c1); |
2967 } | 3015 } |
2968 break; | 3016 break; |
2969 | 3017 |
2970 case '(': | 3018 case '(': |
2971 case '{': | 3019 case '{': |
3011 | 3059 |
3012 if (! match_any (c2, ",;\n") && (c2 == ' ' || c2 == '\t') | 3060 if (! match_any (c2, ",;\n") && (c2 == ' ' || c2 == '\t') |
3013 && next_token_can_follow_bin_op ()) | 3061 && next_token_can_follow_bin_op ()) |
3014 retval = false; | 3062 retval = false; |
3015 | 3063 |
3016 xunput (c2, yytext); | 3064 xunput (c2); |
3017 } | 3065 } |
3018 break; | 3066 break; |
3019 } | 3067 } |
3020 | 3068 |
3021 xunput (c1, yytext); | 3069 xunput (c1); |
3022 } | 3070 } |
3023 break; | 3071 break; |
3024 | 3072 |
3025 case ':': | 3073 case ':': |
3026 case '/': | 3074 case '/': |
3031 | 3079 |
3032 if (! match_any (c1, ",;\n") && (c1 == ' ' || c1 == '\t') | 3080 if (! match_any (c1, ",;\n") && (c1 == ' ' || c1 == '\t') |
3033 && next_token_can_follow_bin_op ()) | 3081 && next_token_can_follow_bin_op ()) |
3034 retval = false; | 3082 retval = false; |
3035 | 3083 |
3036 xunput (c1, yytext); | 3084 xunput (c1); |
3037 } | 3085 } |
3038 break; | 3086 break; |
3039 | 3087 |
3040 // .+ .- ./ .\ .^ .* .** | 3088 // .+ .- ./ .\ .^ .* .** |
3041 case '.': | 3089 case '.': |
3052 | 3100 |
3053 if (! match_any (c3, ",;\n") && (c3 == ' ' || c3 == '\t') | 3101 if (! match_any (c3, ",;\n") && (c3 == ' ' || c3 == '\t') |
3054 && next_token_can_follow_bin_op ()) | 3102 && next_token_can_follow_bin_op ()) |
3055 retval = false; | 3103 retval = false; |
3056 | 3104 |
3057 xunput (c3, yytext); | 3105 xunput (c3); |
3058 } | 3106 } |
3059 else if (! match_any (c2, ",;\n") && (c2 == ' ' || c2 == '\t') | 3107 else if (! match_any (c2, ",;\n") && (c2 == ' ' || c2 == '\t') |
3060 && next_token_can_follow_bin_op ()) | 3108 && next_token_can_follow_bin_op ()) |
3061 retval = false; | 3109 retval = false; |
3062 | 3110 |
3063 xunput (c2, yytext); | 3111 xunput (c2); |
3064 } | 3112 } |
3065 else if (! match_any (c1, ",;\n") | 3113 else if (! match_any (c1, ",;\n") |
3066 && (! isdigit (c1) && c1 != ' ' && c1 != '\t' | 3114 && (! isdigit (c1) && c1 != ' ' && c1 != '\t' |
3067 && c1 != '.')) | 3115 && c1 != '.')) |
3068 { | 3116 { |
3069 // Structure reference. FIXME -- is this a complete check? | 3117 // Structure reference. FIXME -- is this a complete check? |
3070 | 3118 |
3071 retval = false; | 3119 retval = false; |
3072 } | 3120 } |
3073 | 3121 |
3074 xunput (c1, yytext); | 3122 xunput (c1); |
3075 } | 3123 } |
3076 break; | 3124 break; |
3077 | 3125 |
3078 // & && | || * ** | 3126 // & && | || * ** |
3079 case '&': | 3127 case '&': |
3088 | 3136 |
3089 if (! match_any (c2, ",;\n") && (c2 == ' ' || c2 == '\t') | 3137 if (! match_any (c2, ",;\n") && (c2 == ' ' || c2 == '\t') |
3090 && next_token_can_follow_bin_op ()) | 3138 && next_token_can_follow_bin_op ()) |
3091 retval = false; | 3139 retval = false; |
3092 | 3140 |
3093 xunput (c2, yytext); | 3141 xunput (c2); |
3094 } | 3142 } |
3095 else if (! match_any (c1, ",;\n") && (c1 == ' ' || c1 == '\t') | 3143 else if (! match_any (c1, ",;\n") && (c1 == ' ' || c1 == '\t') |
3096 && next_token_can_follow_bin_op ()) | 3144 && next_token_can_follow_bin_op ()) |
3097 retval = false; | 3145 retval = false; |
3098 | 3146 |
3099 xunput (c1, yytext); | 3147 xunput (c1); |
3100 } | 3148 } |
3101 break; | 3149 break; |
3102 | 3150 |
3103 // < <= > >= | 3151 // < <= > >= |
3104 case '<': | 3152 case '<': |
3112 | 3160 |
3113 if (! match_any (c2, ",;\n") && (c2 == ' ' || c2 == '\t') | 3161 if (! match_any (c2, ",;\n") && (c2 == ' ' || c2 == '\t') |
3114 && next_token_can_follow_bin_op ()) | 3162 && next_token_can_follow_bin_op ()) |
3115 retval = false; | 3163 retval = false; |
3116 | 3164 |
3117 xunput (c2, yytext); | 3165 xunput (c2); |
3118 } | 3166 } |
3119 else if (! match_any (c1, ",;\n") && (c1 == ' ' || c1 == '\t') | 3167 else if (! match_any (c1, ",;\n") && (c1 == ' ' || c1 == '\t') |
3120 && next_token_can_follow_bin_op ()) | 3168 && next_token_can_follow_bin_op ()) |
3121 retval = false; | 3169 retval = false; |
3122 | 3170 |
3123 xunput (c1, yytext); | 3171 xunput (c1); |
3124 } | 3172 } |
3125 break; | 3173 break; |
3126 | 3174 |
3127 // ~= != | 3175 // ~= != |
3128 case '~': | 3176 case '~': |
3137 | 3185 |
3138 if (! match_any (c2, ",;\n") && (c2 == ' ' || c2 == '\t') | 3186 if (! match_any (c2, ",;\n") && (c2 == ' ' || c2 == '\t') |
3139 && next_token_can_follow_bin_op ()) | 3187 && next_token_can_follow_bin_op ()) |
3140 retval = false; | 3188 retval = false; |
3141 | 3189 |
3142 xunput (c2, yytext); | 3190 xunput (c2); |
3143 } | 3191 } |
3144 else if (! match_any (c1, ",;\n") && (c1 == ' ' || c1 == '\t') | 3192 else if (! match_any (c1, ",;\n") && (c1 == ' ' || c1 == '\t') |
3145 && next_token_can_follow_bin_op ()) | 3193 && next_token_can_follow_bin_op ()) |
3146 retval = false; | 3194 retval = false; |
3147 | 3195 |
3148 xunput (c1, yytext); | 3196 xunput (c1); |
3149 } | 3197 } |
3150 break; | 3198 break; |
3151 | 3199 |
3152 default: | 3200 default: |
3153 break; | 3201 break; |
3154 } | 3202 } |
3155 | 3203 |
3156 xunput (c0, yytext); | 3204 xunput (c0); |
3157 | 3205 |
3158 return retval; | 3206 return retval; |
3159 } | 3207 } |
3160 | 3208 |
3161 static int | 3209 int |
3162 handle_superclass_identifier (void) | 3210 lexical_feedback::handle_superclass_identifier (void) |
3163 { | 3211 { |
3164 int c = yytext[yyleng-1]; | 3212 char *yytxt = flex_yytext (); |
3165 | 3213 int c = yytxt[flex_yyleng()-1]; |
3166 std::string meth = strip_trailing_whitespace (yytext); | 3214 |
3215 std::string meth = strip_trailing_whitespace (yytxt); | |
3167 | 3216 |
3168 int cont_is_spc = eat_continuation (); | 3217 int cont_is_spc = eat_continuation (); |
3169 | 3218 |
3170 int spc_gobbled = (cont_is_spc || c == ' ' || c == '\t'); | 3219 int spc_gobbled = (cont_is_spc || c == ' ' || c == '\t'); |
3171 | 3220 |
3187 { | 3236 { |
3188 error ("method, class, and package names may not be keywords"); | 3237 error ("method, class, and package names may not be keywords"); |
3189 return LEXICAL_ERROR; | 3238 return LEXICAL_ERROR; |
3190 } | 3239 } |
3191 | 3240 |
3192 yylval.tok_val = new token (meth, pkg, cls, input_line_number, | 3241 push_token (new token (meth, pkg, cls, input_line_number, |
3193 current_input_column); | 3242 current_input_column)); |
3194 token_stack.push (yylval.tok_val); | |
3195 | 3243 |
3196 do_comma_insert_check (); | 3244 do_comma_insert_check (); |
3197 maybe_unput_comma (spc_gobbled); | 3245 maybe_unput_comma (spc_gobbled); |
3198 current_input_column += yyleng; | 3246 current_input_column += flex_yyleng (); |
3199 | 3247 |
3200 return SUPERCLASSREF; | 3248 return SUPERCLASSREF; |
3201 } | 3249 } |
3202 | 3250 |
3203 static int | 3251 int |
3204 handle_meta_identifier (void) | 3252 lexical_feedback::handle_meta_identifier (void) |
3205 { | 3253 { |
3206 int c = yytext[yyleng-1]; | 3254 char *yytxt = flex_yytext (); |
3207 | 3255 int c = yytxt[flex_yyleng()-1]; |
3208 std::string cls = strip_trailing_whitespace (yytext).substr (1); | 3256 |
3257 std::string cls = strip_trailing_whitespace (yytxt).substr (1); | |
3209 | 3258 |
3210 int cont_is_spc = eat_continuation (); | 3259 int cont_is_spc = eat_continuation (); |
3211 | 3260 |
3212 int spc_gobbled = (cont_is_spc || c == ' ' || c == '\t'); | 3261 int spc_gobbled = (cont_is_spc || c == ' ' || c == '\t'); |
3213 | 3262 |
3224 { | 3273 { |
3225 error ("class and package names may not be keywords"); | 3274 error ("class and package names may not be keywords"); |
3226 return LEXICAL_ERROR; | 3275 return LEXICAL_ERROR; |
3227 } | 3276 } |
3228 | 3277 |
3229 yylval.tok_val = new token (pkg, cls, input_line_number, | 3278 push_token (new token (pkg, cls, input_line_number, |
3230 current_input_column); | 3279 current_input_column)); |
3231 token_stack.push (yylval.tok_val); | |
3232 | 3280 |
3233 do_comma_insert_check (); | 3281 do_comma_insert_check (); |
3234 maybe_unput_comma (spc_gobbled); | 3282 maybe_unput_comma (spc_gobbled); |
3235 current_input_column += yyleng; | 3283 current_input_column += flex_yyleng (); |
3236 | 3284 |
3237 return METAQUERY; | 3285 return METAQUERY; |
3238 } | 3286 } |
3239 | 3287 |
3240 // Figure out exactly what kind of token to return when we have seen | 3288 // Figure out exactly what kind of token to return when we have seen |
3241 // an identifier. Handles keywords. Return -1 if the identifier | 3289 // an identifier. Handles keywords. Return -1 if the identifier |
3242 // should be ignored. | 3290 // should be ignored. |
3243 | 3291 |
3244 static int | 3292 int |
3245 handle_identifier (void) | 3293 lexical_feedback::handle_identifier (void) |
3246 { | 3294 { |
3247 bool at_bos = lexer_flags.at_beginning_of_statement; | 3295 OCTAVE_YYG; |
3248 | 3296 |
3249 std::string tok = strip_trailing_whitespace (yytext); | 3297 bool at_bos = at_beginning_of_statement; |
3250 | 3298 |
3251 int c = yytext[yyleng-1]; | 3299 char *yytxt = flex_yytext (); |
3252 | 3300 |
3253 int cont_is_spc = eat_continuation (); | 3301 std::string tok = strip_trailing_whitespace (yytxt); |
3302 | |
3303 int c = yytxt[flex_yyleng()-1]; | |
3304 | |
3305 bool cont_is_spc = (eat_continuation () != lexical_feedback::NO_WHITESPACE); | |
3254 | 3306 |
3255 int spc_gobbled = (cont_is_spc || c == ' ' || c == '\t'); | 3307 int spc_gobbled = (cont_is_spc || c == ' ' || c == '\t'); |
3256 | 3308 |
3257 // If we are expecting a structure element, avoid recognizing | 3309 // If we are expecting a structure element, avoid recognizing |
3258 // keywords and other special names and return STRUCT_ELT, which is | 3310 // keywords and other special names and return STRUCT_ELT, which is |
3259 // a string that is also a valid identifier. But first, we have to | 3311 // a string that is also a valid identifier. But first, we have to |
3260 // decide whether to insert a comma. | 3312 // decide whether to insert a comma. |
3261 | 3313 |
3262 if (lexer_flags.looking_at_indirect_ref) | 3314 if (looking_at_indirect_ref) |
3263 { | 3315 { |
3264 do_comma_insert_check (); | 3316 do_comma_insert_check (); |
3265 | 3317 |
3266 maybe_unput_comma (spc_gobbled); | 3318 maybe_unput_comma (spc_gobbled); |
3267 | 3319 |
3268 yylval.tok_val = new token (tok, input_line_number, | 3320 push_token (new token (tok, input_line_number, |
3269 current_input_column); | 3321 current_input_column)); |
3270 | 3322 |
3271 token_stack.push (yylval.tok_val); | 3323 quote_is_transpose = true; |
3272 | 3324 convert_spaces_to_comma = true; |
3273 lexer_flags.quote_is_transpose = true; | 3325 looking_for_object_index = true; |
3274 lexer_flags.convert_spaces_to_comma = true; | 3326 |
3275 lexer_flags.looking_for_object_index = true; | 3327 current_input_column += flex_yyleng (); |
3276 | |
3277 current_input_column += yyleng; | |
3278 | 3328 |
3279 return STRUCT_ELT; | 3329 return STRUCT_ELT; |
3280 } | 3330 } |
3281 | 3331 |
3282 lexer_flags.at_beginning_of_statement = false; | 3332 at_beginning_of_statement = false; |
3283 | 3333 |
3284 // The is_keyword_token may reset | 3334 // The is_keyword_token may reset |
3285 // lexer_flags.at_beginning_of_statement. For example, if it sees | 3335 // at_beginning_of_statement. For example, if it sees |
3286 // an else token, then the next token is at the beginning of a | 3336 // an else token, then the next token is at the beginning of a |
3287 // statement. | 3337 // statement. |
3288 | 3338 |
3289 int kw_token = is_keyword_token (tok); | 3339 int kw_token = is_keyword_token (tok); |
3290 | 3340 |
3291 // If we found a keyword token, then the beginning_of_statement flag | 3341 // If we found a keyword token, then the beginning_of_statement flag |
3292 // is already set. Otherwise, we won't be at the beginning of a | 3342 // is already set. Otherwise, we won't be at the beginning of a |
3293 // statement. | 3343 // statement. |
3294 | 3344 |
3295 if (lexer_flags.looking_at_function_handle) | 3345 if (looking_at_function_handle) |
3296 { | 3346 { |
3297 if (kw_token) | 3347 if (kw_token) |
3298 { | 3348 { |
3299 error ("function handles may not refer to keywords"); | 3349 error ("function handles may not refer to keywords"); |
3300 | 3350 |
3301 return LEXICAL_ERROR; | 3351 return LEXICAL_ERROR; |
3302 } | 3352 } |
3303 else | 3353 else |
3304 { | 3354 { |
3305 yylval.tok_val = new token (tok, input_line_number, | 3355 push_token (new token (tok, input_line_number, |
3306 current_input_column); | 3356 current_input_column)); |
3307 | 3357 |
3308 token_stack.push (yylval.tok_val); | 3358 current_input_column += flex_yyleng (); |
3309 | 3359 quote_is_transpose = false; |
3310 current_input_column += yyleng; | 3360 convert_spaces_to_comma = true; |
3311 lexer_flags.quote_is_transpose = false; | 3361 looking_for_object_index = true; |
3312 lexer_flags.convert_spaces_to_comma = true; | |
3313 lexer_flags.looking_for_object_index = true; | |
3314 | 3362 |
3315 return FCN_HANDLE; | 3363 return FCN_HANDLE; |
3316 } | 3364 } |
3317 } | 3365 } |
3318 | 3366 |
3321 | 3369 |
3322 if (kw_token) | 3370 if (kw_token) |
3323 { | 3371 { |
3324 if (kw_token >= 0) | 3372 if (kw_token >= 0) |
3325 { | 3373 { |
3326 current_input_column += yyleng; | 3374 current_input_column += flex_yyleng (); |
3327 lexer_flags.quote_is_transpose = false; | 3375 quote_is_transpose = false; |
3328 lexer_flags.convert_spaces_to_comma = true; | 3376 convert_spaces_to_comma = true; |
3329 lexer_flags.looking_for_object_index = false; | 3377 looking_for_object_index = false; |
3330 } | 3378 } |
3331 | 3379 |
3332 return kw_token; | 3380 return kw_token; |
3333 } | 3381 } |
3334 | 3382 |
3338 | 3386 |
3339 bool next_tok_is_eq = false; | 3387 bool next_tok_is_eq = false; |
3340 if (c1 == '=') | 3388 if (c1 == '=') |
3341 { | 3389 { |
3342 int c2 = text_yyinput (); | 3390 int c2 = text_yyinput (); |
3343 xunput (c2, yytext); | 3391 xunput (c2); |
3344 | 3392 |
3345 if (c2 != '=') | 3393 if (c2 != '=') |
3346 next_tok_is_eq = true; | 3394 next_tok_is_eq = true; |
3347 } | 3395 } |
3348 | 3396 |
3349 xunput (c1, yytext); | 3397 xunput (c1); |
3350 | 3398 |
3351 // Kluge alert. | 3399 // Kluge alert. |
3352 // | 3400 // |
3353 // If we are looking at a text style function, set up to gobble its | 3401 // If we are looking at a text style function, set up to gobble its |
3354 // arguments. | 3402 // arguments. |
3364 && looks_like_command_arg ()) | 3412 && looks_like_command_arg ()) |
3365 { | 3413 { |
3366 BEGIN (COMMAND_START); | 3414 BEGIN (COMMAND_START); |
3367 } | 3415 } |
3368 else if (next_tok_is_eq | 3416 else if (next_tok_is_eq |
3369 || lexer_flags.looking_at_decl_list | 3417 || looking_at_decl_list |
3370 || lexer_flags.looking_at_return_list | 3418 || looking_at_return_list |
3371 || (lexer_flags.looking_at_parameter_list | 3419 || (looking_at_parameter_list |
3372 && ! lexer_flags.looking_at_initializer_expression)) | 3420 && ! looking_at_initializer_expression)) |
3373 { | 3421 { |
3374 symbol_table::force_variable (tok); | 3422 symbol_table::force_variable (tok); |
3375 } | 3423 } |
3376 else if (lexer_flags.looking_at_matrix_or_assign_lhs) | 3424 else if (looking_at_matrix_or_assign_lhs) |
3377 { | 3425 { |
3378 lexer_flags.pending_local_variables.insert (tok); | 3426 pending_local_variables.insert (tok); |
3379 } | 3427 } |
3380 } | 3428 } |
3381 | 3429 |
3382 // Find the token in the symbol table. Beware the magic | 3430 // Find the token in the symbol table. Beware the magic |
3383 // transformation of the end keyword... | 3431 // transformation of the end keyword... |
3384 | 3432 |
3385 if (tok == "end") | 3433 if (tok == "end") |
3386 tok = "__end__"; | 3434 tok = "__end__"; |
3387 | 3435 |
3388 yylval.tok_val = new token (&(symbol_table::insert (tok)), | 3436 push_token (new token (&(symbol_table::insert (tok)), |
3389 input_line_number, current_input_column); | 3437 input_line_number, current_input_column)); |
3390 | |
3391 token_stack.push (yylval.tok_val); | |
3392 | 3438 |
3393 // After seeing an identifer, it is ok to convert spaces to a comma | 3439 // After seeing an identifer, it is ok to convert spaces to a comma |
3394 // (if needed). | 3440 // (if needed). |
3395 | 3441 |
3396 lexer_flags.convert_spaces_to_comma = true; | 3442 convert_spaces_to_comma = true; |
3397 | 3443 |
3398 if (! (next_tok_is_eq || YY_START == COMMAND_START)) | 3444 if (! (next_tok_is_eq || YY_START == COMMAND_START)) |
3399 { | 3445 { |
3400 lexer_flags.quote_is_transpose = true; | 3446 quote_is_transpose = true; |
3401 | 3447 |
3402 do_comma_insert_check (); | 3448 do_comma_insert_check (); |
3403 | 3449 |
3404 maybe_unput_comma (spc_gobbled); | 3450 maybe_unput_comma (spc_gobbled); |
3405 } | 3451 } |
3406 | 3452 |
3407 current_input_column += yyleng; | 3453 current_input_column += flex_yyleng (); |
3408 | 3454 |
3409 if (tok != "__end__") | 3455 if (tok != "__end__") |
3410 lexer_flags.looking_for_object_index = true; | 3456 looking_for_object_index = true; |
3411 | 3457 |
3412 return NAME; | 3458 return NAME; |
3413 } | 3459 } |
3414 | 3460 |
3415 void | 3461 void |
3416 lexical_feedback::init (void) | 3462 lexical_feedback::maybe_warn_separator_insert (char sep) |
3417 { | |
3418 // Not initially defining a matrix list. | |
3419 bracketflag = 0; | |
3420 | |
3421 // Not initially defining a cell array list. | |
3422 braceflag = 0; | |
3423 | |
3424 // Not initially inside a loop or if statement. | |
3425 looping = 0; | |
3426 | |
3427 // Not initially defining a function. | |
3428 defining_func = 0; | |
3429 | |
3430 // Not parsing an object index. | |
3431 while (! parsed_function_name.empty ()) | |
3432 parsed_function_name.pop (); | |
3433 | |
3434 parsing_class_method = false; | |
3435 | |
3436 // Not initially defining a class with classdef. | |
3437 maybe_classdef_get_set_method = false; | |
3438 parsing_classdef = false; | |
3439 parsing_classdef_get_method = false; | |
3440 parsing_classdef_set_method = false; | |
3441 | |
3442 // Not initiallly looking at a function handle. | |
3443 looking_at_function_handle = 0; | |
3444 | |
3445 // Not initiallly looking at an anonymous function argument list. | |
3446 looking_at_anon_fcn_args = 0; | |
3447 | |
3448 // Not parsing a function return, parameter, or declaration list. | |
3449 looking_at_return_list = false; | |
3450 looking_at_parameter_list = false; | |
3451 looking_at_decl_list = false; | |
3452 | |
3453 // Not looking at an argument list initializer expression. | |
3454 looking_at_initializer_expression = false; | |
3455 | |
3456 // Not parsing a matrix or the left hand side of multi-value | |
3457 // assignment statement. | |
3458 looking_at_matrix_or_assign_lhs = false; | |
3459 | |
3460 // Not parsing an object index. | |
3461 while (! looking_at_object_index.empty ()) | |
3462 looking_at_object_index.pop_front (); | |
3463 | |
3464 looking_at_object_index.push_front (false); | |
3465 | |
3466 // Object index not possible until we've seen something. | |
3467 looking_for_object_index = false; | |
3468 | |
3469 // Yes, we are at the beginning of a statement. | |
3470 at_beginning_of_statement = true; | |
3471 | |
3472 // No need to do comma insert or convert spaces to comma at | |
3473 // beginning of input. | |
3474 convert_spaces_to_comma = true; | |
3475 do_comma_insert = false; | |
3476 | |
3477 // Not initially looking at indirect references. | |
3478 looking_at_indirect_ref = false; | |
3479 | |
3480 // Quote marks strings intially. | |
3481 quote_is_transpose = false; | |
3482 | |
3483 // Set of identifiers that might be local variable names is empty. | |
3484 pending_local_variables.clear (); | |
3485 } | |
3486 | |
3487 bool | |
3488 is_keyword (const std::string& s) | |
3489 { | |
3490 // Parsing function names like "set.property_name" inside | |
3491 // classdef-style class definitions is simplified by handling the | |
3492 // "set" and "get" portions of the names using the same mechanism as | |
3493 // is used for keywords. However, they are not really keywords in | |
3494 // the language, so omit them from the list of possible keywords. | |
3495 | |
3496 return (octave_kw_hash::in_word_set (s.c_str (), s.length ()) != 0 | |
3497 && ! (s == "set" || s == "get")); | |
3498 } | |
3499 | |
3500 DEFUN (iskeyword, args, , | |
3501 "-*- texinfo -*-\n\ | |
3502 @deftypefn {Built-in Function} {} iskeyword ()\n\ | |
3503 @deftypefnx {Built-in Function} {} iskeyword (@var{name})\n\ | |
3504 Return true if @var{name} is an Octave keyword. If @var{name}\n\ | |
3505 is omitted, return a list of keywords.\n\ | |
3506 @seealso{isvarname, exist}\n\ | |
3507 @end deftypefn") | |
3508 { | |
3509 octave_value retval; | |
3510 | |
3511 int argc = args.length () + 1; | |
3512 | |
3513 string_vector argv = args.make_argv ("iskeyword"); | |
3514 | |
3515 if (error_state) | |
3516 return retval; | |
3517 | |
3518 if (argc == 1) | |
3519 { | |
3520 // Neither set and get are keywords. See the note in the | |
3521 // is_keyword function for additional details. | |
3522 | |
3523 string_vector lst (TOTAL_KEYWORDS); | |
3524 | |
3525 int j = 0; | |
3526 | |
3527 for (int i = 0; i < TOTAL_KEYWORDS; i++) | |
3528 { | |
3529 std::string tmp = wordlist[i].name; | |
3530 | |
3531 if (! (tmp == "set" || tmp == "get")) | |
3532 lst[j++] = tmp; | |
3533 } | |
3534 | |
3535 lst.resize (j); | |
3536 | |
3537 retval = Cell (lst.sort ()); | |
3538 } | |
3539 else if (argc == 2) | |
3540 { | |
3541 retval = is_keyword (argv[1]); | |
3542 } | |
3543 else | |
3544 print_usage (); | |
3545 | |
3546 return retval; | |
3547 } | |
3548 | |
3549 /* | |
3550 | |
3551 %!assert (iskeyword ("for")) | |
3552 %!assert (iskeyword ("fort"), false) | |
3553 %!assert (iskeyword ("fft"), false) | |
3554 | |
3555 */ | |
3556 | |
3557 void | |
3558 prep_lexer_for_script_file (void) | |
3559 { | |
3560 BEGIN (SCRIPT_FILE_BEGIN); | |
3561 } | |
3562 | |
3563 void | |
3564 prep_lexer_for_function_file (void) | |
3565 { | |
3566 BEGIN (FUNCTION_FILE_BEGIN); | |
3567 } | |
3568 | |
3569 void | |
3570 prep_lexer_for_classdef_file (void) | |
3571 { | |
3572 BEGIN (CLASSDEF_FILE_BEGIN); | |
3573 } | |
3574 | |
3575 static void | |
3576 maybe_warn_separator_insert (char sep) | |
3577 { | 3463 { |
3578 std::string nm = curr_fcn_file_full_name; | 3464 std::string nm = curr_fcn_file_full_name; |
3579 | 3465 |
3580 if (nm.empty ()) | 3466 if (nm.empty ()) |
3581 warning_with_id ("Octave:separator-insert", | 3467 warning_with_id ("Octave:separator-insert", |
3585 warning_with_id ("Octave:separator-insert", | 3471 warning_with_id ("Octave:separator-insert", |
3586 "potential auto-insertion of '%c' near line %d of file %s", | 3472 "potential auto-insertion of '%c' near line %d of file %s", |
3587 sep, input_line_number, nm.c_str ()); | 3473 sep, input_line_number, nm.c_str ()); |
3588 } | 3474 } |
3589 | 3475 |
3590 static void | 3476 void |
3591 gripe_single_quote_string (void) | 3477 lexical_feedback::gripe_single_quote_string (void) |
3592 { | 3478 { |
3593 std::string nm = curr_fcn_file_full_name; | 3479 std::string nm = curr_fcn_file_full_name; |
3594 | 3480 |
3595 if (nm.empty ()) | 3481 if (nm.empty ()) |
3596 warning_with_id ("Octave:single-quote-string", | 3482 warning_with_id ("Octave:single-quote-string", |
3600 warning_with_id ("Octave:single-quote-string", | 3486 warning_with_id ("Octave:single-quote-string", |
3601 "single quote delimited string near line %d of file %s", | 3487 "single quote delimited string near line %d of file %s", |
3602 input_line_number, nm.c_str ()); | 3488 input_line_number, nm.c_str ()); |
3603 } | 3489 } |
3604 | 3490 |
3605 static void | 3491 void |
3606 gripe_matlab_incompatible (const std::string& msg) | 3492 lexical_feedback::gripe_matlab_incompatible (const std::string& msg) |
3607 { | 3493 { |
3608 std::string nm = curr_fcn_file_full_name; | 3494 std::string nm = curr_fcn_file_full_name; |
3609 | 3495 |
3610 if (nm.empty ()) | 3496 if (nm.empty ()) |
3611 warning_with_id ("Octave:matlab-incompatible", | 3497 warning_with_id ("Octave:matlab-incompatible", |
3615 warning_with_id ("Octave:matlab-incompatible", | 3501 warning_with_id ("Octave:matlab-incompatible", |
3616 "potential Matlab compatibility problem: %s near line %d offile %s", | 3502 "potential Matlab compatibility problem: %s near line %d offile %s", |
3617 msg.c_str (), input_line_number, nm.c_str ()); | 3503 msg.c_str (), input_line_number, nm.c_str ()); |
3618 } | 3504 } |
3619 | 3505 |
3620 static void | 3506 void |
3621 maybe_gripe_matlab_incompatible_comment (char c) | 3507 lexical_feedback::maybe_gripe_matlab_incompatible_comment (char c) |
3622 { | 3508 { |
3623 if (c == '#') | 3509 if (c == '#') |
3624 gripe_matlab_incompatible ("# used as comment character"); | 3510 gripe_matlab_incompatible ("# used as comment character"); |
3625 } | 3511 } |
3626 | 3512 |
3627 static void | 3513 void |
3628 gripe_matlab_incompatible_continuation (void) | 3514 lexical_feedback::gripe_matlab_incompatible_continuation (void) |
3629 { | 3515 { |
3630 gripe_matlab_incompatible ("\\ used as line continuation marker"); | 3516 gripe_matlab_incompatible ("\\ used as line continuation marker"); |
3631 } | 3517 } |
3632 | 3518 |
3633 static void | 3519 void |
3634 gripe_matlab_incompatible_operator (const std::string& op) | 3520 lexical_feedback::gripe_matlab_incompatible_operator (const std::string& op) |
3635 { | 3521 { |
3636 std::string t = op; | 3522 std::string t = op; |
3637 int n = t.length (); | 3523 int n = t.length (); |
3638 if (t[n-1] == '\n') | 3524 if (t[n-1] == '\n') |
3639 t.resize (n-1); | 3525 t.resize (n-1); |
3640 gripe_matlab_incompatible (t + " used as operator"); | 3526 gripe_matlab_incompatible (t + " used as operator"); |
3641 } | 3527 } |
3642 | 3528 |
3643 static void | 3529 void |
3644 display_token (int tok) | 3530 lexical_feedback::push_token (token *tok) |
3531 { | |
3532 YYSTYPE *lval = yyget_lval (scanner); | |
3533 lval->tok_val = tok; | |
3534 token_stack.push (tok); | |
3535 } | |
3536 | |
3537 token * | |
3538 lexical_feedback::current_token (void) | |
3539 { | |
3540 YYSTYPE *lval = yyget_lval (scanner); | |
3541 return lval->tok_val; | |
3542 } | |
3543 | |
3544 void | |
3545 lexical_feedback::display_token (int tok) | |
3645 { | 3546 { |
3646 switch (tok) | 3547 switch (tok) |
3647 { | 3548 { |
3648 case '=': std::cerr << "'='\n"; break; | 3549 case '=': std::cerr << "'='\n"; break; |
3649 case ':': std::cerr << "':'\n"; break; | 3550 case ':': std::cerr << "':'\n"; break; |
3691 case POW: std::cerr << "POW\n"; break; | 3592 case POW: std::cerr << "POW\n"; break; |
3692 case EPOW: std::cerr << "EPOW\n"; break; | 3593 case EPOW: std::cerr << "EPOW\n"; break; |
3693 | 3594 |
3694 case NUM: | 3595 case NUM: |
3695 case IMAG_NUM: | 3596 case IMAG_NUM: |
3696 std::cerr << (tok == NUM ? "NUM" : "IMAG_NUM") | 3597 { |
3697 << " [" << yylval.tok_val->number () << "]\n"; | 3598 token *tok_val = current_token (); |
3599 std::cerr << (tok == NUM ? "NUM" : "IMAG_NUM") | |
3600 << " [" << tok_val->number () << "]\n"; | |
3601 } | |
3698 break; | 3602 break; |
3699 | 3603 |
3700 case STRUCT_ELT: | 3604 case STRUCT_ELT: |
3701 std::cerr << "STRUCT_ELT [" << yylval.tok_val->text () << "]\n"; break; | 3605 { |
3606 token *tok_val = current_token (); | |
3607 std::cerr << "STRUCT_ELT [" << tok_val->text () << "]\n"; | |
3608 } | |
3609 break; | |
3702 | 3610 |
3703 case NAME: | 3611 case NAME: |
3704 { | 3612 { |
3705 symbol_table::symbol_record *sr = yylval.tok_val->sym_rec (); | 3613 token *tok_val = current_token (); |
3614 symbol_table::symbol_record *sr = tok_val->sym_rec (); | |
3706 std::cerr << "NAME"; | 3615 std::cerr << "NAME"; |
3707 if (sr) | 3616 if (sr) |
3708 std::cerr << " [" << sr->name () << "]"; | 3617 std::cerr << " [" << sr->name () << "]"; |
3709 std::cerr << "\n"; | 3618 std::cerr << "\n"; |
3710 } | 3619 } |
3712 | 3621 |
3713 case END: std::cerr << "END\n"; break; | 3622 case END: std::cerr << "END\n"; break; |
3714 | 3623 |
3715 case DQ_STRING: | 3624 case DQ_STRING: |
3716 case SQ_STRING: | 3625 case SQ_STRING: |
3717 std::cerr << (tok == DQ_STRING ? "DQ_STRING" : "SQ_STRING") | 3626 { |
3718 << " [" << yylval.tok_val->text () << "]\n"; | 3627 token *tok_val = current_token (); |
3628 | |
3629 std::cerr << (tok == DQ_STRING ? "DQ_STRING" : "SQ_STRING") | |
3630 << " [" << tok_val->text () << "]\n"; | |
3631 } | |
3719 break; | 3632 break; |
3720 | 3633 |
3721 case FOR: std::cerr << "FOR\n"; break; | 3634 case FOR: std::cerr << "FOR\n"; break; |
3722 case WHILE: std::cerr << "WHILE\n"; break; | 3635 case WHILE: std::cerr << "WHILE\n"; break; |
3723 case DO: std::cerr << "DO\n"; break; | 3636 case DO: std::cerr << "DO\n"; break; |
3766 break; | 3679 break; |
3767 } | 3680 } |
3768 } | 3681 } |
3769 | 3682 |
3770 static void | 3683 static void |
3771 display_state (void) | 3684 display_state (int state) |
3772 { | 3685 { |
3773 std::cerr << "S: "; | 3686 std::cerr << "S: "; |
3774 | 3687 |
3775 switch (YY_START) | 3688 switch (state) |
3776 { | 3689 { |
3777 case INITIAL: | 3690 case INITIAL: |
3778 std::cerr << "INITIAL" << std::endl; | 3691 std::cerr << "INITIAL" << std::endl; |
3779 break; | 3692 break; |
3780 | 3693 |
3802 std::cerr << "UNKNOWN START STATE!" << std::endl; | 3715 std::cerr << "UNKNOWN START STATE!" << std::endl; |
3803 break; | 3716 break; |
3804 } | 3717 } |
3805 } | 3718 } |
3806 | 3719 |
3807 static void | 3720 void |
3808 lexer_debug (const char *pattern, const char *text) | 3721 lexical_feedback::fatal_error (const char *msg) |
3809 { | 3722 { |
3723 error (msg); | |
3724 | |
3725 OCTAVE_QUIT; | |
3726 | |
3727 yy_fatal_error (msg, scanner); | |
3728 } | |
3729 | |
3730 void | |
3731 lexical_feedback::lexer_debug (const char *pattern, const char *text) | |
3732 { | |
3733 OCTAVE_YYG; | |
3734 | |
3810 std::cerr << std::endl; | 3735 std::cerr << std::endl; |
3811 | 3736 |
3812 display_state (); | 3737 display_state (YY_START); |
3813 | 3738 |
3814 std::cerr << "P: " << pattern << std::endl; | 3739 std::cerr << "P: " << pattern << std::endl; |
3815 std::cerr << "T: " << text << std::endl; | 3740 std::cerr << "T: " << text << std::endl; |
3816 } | 3741 } |
3817 | |
3818 DEFUN (__display_tokens__, args, nargout, | |
3819 "-*- texinfo -*-\n\ | |
3820 @deftypefn {Built-in Function} {} __display_tokens__ ()\n\ | |
3821 Query or set the internal variable that determines whether Octave's\n\ | |
3822 lexer displays tokens as they are read.\n\ | |
3823 @end deftypefn") | |
3824 { | |
3825 return SET_INTERNAL_VARIABLE (display_tokens); | |
3826 } | |
3827 | |
3828 DEFUN (__token_count__, , , | |
3829 "-*- texinfo -*-\n\ | |
3830 @deftypefn {Built-in Function} {} __token_count__ ()\n\ | |
3831 Number of language tokens processed since Octave startup.\n\ | |
3832 @end deftypefn") | |
3833 { | |
3834 return octave_value (Vtoken_count); | |
3835 } | |
3836 | |
3837 DEFUN (__lexer_debug_flag__, args, nargout, | |
3838 "-*- texinfo -*-\n\ | |
3839 @deftypefn {Built-in Function} {@var{old_val} =} __lexer_debug_flag__ (@var{new_val}))\n\ | |
3840 Undocumented internal function.\n\ | |
3841 @end deftypefn") | |
3842 { | |
3843 octave_value retval; | |
3844 | |
3845 retval = set_internal_variable (lexer_debug_flag, args, nargout, | |
3846 "__lexer_debug_flag__"); | |
3847 | |
3848 return retval; | |
3849 } |