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 }