diff 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
line wrap: on
line diff
--- a/src/parse.y
+++ b/src/parse.y
@@ -148,6 +148,10 @@
 static tree_expression *make_unary_op (int op, tree_expression *op1,
 				       token *tok_val);
 
+// Make an expression that handles assignment of multiple values.
+static tree_expression *make_multi_val_ret (tree_expression *rhs,
+					    int l = -1, int c = -1);
+
 #define ABORT_PARSE \
   do \
     { \
@@ -163,9 +167,8 @@
 
 %}
 
-/*
- * Bison declarations.
- */
+// Bison declarations.
+
 %union
 {
 // The type of the basic tokens returned by the lexer.
@@ -270,9 +273,8 @@
 // Where to start.
 %start input
 
-/*
- * Grammar rules.
- */
+// Grammar rules.
+
 %%
 
 input		: input1
@@ -689,32 +691,6 @@
 expression	: variable '=' expression
 		  { $$ = new tree_simple_assignment_expression
 		      ($1, $3, 0, 0, $2->line (), $2->column ()); }
-		| '[' screwed_again matrix_row SCREW_TWO '=' expression
-		  {
-
-// Will need a way to convert the matrix list to a list of
-// identifiers.	 If that fails, we can abort here, without losing
-// anything -- no other possible syntax is valid if we've seen the
-// equals sign as the next token after the `]'.
-
-		    $$ = 0;
-		    maybe_screwed_again--;
-		    tree_matrix *tmp = ml.pop ();
-		    tmp = tmp->reverse ();
-		    tree_return_list *id_list = tmp->to_return_list ();
-		    if (id_list)
-		      {
-			$$ = new tree_multi_assignment_expression
-			  (id_list, $6, $5->line (), $5->column ());
-		      }
-		    else
-		      {
-			yyerror ("parse error");
-			error ("invalid identifier list for assignment");
-			$$ = 0;
-			ABORT_PARSE;
-		      }
-		  }
 		| NUM '=' expression
 		  {
 		    yyerror ("parse error");
@@ -722,6 +698,13 @@
 		    $$ = 0;
 		    ABORT_PARSE;
 		  }
+		| '[' screwed_again matrix_row SCREW_TWO '=' expression
+		  {
+		    $$ = make_multi_val_ret ($6, $5->line (), $5->column ());
+
+		    if (! $$)
+		      ABORT_PARSE;
+		  }
 		| simple_expr
 		  { $$ = $1; }
 		;
@@ -1126,6 +1109,8 @@
 
 %%
 
+// Generic error messages.
+
 static void
 yyerror (char *s)
 {
@@ -1165,6 +1150,8 @@
   maybe_page_output (output_buf);
 }
 
+// Error mesages for mismatched end tokens.
+
 static void
 end_error (char *type, token::end_tok_type ettype, int l, int c)
 {
@@ -1193,6 +1180,8 @@
     }
 }
 
+// Check to see that end tokens are properly matched.
+
 static int
 check_end (token *tok, token::end_tok_type expected)
 {
@@ -1228,19 +1217,21 @@
     return 0;
 }
 
-/*
- * Need to make sure that the expression isn't already an identifier
- * that has a name, or an assignment expression.
- *
- * Note that an expression can't be just an identifier anymore -- it
- * must at least be an index expression (see the definition of the
- * non-terminal `variable' above).
- *
- * XXX FIXME XXX.  This isn't quite sufficient.  For example, try the
- * command `x = 4, x' for `x' previously undefined.
- *
- * XXX FIXME XXX -- we should probably delay doing this until eval-time.
- */
+// Try to figure out early if an expression should become an
+// assignment to the builtin variable ans.
+//
+// Need to make sure that the expression isn't already an identifier
+// that has a name, or an assignment expression.
+//
+// Note that an expression can't be just an identifier anymore -- it
+// must at least be an index expression (see the definition of the
+// non-terminal `variable' above).
+//
+// XXX FIXME XXX.  This isn't quite sufficient.  For example, try the
+// command `x = 4, x' for `x' previously undefined.
+//
+// XXX FIXME XXX -- we should probably delay doing this until eval-time.
+
 static tree_expression *
 maybe_convert_to_ans_assign (tree_expression *expr)
 {
@@ -1266,6 +1257,9 @@
     }
 }
 
+// Maybe print a warning if an assignment expression is used as the
+// test in a logical expression.
+
 static void
 maybe_warn_assign_as_truth_value (tree_expression *expr)
 {
@@ -1277,6 +1271,8 @@
     }
 }
 
+// Build a binary expression.
+
 static tree_expression *
 make_binary_op (int op, tree_expression *op1, token *tok_val,
 		tree_expression *op2)
@@ -1355,6 +1351,8 @@
   return new tree_binary_expression (op1, op2, t, l, c);
 }
 
+// Build a prefix expression.
+
 static tree_expression *
 make_prefix_op (int op, tree_identifier *op1, token *tok_val)
 {
@@ -1378,6 +1376,8 @@
   return new tree_prefix_expression (op1, t, l, c);
 }
 
+// Build a postfix expression.
+
 static tree_expression *
 make_postfix_op (int op, tree_identifier *op1, token *tok_val)
 {
@@ -1401,6 +1401,8 @@
   return new tree_postfix_expression (op1, t, l, c);
 }
 
+// Build a unary expression.
+
 static tree_expression *
 make_unary_op (int op, tree_expression *op1, token *tok_val)
 {
@@ -1429,3 +1431,59 @@
 
   return new tree_unary_expression (op1, t, l, c);
 }
+
+// Make an expression that handles assignment of multiple values.
+
+static tree_expression *
+make_multi_val_ret (tree_expression *rhs, int l, int c) 
+{
+// Convert the matrix list to a list of identifiers.  If that fails,
+// we can abort here, without losing anything -- no other possible
+// syntax is valid if we've seen the equals sign as the next token
+// after the `]'. 
+
+  tree_expression *retval = 0;
+
+  maybe_screwed_again--;
+
+  tree_matrix *tmp = ml.pop ();
+
+  tmp = tmp->reverse ();
+
+  tree_return_list *id_list = tmp->to_return_list ();
+
+  if (id_list)
+    {
+      int list_len = id_list->length ();
+
+      if (list_len == 1)
+	{
+	  tree_index_expression *lhs = id_list->remove_front ();
+	  retval = new tree_simple_assignment_expression (lhs, rhs, l, c);
+	  
+	}
+      else if (list_len > 1)
+	{
+	  if (rhs->is_multi_val_ret_expression ())
+	    {
+	      tree_multi_val_ret *t = (tree_multi_val_ret *) rhs;
+	      retval = new tree_multi_assignment_expression (id_list, t, l, c);
+	    }
+	  else
+	    {
+	      yyerror ("parse error");
+	      error ("RHS must be an expression that can return\
+ multiple values");
+	    }
+	}
+      else
+	panic_impossible ();
+    }
+  else
+    {
+      yyerror ("parse error");
+      error ("invalid identifier list for assignment");
+    }
+
+  return retval;
+}