Mercurial > hg > octave-lyh
comparison src/parse.y @ 666:fb4f6556b443
[project @ 1994-09-06 21:22:46 by jwe]
author | jwe |
---|---|
date | Tue, 06 Sep 1994 21:25:14 +0000 |
parents | 739d16c30481 |
children | 1c072f20b522 |
comparison
equal
deleted
inserted
replaced
665:2aeae851a164 | 666:fb4f6556b443 |
---|---|
146 | 146 |
147 // Build a binary expression. | 147 // Build a binary expression. |
148 static tree_expression *make_unary_op (int op, tree_expression *op1, | 148 static tree_expression *make_unary_op (int op, tree_expression *op1, |
149 token *tok_val); | 149 token *tok_val); |
150 | 150 |
151 // Make an expression that handles assignment of multiple values. | |
152 static tree_expression *make_multi_val_ret (tree_expression *rhs, | |
153 int l = -1, int c = -1); | |
154 | |
151 #define ABORT_PARSE \ | 155 #define ABORT_PARSE \ |
152 do \ | 156 do \ |
153 { \ | 157 { \ |
154 global_command = 0; \ | 158 global_command = 0; \ |
155 reset_parser (); \ | 159 reset_parser (); \ |
161 } \ | 165 } \ |
162 while (0) | 166 while (0) |
163 | 167 |
164 %} | 168 %} |
165 | 169 |
166 /* | 170 // Bison declarations. |
167 * Bison declarations. | 171 |
168 */ | |
169 %union | 172 %union |
170 { | 173 { |
171 // The type of the basic tokens returned by the lexer. | 174 // The type of the basic tokens returned by the lexer. |
172 token *tok_val; | 175 token *tok_val; |
173 | 176 |
268 %expect 19 | 271 %expect 19 |
269 | 272 |
270 // Where to start. | 273 // Where to start. |
271 %start input | 274 %start input |
272 | 275 |
273 /* | 276 // Grammar rules. |
274 * Grammar rules. | 277 |
275 */ | |
276 %% | 278 %% |
277 | 279 |
278 input : input1 | 280 input : input1 |
279 { | 281 { |
280 global_command = $1; | 282 global_command = $1; |
687 ; | 689 ; |
688 | 690 |
689 expression : variable '=' expression | 691 expression : variable '=' expression |
690 { $$ = new tree_simple_assignment_expression | 692 { $$ = new tree_simple_assignment_expression |
691 ($1, $3, 0, 0, $2->line (), $2->column ()); } | 693 ($1, $3, 0, 0, $2->line (), $2->column ()); } |
692 | '[' screwed_again matrix_row SCREW_TWO '=' expression | |
693 { | |
694 | |
695 // Will need a way to convert the matrix list to a list of | |
696 // identifiers. If that fails, we can abort here, without losing | |
697 // anything -- no other possible syntax is valid if we've seen the | |
698 // equals sign as the next token after the `]'. | |
699 | |
700 $$ = 0; | |
701 maybe_screwed_again--; | |
702 tree_matrix *tmp = ml.pop (); | |
703 tmp = tmp->reverse (); | |
704 tree_return_list *id_list = tmp->to_return_list (); | |
705 if (id_list) | |
706 { | |
707 $$ = new tree_multi_assignment_expression | |
708 (id_list, $6, $5->line (), $5->column ()); | |
709 } | |
710 else | |
711 { | |
712 yyerror ("parse error"); | |
713 error ("invalid identifier list for assignment"); | |
714 $$ = 0; | |
715 ABORT_PARSE; | |
716 } | |
717 } | |
718 | NUM '=' expression | 694 | NUM '=' expression |
719 { | 695 { |
720 yyerror ("parse error"); | 696 yyerror ("parse error"); |
721 error ("invalid assignment to a number"); | 697 error ("invalid assignment to a number"); |
722 $$ = 0; | 698 $$ = 0; |
723 ABORT_PARSE; | 699 ABORT_PARSE; |
700 } | |
701 | '[' screwed_again matrix_row SCREW_TWO '=' expression | |
702 { | |
703 $$ = make_multi_val_ret ($6, $5->line (), $5->column ()); | |
704 | |
705 if (! $$) | |
706 ABORT_PARSE; | |
724 } | 707 } |
725 | simple_expr | 708 | simple_expr |
726 { $$ = $1; } | 709 { $$ = $1; } |
727 ; | 710 ; |
728 | 711 |
1124 } | 1107 } |
1125 ; | 1108 ; |
1126 | 1109 |
1127 %% | 1110 %% |
1128 | 1111 |
1112 // Generic error messages. | |
1113 | |
1129 static void | 1114 static void |
1130 yyerror (char *s) | 1115 yyerror (char *s) |
1131 { | 1116 { |
1132 char *line = current_input_line; | 1117 char *line = current_input_line; |
1133 int err_col = current_input_column - 1; | 1118 int err_col = current_input_column - 1; |
1163 output_buf << "\n\n"; | 1148 output_buf << "\n\n"; |
1164 | 1149 |
1165 maybe_page_output (output_buf); | 1150 maybe_page_output (output_buf); |
1166 } | 1151 } |
1167 | 1152 |
1153 // Error mesages for mismatched end tokens. | |
1154 | |
1168 static void | 1155 static void |
1169 end_error (char *type, token::end_tok_type ettype, int l, int c) | 1156 end_error (char *type, token::end_tok_type ettype, int l, int c) |
1170 { | 1157 { |
1171 static char *fmt = "%s command matched by `%s' near line %d column %d"; | 1158 static char *fmt = "%s command matched by `%s' near line %d column %d"; |
1172 | 1159 |
1190 default: | 1177 default: |
1191 panic_impossible (); | 1178 panic_impossible (); |
1192 break; | 1179 break; |
1193 } | 1180 } |
1194 } | 1181 } |
1182 | |
1183 // Check to see that end tokens are properly matched. | |
1195 | 1184 |
1196 static int | 1185 static int |
1197 check_end (token *tok, token::end_tok_type expected) | 1186 check_end (token *tok, token::end_tok_type expected) |
1198 { | 1187 { |
1199 token::end_tok_type ettype = tok->ettype (); | 1188 token::end_tok_type ettype = tok->ettype (); |
1226 } | 1215 } |
1227 else | 1216 else |
1228 return 0; | 1217 return 0; |
1229 } | 1218 } |
1230 | 1219 |
1231 /* | 1220 // Try to figure out early if an expression should become an |
1232 * Need to make sure that the expression isn't already an identifier | 1221 // assignment to the builtin variable ans. |
1233 * that has a name, or an assignment expression. | 1222 // |
1234 * | 1223 // Need to make sure that the expression isn't already an identifier |
1235 * Note that an expression can't be just an identifier anymore -- it | 1224 // that has a name, or an assignment expression. |
1236 * must at least be an index expression (see the definition of the | 1225 // |
1237 * non-terminal `variable' above). | 1226 // Note that an expression can't be just an identifier anymore -- it |
1238 * | 1227 // must at least be an index expression (see the definition of the |
1239 * XXX FIXME XXX. This isn't quite sufficient. For example, try the | 1228 // non-terminal `variable' above). |
1240 * command `x = 4, x' for `x' previously undefined. | 1229 // |
1241 * | 1230 // XXX FIXME XXX. This isn't quite sufficient. For example, try the |
1242 * XXX FIXME XXX -- we should probably delay doing this until eval-time. | 1231 // command `x = 4, x' for `x' previously undefined. |
1243 */ | 1232 // |
1233 // XXX FIXME XXX -- we should probably delay doing this until eval-time. | |
1234 | |
1244 static tree_expression * | 1235 static tree_expression * |
1245 maybe_convert_to_ans_assign (tree_expression *expr) | 1236 maybe_convert_to_ans_assign (tree_expression *expr) |
1246 { | 1237 { |
1247 if (expr->is_index_expression ()) | 1238 if (expr->is_index_expression ()) |
1248 { | 1239 { |
1264 | 1255 |
1265 return new tree_simple_assignment_expression (ans, expr, 0, 1); | 1256 return new tree_simple_assignment_expression (ans, expr, 0, 1); |
1266 } | 1257 } |
1267 } | 1258 } |
1268 | 1259 |
1260 // Maybe print a warning if an assignment expression is used as the | |
1261 // test in a logical expression. | |
1262 | |
1269 static void | 1263 static void |
1270 maybe_warn_assign_as_truth_value (tree_expression *expr) | 1264 maybe_warn_assign_as_truth_value (tree_expression *expr) |
1271 { | 1265 { |
1272 if (user_pref.warn_assign_as_truth_value | 1266 if (user_pref.warn_assign_as_truth_value |
1273 && expr->is_assignment_expression () | 1267 && expr->is_assignment_expression () |
1275 { | 1269 { |
1276 warning ("suggest parenthesis around assignment used as truth value"); | 1270 warning ("suggest parenthesis around assignment used as truth value"); |
1277 } | 1271 } |
1278 } | 1272 } |
1279 | 1273 |
1274 // Build a binary expression. | |
1275 | |
1280 static tree_expression * | 1276 static tree_expression * |
1281 make_binary_op (int op, tree_expression *op1, token *tok_val, | 1277 make_binary_op (int op, tree_expression *op1, token *tok_val, |
1282 tree_expression *op2) | 1278 tree_expression *op2) |
1283 { | 1279 { |
1284 tree_expression::type t; | 1280 tree_expression::type t; |
1353 int c = tok_val->column (); | 1349 int c = tok_val->column (); |
1354 | 1350 |
1355 return new tree_binary_expression (op1, op2, t, l, c); | 1351 return new tree_binary_expression (op1, op2, t, l, c); |
1356 } | 1352 } |
1357 | 1353 |
1354 // Build a prefix expression. | |
1355 | |
1358 static tree_expression * | 1356 static tree_expression * |
1359 make_prefix_op (int op, tree_identifier *op1, token *tok_val) | 1357 make_prefix_op (int op, tree_identifier *op1, token *tok_val) |
1360 { | 1358 { |
1361 tree_expression::type t; | 1359 tree_expression::type t; |
1362 switch (op) | 1360 switch (op) |
1376 int c = tok_val->column (); | 1374 int c = tok_val->column (); |
1377 | 1375 |
1378 return new tree_prefix_expression (op1, t, l, c); | 1376 return new tree_prefix_expression (op1, t, l, c); |
1379 } | 1377 } |
1380 | 1378 |
1379 // Build a postfix expression. | |
1380 | |
1381 static tree_expression * | 1381 static tree_expression * |
1382 make_postfix_op (int op, tree_identifier *op1, token *tok_val) | 1382 make_postfix_op (int op, tree_identifier *op1, token *tok_val) |
1383 { | 1383 { |
1384 tree_expression::type t; | 1384 tree_expression::type t; |
1385 switch (op) | 1385 switch (op) |
1399 int c = tok_val->column (); | 1399 int c = tok_val->column (); |
1400 | 1400 |
1401 return new tree_postfix_expression (op1, t, l, c); | 1401 return new tree_postfix_expression (op1, t, l, c); |
1402 } | 1402 } |
1403 | 1403 |
1404 // Build a unary expression. | |
1405 | |
1404 static tree_expression * | 1406 static tree_expression * |
1405 make_unary_op (int op, tree_expression *op1, token *tok_val) | 1407 make_unary_op (int op, tree_expression *op1, token *tok_val) |
1406 { | 1408 { |
1407 tree_expression::type t; | 1409 tree_expression::type t; |
1408 switch (op) | 1410 switch (op) |
1427 int l = tok_val->line (); | 1429 int l = tok_val->line (); |
1428 int c = tok_val->column (); | 1430 int c = tok_val->column (); |
1429 | 1431 |
1430 return new tree_unary_expression (op1, t, l, c); | 1432 return new tree_unary_expression (op1, t, l, c); |
1431 } | 1433 } |
1434 | |
1435 // Make an expression that handles assignment of multiple values. | |
1436 | |
1437 static tree_expression * | |
1438 make_multi_val_ret (tree_expression *rhs, int l, int c) | |
1439 { | |
1440 // Convert the matrix list to a list of identifiers. If that fails, | |
1441 // we can abort here, without losing anything -- no other possible | |
1442 // syntax is valid if we've seen the equals sign as the next token | |
1443 // after the `]'. | |
1444 | |
1445 tree_expression *retval = 0; | |
1446 | |
1447 maybe_screwed_again--; | |
1448 | |
1449 tree_matrix *tmp = ml.pop (); | |
1450 | |
1451 tmp = tmp->reverse (); | |
1452 | |
1453 tree_return_list *id_list = tmp->to_return_list (); | |
1454 | |
1455 if (id_list) | |
1456 { | |
1457 int list_len = id_list->length (); | |
1458 | |
1459 if (list_len == 1) | |
1460 { | |
1461 tree_index_expression *lhs = id_list->remove_front (); | |
1462 retval = new tree_simple_assignment_expression (lhs, rhs, l, c); | |
1463 | |
1464 } | |
1465 else if (list_len > 1) | |
1466 { | |
1467 if (rhs->is_multi_val_ret_expression ()) | |
1468 { | |
1469 tree_multi_val_ret *t = (tree_multi_val_ret *) rhs; | |
1470 retval = new tree_multi_assignment_expression (id_list, t, l, c); | |
1471 } | |
1472 else | |
1473 { | |
1474 yyerror ("parse error"); | |
1475 error ("RHS must be an expression that can return\ | |
1476 multiple values"); | |
1477 } | |
1478 } | |
1479 else | |
1480 panic_impossible (); | |
1481 } | |
1482 else | |
1483 { | |
1484 yyerror ("parse error"); | |
1485 error ("invalid identifier list for assignment"); | |
1486 } | |
1487 | |
1488 return retval; | |
1489 } |