Mercurial > octave
comparison src/lex.l @ 4238:a5a68c0afe56
[project @ 2002-12-25 21:04:33 by jwe]
author | jwe |
---|---|
date | Wed, 25 Dec 2002 21:04:34 +0000 |
parents | 9c8034434982 |
children | 8627d992beb8 |
comparison
equal
deleted
inserted
replaced
4237:9c8034434982 | 4238:a5a68c0afe56 |
---|---|
20 | 20 |
21 */ | 21 */ |
22 | 22 |
23 %s COMMAND_START | 23 %s COMMAND_START |
24 %s MATRIX_START | 24 %s MATRIX_START |
25 %s NESTED_FUNCTION_START | |
25 | 26 |
26 %{ | 27 %{ |
27 #ifdef HAVE_CONFIG_H | 28 #ifdef HAVE_CONFIG_H |
28 #include <config.h> | 29 #include <config.h> |
29 #endif | 30 #endif |
191 | 192 |
192 static void fixup_column_count (char *s); | 193 static void fixup_column_count (char *s); |
193 static void do_comma_insert_check (void); | 194 static void do_comma_insert_check (void); |
194 static int is_plot_keyword (const std::string& s); | 195 static int is_plot_keyword (const std::string& s); |
195 static int is_keyword (const std::string& s); | 196 static int is_keyword (const std::string& s); |
197 static void prep_for_function (void); | |
198 static void prep_for_nested_function (void); | |
196 static std::string plot_style_token (const std::string& s); | 199 static std::string plot_style_token (const std::string& s); |
197 static symbol_record *lookup_identifier (const std::string& s); | 200 static symbol_record *lookup_identifier (const std::string& s); |
198 static void grab_help_text (void); | 201 static void grab_help_text (void); |
199 static bool match_any (char c, const char *s); | 202 static bool match_any (char c, const char *s); |
200 static bool next_token_is_sep_op (void); | 203 static bool next_token_is_sep_op (void); |
236 IDENT ([_a-zA-Z][_a-zA-Z0-9]*) | 239 IDENT ([_a-zA-Z][_a-zA-Z0-9]*) |
237 EXPON ([DdEe][+-]?{D}+) | 240 EXPON ([DdEe][+-]?{D}+) |
238 NUMBER (({D}+\.?{D}*{EXPON}?)|(\.{D}+{EXPON}?)|(0[xX][0-9a-fA-F]+)) | 241 NUMBER (({D}+\.?{D}*{EXPON}?)|(\.{D}+{EXPON}?)|(0[xX][0-9a-fA-F]+)) |
239 %% | 242 %% |
240 | 243 |
244 <NESTED_FUNCTION_START>{} { | |
245 BEGIN 0; | |
246 prep_for_nested_function (); | |
247 return FCN; | |
248 } | |
249 | |
241 %{ | 250 %{ |
242 // Help and other command-style functions are a pain in the ass. This | 251 // Help and other command-style functions are a pain in the ass. This |
243 // stuff needs to be simplified. May require some changes in the | 252 // stuff needs to be simplified. May require some changes in the |
244 // parser too. | 253 // parser too. |
245 %} | 254 %} |
527 // Identifiers. Truncate the token at the first space or tab but | 536 // Identifiers. Truncate the token at the first space or tab but |
528 // don't write directly on yytext. | 537 // don't write directly on yytext. |
529 %} | 538 %} |
530 | 539 |
531 {IDENT}{S}* { | 540 {IDENT}{S}* { |
532 return handle_identifier (); | 541 int id_tok = handle_identifier (); |
542 | |
543 if (id_tok >= 0) | |
544 return id_tok; | |
533 } | 545 } |
534 | 546 |
535 %{ | 547 %{ |
536 // A new line character. New line characters inside matrix constants | 548 // A new line character. New line characters inside matrix constants |
537 // are handled by the <MATRIX_START> start state code above. If closest | 549 // are handled by the <MATRIX_START> start state code above. If closest |
812 // Start off on the right foot. | 824 // Start off on the right foot. |
813 BEGIN 0; | 825 BEGIN 0; |
814 error_state = 0; | 826 error_state = 0; |
815 warning_state = 0; | 827 warning_state = 0; |
816 parser_end_of_input = false; | 828 parser_end_of_input = false; |
817 symtab_context = 0; | 829 end_tokens_expected = 0; |
830 | |
831 while (! symtab_context.empty ()) | |
832 symtab_context.pop (); | |
818 | 833 |
819 // We do want a prompt by default. | 834 // We do want a prompt by default. |
820 promptflag = 1; | 835 promptflag = 1; |
821 | 836 |
822 // Error may have occurred inside some brackets, braces, or parentheses. | 837 // Error may have occurred inside some brackets, braces, or parentheses. |
1044 { | 1059 { |
1045 return 0; | 1060 return 0; |
1046 } | 1061 } |
1047 } | 1062 } |
1048 | 1063 |
1049 // Handle keywords. | 1064 static void |
1065 prep_for_function (void) | |
1066 { | |
1067 end_tokens_expected++; | |
1068 | |
1069 // Prepare for local symbols. | |
1070 | |
1071 tmp_local_sym_tab = new symbol_table (); | |
1072 | |
1073 promptflag--; | |
1074 | |
1075 lexer_flags.defining_func = true; | |
1076 lexer_flags.parsed_function_name = false; | |
1077 lexer_flags.beginning_of_function = true; | |
1078 | |
1079 if (! (reading_fcn_file || reading_script_file)) | |
1080 input_line_number = 1; | |
1081 } | |
1082 | |
1083 static void | |
1084 prep_for_nested_function (void) | |
1085 { | |
1086 lexer_flags.parsing_nested_function = true; | |
1087 prep_for_function (); | |
1088 yylval.tok_val = new token (input_line_number, current_input_column); | |
1089 token_stack.push (yylval.tok_val); | |
1090 } | |
1091 | |
1092 // Handle keywords. Return -1 if the keyword should be ignored. | |
1050 | 1093 |
1051 static int | 1094 static int |
1052 is_keyword (const std::string& s) | 1095 is_keyword (const std::string& s) |
1053 { | 1096 { |
1054 int l = input_line_number; | 1097 int l = input_line_number; |
1109 | 1152 |
1110 case end_kw: | 1153 case end_kw: |
1111 if (lexer_flags.looking_at_object_index) | 1154 if (lexer_flags.looking_at_object_index) |
1112 return 0; | 1155 return 0; |
1113 else | 1156 else |
1114 yylval.tok_val = new token (token::simple_end, l, c); | 1157 { |
1158 if (reading_fcn_file && end_tokens_expected == 1) | |
1159 return -1; | |
1160 else | |
1161 { | |
1162 yylval.tok_val = new token (token::simple_end, l, c); | |
1163 end_tokens_expected--; | |
1164 } | |
1165 } | |
1115 break; | 1166 break; |
1116 | 1167 |
1117 case end_try_catch_kw: | 1168 case end_try_catch_kw: |
1169 end_tokens_expected--; | |
1118 yylval.tok_val = new token (token::try_catch_end, l, c); | 1170 yylval.tok_val = new token (token::try_catch_end, l, c); |
1119 break; | 1171 break; |
1120 | 1172 |
1121 case end_unwind_protect_kw: | 1173 case end_unwind_protect_kw: |
1174 end_tokens_expected--; | |
1122 yylval.tok_val = new token (token::unwind_protect_end, l, c); | 1175 yylval.tok_val = new token (token::unwind_protect_end, l, c); |
1123 break; | 1176 break; |
1124 | 1177 |
1125 case endfor_kw: | 1178 case endfor_kw: |
1179 end_tokens_expected--; | |
1126 yylval.tok_val = new token (token::for_end, l, c); | 1180 yylval.tok_val = new token (token::for_end, l, c); |
1127 break; | 1181 break; |
1128 | 1182 |
1129 case endfunction_kw: | 1183 case endfunction_kw: |
1130 yylval.tok_val = new token (token::function_end, l, c); | 1184 { |
1185 if (reading_fcn_file && end_tokens_expected == 1) | |
1186 return -1; | |
1187 else | |
1188 { | |
1189 yylval.tok_val = new token (token::function_end, l, c); | |
1190 end_tokens_expected--; | |
1191 } | |
1192 } | |
1131 break; | 1193 break; |
1132 | 1194 |
1133 case endif_kw: | 1195 case endif_kw: |
1196 end_tokens_expected--; | |
1134 yylval.tok_val = new token (token::if_end, l, c); | 1197 yylval.tok_val = new token (token::if_end, l, c); |
1135 break; | 1198 break; |
1136 | 1199 |
1137 case endswitch_kw: | 1200 case endswitch_kw: |
1201 end_tokens_expected--; | |
1138 yylval.tok_val = new token (token::switch_end, l, c); | 1202 yylval.tok_val = new token (token::switch_end, l, c); |
1139 break; | 1203 break; |
1140 | 1204 |
1141 case endwhile_kw: | 1205 case endwhile_kw: |
1206 end_tokens_expected--; | |
1142 yylval.tok_val = new token (token::while_end, l, c); | 1207 yylval.tok_val = new token (token::while_end, l, c); |
1143 break; | 1208 break; |
1144 | 1209 |
1145 case do_kw: | |
1146 case for_kw: | 1210 case for_kw: |
1147 case while_kw: | 1211 case while_kw: |
1212 end_tokens_expected++; | |
1213 // Fall through... | |
1214 | |
1215 case do_kw: | |
1148 promptflag--; | 1216 promptflag--; |
1149 lexer_flags.looping++; | 1217 lexer_flags.looping++; |
1150 break; | 1218 break; |
1151 | 1219 |
1152 case if_kw: | 1220 case if_kw: |
1153 case try_kw: | 1221 case try_kw: |
1154 case switch_kw: | 1222 case switch_kw: |
1155 case unwind_protect_kw: | 1223 case unwind_protect_kw: |
1224 end_tokens_expected++; | |
1156 promptflag--; | 1225 promptflag--; |
1157 break; | 1226 break; |
1158 | 1227 |
1159 case gplot_kw: | 1228 case gplot_kw: |
1160 lexer_flags.plotting = true; | 1229 lexer_flags.plotting = true; |
1170 lexer_flags.plotting = true; | 1239 lexer_flags.plotting = true; |
1171 yylval.tok_val = new token (token::replot, l, c); | 1240 yylval.tok_val = new token (token::replot, l, c); |
1172 break; | 1241 break; |
1173 | 1242 |
1174 case function_kw: | 1243 case function_kw: |
1175 if (lexer_flags.defining_func) | 1244 { |
1176 { | 1245 if (lexer_flags.defining_func) |
1177 error ("function keyword invalid within a function body"); | 1246 { |
1178 | 1247 if (reading_fcn_file) |
1179 if ((reading_fcn_file || reading_script_file) | 1248 { |
1180 && ! curr_fcn_file_name.empty ()) | 1249 |
1181 error ("defining new function near line %d of file `%s.m'", | 1250 if (lexer_flags.parsing_nested_function) |
1182 input_line_number, curr_fcn_file_name.c_str ()); | 1251 { |
1183 else | 1252 BEGIN NESTED_FUNCTION_START; |
1184 error ("defining new function near line %d", | 1253 yylval.tok_val = new token (token::function_end, l, c); |
1185 input_line_number); | 1254 } |
1186 | 1255 else |
1187 return LEXICAL_ERROR; | 1256 { |
1188 } | 1257 prep_for_nested_function (); |
1189 else | 1258 return FCN; |
1190 { | 1259 } |
1191 // Prepare for local symbols. | 1260 } |
1192 | 1261 else |
1193 tmp_local_sym_tab = new symbol_table (); | 1262 { |
1194 | 1263 error ("nested functions not implemented in this context"); |
1195 promptflag--; | 1264 |
1196 | 1265 if ((reading_fcn_file || reading_script_file) |
1197 lexer_flags.defining_func = true; | 1266 && ! curr_fcn_file_name.empty ()) |
1198 lexer_flags.parsed_function_name = false; | 1267 error ("near line %d of file `%s.m'", |
1199 lexer_flags.beginning_of_function = true; | 1268 input_line_number, curr_fcn_file_name.c_str ()); |
1200 | 1269 else |
1201 if (! (reading_fcn_file || reading_script_file)) | 1270 error ("near line %d", input_line_number); |
1202 input_line_number = 1; | 1271 |
1203 } | 1272 return LEXICAL_ERROR; |
1273 } | |
1274 } | |
1275 else | |
1276 prep_for_function (); | |
1277 } | |
1204 break; | 1278 break; |
1205 | 1279 |
1206 case magic_file_kw: | 1280 case magic_file_kw: |
1207 { | 1281 { |
1208 if ((reading_fcn_file || reading_script_file) | 1282 if ((reading_fcn_file || reading_script_file) |
1246 // variables occurs when expressions are evaluated. | 1320 // variables occurs when expressions are evaluated. |
1247 | 1321 |
1248 static symbol_record * | 1322 static symbol_record * |
1249 lookup_identifier (const std::string& name) | 1323 lookup_identifier (const std::string& name) |
1250 { | 1324 { |
1251 return curr_sym_tab->lookup (name, true); | 1325 std::string sym_name = name; |
1326 | |
1327 if (curr_sym_tab == fbi_sym_tab | |
1328 && lexer_flags.parsing_nested_function) | |
1329 sym_name = parent_function_name + ":" + sym_name; | |
1330 | |
1331 return curr_sym_tab->lookup (sym_name, true); | |
1252 } | 1332 } |
1253 | 1333 |
1254 static bool | 1334 static bool |
1255 is_variable (const std::string& name) | 1335 is_variable (const std::string& name) |
1256 { | 1336 { |
2241 } | 2321 } |
2242 } | 2322 } |
2243 } | 2323 } |
2244 | 2324 |
2245 // Figure out exactly what kind of token to return when we have seen | 2325 // Figure out exactly what kind of token to return when we have seen |
2246 // an identifier. Handles keywords. | 2326 // an identifier. Handles keywords. Return -1 if the identifier |
2327 // should be ignored. | |
2247 | 2328 |
2248 static int | 2329 static int |
2249 handle_identifier (void) | 2330 handle_identifier (void) |
2250 { | 2331 { |
2251 std::string tok = strip_trailing_whitespace (yytext); | 2332 std::string tok = strip_trailing_whitespace (yytext); |
2293 | 2374 |
2294 int kw_token = is_keyword (tok); | 2375 int kw_token = is_keyword (tok); |
2295 | 2376 |
2296 if (kw_token) | 2377 if (kw_token) |
2297 { | 2378 { |
2298 if (kw_token == STYLE) | 2379 if (kw_token < 0) |
2380 return kw_token; | |
2381 else if (kw_token == STYLE) | |
2299 { | 2382 { |
2300 current_input_column += yyleng; | 2383 current_input_column += yyleng; |
2301 lexer_flags.quote_is_transpose = false; | 2384 lexer_flags.quote_is_transpose = false; |
2302 lexer_flags.convert_spaces_to_comma = true; | 2385 lexer_flags.convert_spaces_to_comma = true; |
2303 return kw_token; | 2386 return kw_token; |
2534 | 2617 |
2535 // Not initially defining a function. | 2618 // Not initially defining a function. |
2536 beginning_of_function = false; | 2619 beginning_of_function = false; |
2537 defining_func = false; | 2620 defining_func = false; |
2538 parsed_function_name = false; | 2621 parsed_function_name = false; |
2622 parsing_nested_function = false; | |
2539 | 2623 |
2540 // Not parsing a function return or parameter list. | 2624 // Not parsing a function return or parameter list. |
2541 looking_at_return_list = false; | 2625 looking_at_return_list = false; |
2542 looking_at_parameter_list = false; | 2626 looking_at_parameter_list = false; |
2543 | 2627 |