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