home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / octave-1.1.1p1-src.tgz / tar.out / fsf / octave / src / parse.y < prev    next >
Text File  |  1996-09-28  |  37KB  |  1,624 lines

  1. /* parse.y                        -*- text -*-
  2.  
  3. Copyright (C) 1992, 1993, 1994, 1995 John W. Eaton
  4.  
  5. This file is part of Octave.
  6.  
  7. Octave is free software; you can redistribute it and/or modify it
  8. under the terms of the GNU General Public License as published by the
  9. Free Software Foundation; either version 2, or (at your option) any
  10. later version.
  11.  
  12. Octave is distributed in the hope that it will be useful, but WITHOUT
  13. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15. for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with Octave; see the file COPYING.  If not, write to the Free
  19. Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  
  21. */
  22.  
  23. // Parser for Octave.
  24.  
  25. // C decarations.
  26.  
  27. %{
  28. #define YYDEBUG 1
  29.  
  30. #ifdef HAVE_CONFIG_H
  31. #include "config.h"
  32. #endif
  33.  
  34. #include <strstream.h>
  35.  
  36. #include "SLStack.h"
  37.  
  38. #include "Matrix.h"
  39.  
  40. #include "octave-hist.h"
  41. #include "user-prefs.h"
  42. #include "tree-base.h"
  43. #include "tree-expr.h"
  44. #include "tree-cmd.h"
  45. #include "tree-const.h"
  46. #include "tree-misc.h"
  47. #include "variables.h"
  48. #include "tree-plot.h"
  49. #include "octave.h"
  50. #include "symtab.h"
  51. #include "parse.h"
  52. #include "token.h"
  53. #include "error.h"
  54. #include "pager.h"
  55. #include "input.h"
  56. #include "utils.h"
  57. #include "lex.h"
  58.  
  59. // Nonzero means we're in the middle of defining a function.
  60. int defining_func = 0;
  61.  
  62. // Nonzero means we're in the middle of defining a loop.
  63. int looping = 0;
  64.  
  65. // Nonzero means we're in the middle of defining a conditional expression.
  66. int iffing = 0;
  67.  
  68. // Nonzero means we need to do some extra lookahead to avoid being
  69. // screwed by bogus function syntax.
  70. int maybe_screwed = 0;
  71.  
  72. // Nonzero means we need to do some extra lookahead to avoid being
  73. // screwed by bogus function syntax.
  74. int maybe_screwed_again = 0;
  75.  
  76. // Temporary symbol table pointer used to cope with bogus function syntax.
  77. symbol_table *tmp_local_sym_tab = 0;
  78.  
  79. // Stack to hold list of literal matrices.
  80. SLStack <tree_matrix *> ml;
  81.  
  82. // A nonzero element corresponding to an element of ml means we just
  83. // started reading a new matrix.  This should probably be part of a
  84. // new struct for matrix lists... 
  85. SLStack <int> mlnm;
  86.  
  87. // The current input line number.
  88. int input_line_number = 0;
  89.  
  90. // The column of the current token.
  91. int current_input_column = 1;
  92.  
  93. // Buffer for help text snagged from function files.
  94. char *help_buf = 0;
  95.  
  96. // Nonzero means we're working on a plot command.
  97. int plotting = 0;
  98.  
  99. // Nonzero means we've seen something that means we must be past the
  100. // range part of a plot command.
  101. int past_plot_range = 0;
  102.  
  103. // Nonzero means we're looking at the range part of a plot command.
  104. int in_plot_range = 0;
  105.  
  106. // Nonzero means we're looking at the using part of a plot command.
  107. int in_plot_using = 0;
  108.  
  109. // Nonzero means we're looking at the style part of a plot command.
  110. int in_plot_style = 0;
  111.  
  112. // Nonzero means we're looking at an indirect reference to a structure
  113. // element.
  114. int looking_at_indirect_ref = 0;
  115.  
  116. // Forward declarations for some functions defined at the bottom of
  117. // the file.
  118.  
  119. // Generic error messages.
  120. static void yyerror (char *s);
  121.  
  122. // Error mesages for mismatched end tokens.
  123. static void end_error (char *type, token::end_tok_type ettype, int l, int c);
  124.  
  125. // Check to see that end tokens are properly matched.
  126. static int check_end (token *tok, token::end_tok_type expected);
  127.  
  128. // Try to figure out early if an expression should become an
  129. // assignment to the builtin variable ans.
  130. static tree_expression *maybe_convert_to_ans_assign (tree_expression *expr);
  131.  
  132. // Maybe print a warning if an assignment expression is used as the
  133. // test in a logical expression.
  134. static void maybe_warn_assign_as_truth_value (tree_expression *expr);
  135.  
  136. // Build a binary expression.
  137. static tree_expression *make_binary_op
  138.      (int op, tree_expression *op1,    token *tok_val, tree_expression *op2);
  139.  
  140. // Build a prefix expression.
  141. static tree_expression *make_prefix_op
  142.      (int op, tree_identifier *op1, token *tok_val);
  143.  
  144. // Build a postfix expression.
  145. static tree_expression *make_postfix_op
  146.      (int op, tree_identifier *op1, token *tok_val);
  147.  
  148. // Build a binary expression.
  149. static tree_expression *make_unary_op
  150.      (int op, tree_expression *op1, token *tok_val);
  151.  
  152. // Make an expression that handles assignment of multiple values.
  153. static tree_expression *make_multi_val_ret
  154.      (tree_expression *rhs, int l = -1, int c = -1);
  155.  
  156. // Make an index expression.
  157. static tree_index_expression *make_index_expression
  158.      (tree_indirect_ref *indir, tree_argument_list *args);
  159.  
  160. #define ABORT_PARSE \
  161.   do \
  162.     { \
  163.       global_command = 0; \
  164.       yyerrok; \
  165.       if (interactive) \
  166.     YYACCEPT; \
  167.       else \
  168.     YYABORT; \
  169.     } \
  170.   while (0)
  171.  
  172. %}
  173.  
  174. // Bison declarations.
  175.  
  176. %union
  177. {
  178. // The type of the basic tokens returned by the lexer.
  179.   token *tok_val;
  180.  
  181. // Types for the nonterminals we generate.
  182.   tree *tree_type;
  183.   tree_expression *tree_expression_type;
  184.   tree_constant *tree_constant_type;
  185.   tree_matrix *tree_matrix_type;
  186.   tree_identifier *tree_identifier_type;
  187.   tree_indirect_ref *tree_indirect_ref_type;
  188.   tree_function *tree_function_type;
  189.   tree_index_expression *tree_index_expression_type;
  190.   tree_colon_expression *tree_colon_expression_type;
  191.   tree_argument_list *tree_argument_list_type;
  192.   tree_parameter_list *tree_parameter_list_type;
  193.   tree_command *tree_command_type;
  194.   tree_if_command *tree_if_command_type;
  195.   tree_if_clause *tree_if_clause_type;
  196.   tree_if_command_list *tree_if_command_list_type;
  197.   tree_global *tree_global_type;
  198.   tree_global_init_list *tree_global_init_list_type;
  199.   tree_global_command *tree_global_command_type;
  200.   tree_statement *tree_statement_type;
  201.   tree_statement_list *tree_statement_list_type;
  202.   tree_plot_command *tree_plot_command_type;
  203.   subplot *subplot_type;
  204.   subplot_list *subplot_list_type;
  205.   plot_limits *plot_limits_type;
  206.   plot_range *plot_range_type;
  207.   subplot_using *subplot_using_type;
  208.   subplot_style *subplot_style_type;
  209. }
  210.  
  211. // Tokens with line and column information.
  212. %token <tok_val> '=' ':' '-' '+' '*' '/'
  213. %token <tok_val> EXPR_AND_AND EXPR_OR_OR
  214. %token <tok_val> EXPR_AND EXPR_OR EXPR_NOT
  215. %token <tok_val> EXPR_LT EXPR_LE EXPR_EQ EXPR_NE EXPR_GE EXPR_GT
  216. %token <tok_val> LEFTDIV EMUL EDIV ELEFTDIV QUOTE TRANSPOSE
  217. %token <tok_val> PLUS_PLUS MINUS_MINUS POW EPOW
  218. %token <tok_val> NUM IMAG_NUM
  219. %token <tok_val> NAME SCREW
  220. %token <tok_val> END
  221. %token <tok_val> PLOT
  222. %token <tok_val> TEXT STYLE
  223. %token <tok_val> FOR WHILE IF ELSEIF ELSE BREAK CONTINUE FUNC_RET
  224. %token <tok_val> UNWIND CLEANUP
  225. %token <tok_val> GLOBAL
  226. %token <tok_val> TEXT_ID
  227.  
  228. // Other tokens.
  229. %token LEXICAL_ERROR
  230. %token FCN SCREW_TWO
  231. %token ELLIPSIS
  232. %token ALL_VA_ARGS
  233. %token END_OF_INPUT
  234. %token USING TITLE WITH COLON OPEN_BRACE CLOSE_BRACE CLEAR
  235.  
  236. // Nonterminals we construct.
  237. %type <tree_type> input
  238. %type <tree_expression_type> expression simple_expr simple_expr1
  239. %type <tree_expression_type> ans_expression title
  240. %type <tree_matrix_type> matrix
  241. %type <tree_identifier_type> identifier
  242. %type <tree_indirect_ref_type> indirect_ref indirect_ref1
  243. %type <tree_function_type> func_def1 func_def2 func_def3
  244. %type <tree_index_expression_type> variable word_list_cmd
  245. %type <tree_colon_expression_type> colon_expr
  246. %type <tree_argument_list_type> arg_list word_list
  247. %type <tree_parameter_list_type> param_list param_list1
  248. %type <tree_parameter_list_type> return_list return_list1
  249. %type <tree_command_type> command func_def
  250. %type <tree_if_command_type> if_command
  251. %type <tree_if_clause_type> elseif_clause else_clause
  252. %type <tree_if_command_list_type> if_cmd_list1 if_cmd_list
  253. %type <tree_global_type> global_decl2
  254. %type <tree_global_init_list_type> global_decl1
  255. %type <tree_global_command_type> global_decl
  256. %type <tree_statement_type> statement
  257. %type <tree_statement_list_type> simple_list simple_list1 list list1
  258. %type <tree_statement_list_type> opt_list input1
  259. %type <tree_plot_command_type> plot_command 
  260. %type <subplot_type> plot_command2 plot_options
  261. %type <subplot_list_type> plot_command1
  262. %type <plot_limits_type> ranges
  263. %type <plot_range_type> ranges1 
  264. %type <subplot_using_type> using using1 
  265. %type <subplot_style_type> style
  266.  
  267. // Precedence and associativity.
  268. %left ';' ',' '\n'
  269. %right '='
  270. %left EXPR_AND_AND EXPR_OR_OR
  271. %left EXPR_AND EXPR_OR
  272. %left EXPR_LT EXPR_LE EXPR_EQ EXPR_NE EXPR_GE EXPR_GT
  273. %left ':'
  274. %left '-' '+'
  275. %left '*' '/' LEFTDIV EMUL EDIV ELEFTDIV
  276. %left QUOTE TRANSPOSE
  277. %left UNARY PLUS_PLUS MINUS_MINUS EXPR_NOT
  278. %right POW EPOW
  279.  
  280. // There are 19 shift/reduce conflicts, ok?
  281. %expect 19
  282.  
  283. // Where to start.
  284. %start input
  285.  
  286. // Grammar rules.
  287.  
  288. %%
  289.  
  290. input        : input1
  291.           {
  292.             global_command = $1;
  293.             promptflag = 1;
  294.             YYACCEPT;
  295.           }
  296.         | END_OF_INPUT
  297.           {
  298.             global_command = 0;
  299.             promptflag = 1;
  300.             YYABORT;
  301.           }
  302.         | simple_list parse_error
  303.           { ABORT_PARSE; }
  304.         | parse_error
  305.           { ABORT_PARSE; }
  306.         ;
  307.  
  308. input1        : '\n'
  309.           { $$ = 0; }
  310.         | simple_list
  311.           { $$ = $1; }
  312.         | simple_list '\n'
  313.           { $$ = $1; }
  314.         | simple_list END_OF_INPUT
  315.           { $$ = $1; }
  316.         ;
  317.  
  318. parse_error    : LEXICAL_ERROR
  319.           { yyerror ("parse error"); }
  320.         | error
  321.         ;
  322.  
  323. simple_list    : semi_comma
  324.           { $$ = 0; }
  325.         | comma_semi
  326.           { $$ = 0; }
  327.         | simple_list1
  328.           { $$ = $1; }
  329.         | simple_list1 semi_comma
  330.           {
  331.             tree_statement *tmp = $1->rear ();
  332.             tmp->set_print_flag (0);
  333.           }
  334.         | simple_list1 comma_semi
  335.           { $$ = $1; }
  336.         ;
  337.  
  338. simple_list1    : statement
  339.           { $$ = new tree_statement_list ($1); }
  340.         | semi_comma statement
  341.           { $$ = new tree_statement_list ($2); }
  342.         | comma_semi statement
  343.           { $$ = new tree_statement_list ($2); }
  344.         | simple_list1 semi_comma statement
  345.           {
  346.             tree_statement *tmp = $1->rear ();
  347.             tmp->set_print_flag (0);
  348.             $1->append ($3);
  349.           }
  350.         | simple_list1 comma_semi statement
  351.           { $1->append ($3); }
  352.         ;
  353.  
  354. semi_comma    : ';'
  355.         | semi_comma ','
  356.         | semi_comma ';'
  357.         ;
  358.  
  359. comma_semi    : ','
  360.         | comma_semi ';'
  361.         | comma_semi ','
  362.         ;
  363.  
  364. comma_nl_sep    : ','
  365.         | '\n'
  366.         | comma_nl_sep sep
  367.         ;
  368.  
  369. semi_sep    : ';'
  370.         | semi_sep sep
  371.         ;
  372.  
  373. opt_list    : // empty
  374.           { $$ = new tree_statement_list (); }
  375.         | list
  376.           { $$ = $1; }
  377.         ;
  378.  
  379. list        : list1
  380.           { $$ = $1; }
  381.         | list1 comma_nl_sep
  382.           { $$ = $1; }
  383.         | list1 semi_sep
  384.           {
  385.             tree_statement *tmp = $1->rear ();
  386.             tmp->set_print_flag (0);
  387.           }
  388.         ;
  389.  
  390. list1        : statement
  391.           {
  392.             beginning_of_function = 0;
  393.             $$ = new tree_statement_list ($1);
  394.           }
  395.         | list1 comma_nl_sep statement
  396.           { $1->append ($3); }
  397.         | list1 semi_sep statement
  398.           {
  399.             tree_statement *tmp = $1->rear ();
  400.             tmp->set_print_flag (0);
  401.             $1->append ($3);
  402.           }
  403.         ;
  404.  
  405. statement    : command
  406.           { $$ = new tree_statement ($1); }
  407.         | ans_expression
  408.           { $$ = new tree_statement ($1); }
  409.         | PLOT CLEAR
  410.           {
  411.             symbol_record *sr = lookup_by_name ("clearplot", 0);
  412.             tree_identifier *id = new tree_identifier (sr);
  413.             $$ = new tree_statement (id);
  414.           }
  415.         ;
  416.  
  417. plot_command    : PLOT plot_command1
  418.           {
  419.             if (! $2 && $1->pttype () != token::replot)
  420.               {
  421.             yyerror ("must have something to plot");
  422.             ABORT_PARSE;
  423.               }
  424.             else
  425.               {
  426.             $$ = new tree_plot_command ($2, $1->pttype ());
  427.             plotting = 0;
  428.             past_plot_range = 0;
  429.             in_plot_range = 0;
  430.             in_plot_using = 0;
  431.             in_plot_style = 0;
  432.               }
  433.           }
  434.         | PLOT ranges plot_command1
  435.           {
  436.             if ($1->pttype () == token::replot)
  437.               {
  438.             yyerror ("cannot specify new ranges with replot");
  439.             ABORT_PARSE;
  440.               }
  441.             else
  442.               {
  443.             $$ = new tree_plot_command ($3, $2, $1->pttype ());
  444.             plotting = 0;
  445.             past_plot_range = 0;
  446.             in_plot_range = 0;
  447.             in_plot_using = 0;
  448.             in_plot_style = 0;
  449.               }
  450.           }
  451.         ;
  452.  
  453. ranges        : ranges1
  454.           { $$ = new plot_limits ($1); }
  455.         | ranges1 ranges1
  456.           { $$ = new plot_limits ($1, $2); }
  457.         | ranges1 ranges1 ranges1
  458.           { $$ = new plot_limits ($1, $2, $3); }
  459.         ;
  460.  
  461. ranges1        : OPEN_BRACE expression COLON expression CLOSE_BRACE
  462.           { $$ = new plot_range ($2, $4); }
  463.         | OPEN_BRACE COLON expression CLOSE_BRACE
  464.           { $$ = new plot_range (0, $3); }
  465.         | OPEN_BRACE expression COLON CLOSE_BRACE
  466.           { $$ = new plot_range ($2, 0); }
  467.         | OPEN_BRACE COLON CLOSE_BRACE
  468.           { $$ = new plot_range (); }
  469.         | OPEN_BRACE CLOSE_BRACE
  470.           { $$ = new plot_range (); }
  471.         ;
  472.  
  473. plot_command1    : // empty
  474.           { $$ = 0; }
  475.         | plot_command2
  476.           { $$ = new subplot_list ($1); }
  477.         | plot_command1 ',' plot_command2
  478.           { $1->append ($3); }
  479.         ;
  480.  
  481. plot_command2    : expression
  482.           { $$ = new subplot ($1); }
  483.         | expression plot_options
  484.           {
  485.             $2->set_data ($1);
  486.             $$ = $2;
  487.           }
  488.         ;
  489.  
  490. plot_options    : using
  491.           { $$ = new subplot ($1, 0, 0); }
  492.         | title
  493.           { $$ = new subplot (0, $1, 0); }
  494.         | style
  495.           { $$ = new subplot (0, 0, $1); }
  496.         | using title
  497.           { $$ = new subplot ($1, $2, 0); }
  498.         | title using         
  499.           { $$ = new subplot ($2, $1, 0); }
  500.         | using style         
  501.           { $$ = new subplot ($1, 0, $2); }
  502.         | style using         
  503.           { $$ = new subplot ($2, 0, $1); }
  504.         | title style         
  505.           { $$ = new subplot (0, $1, $2); }
  506.         | style title         
  507.           { $$ = new subplot (0, $2, $1); }
  508.         | using title style     
  509.           { $$ = new subplot ($1, $2, $3); }
  510.         | using style title     
  511.           { $$ = new subplot ($1, $3, $2); }
  512.         | title using style     
  513.           { $$ = new subplot ($2, $1, $3); }
  514.         | title style using     
  515.           { $$ = new subplot ($3, $1, $2); }
  516.         | style using title     
  517.           { $$ = new subplot ($2, $3, $1); }
  518.         | style title using     
  519.           { $$ = new subplot ($3, $2, $1); }
  520.         ;
  521.  
  522. using        : using1
  523.           {
  524.             in_plot_using = 0;
  525.             $$ = $1;
  526.           }
  527.         | using1 expression
  528.           {
  529.             in_plot_using = 0;
  530.             $$ = $1->set_format ($2);
  531.           }
  532.         ;
  533.  
  534. using1        : USING expression
  535.           {
  536.             subplot_using *tmp = new subplot_using ();
  537.             $$ = tmp->add_qualifier ($2);
  538.           }
  539.         | using1 COLON expression
  540.           { $$ = $1->add_qualifier ($3); }
  541.         ;
  542.  
  543. title        : TITLE expression
  544.           { $$ = $2; }
  545.         ;
  546.  
  547. style        : WITH STYLE
  548.           { $$ = new subplot_style ($2->string ()); }
  549.         | WITH STYLE expression
  550.           { $$ = new subplot_style ($2->string (), $3); }
  551.         | WITH STYLE expression bogus_syntax expression
  552.           { $$ = new subplot_style ($2->string (), $3, $5); }
  553.         ;
  554.  
  555. bogus_syntax    : // empty
  556.         ;
  557.  
  558. ans_expression    : expression
  559.           { $$ = maybe_convert_to_ans_assign ($1); }
  560.         ;
  561.  
  562. global_decl    : GLOBAL global_decl1
  563.           {
  564.             $$ = new tree_global_command ($2, $1->line (),
  565.                           $1->column ());
  566.           }
  567.         ;
  568.  
  569. global_decl1    : global_decl2
  570.           { $$ = new tree_global_init_list ($1); }
  571.         | global_decl1 optcomma global_decl2
  572.           { $1->append ($3); }
  573.  
  574. global_decl2    : identifier
  575.           { $$ = new tree_global ($1); }
  576.         | identifier '=' expression
  577.           {
  578.             tree_simple_assignment_expression *tmp_ass;
  579.             tmp_ass = new tree_simple_assignment_expression
  580.               ($1, $3, 0, 0, $2->line (), $2->column ());
  581.             $$ = new tree_global (tmp_ass);
  582.           }
  583.         ;
  584.  
  585. optcomma    : // empty
  586.         | ','
  587.           {
  588.             if (user_pref.warn_comma_in_global_decl)
  589.               warning ("comma in global declaration not\
  590.  interpreted as a command separator");
  591.           }
  592.         ;
  593.  
  594. command        : plot_command
  595.           { $$ = $1; }
  596.         | func_def
  597.           { $$ = $1; }
  598.         | global_decl
  599.           { $$ = $1; }
  600.         | if_command
  601.           {
  602.             iffing--;
  603.             $$ = $1;
  604.           }
  605.  
  606.         | UNWIND optsep opt_list CLEANUP optsep opt_list END
  607.           {
  608.             if (check_end ($7, token::unwind_protect_end))
  609.               ABORT_PARSE;
  610.  
  611.             $$ = new tree_unwind_protect_command ($3, $6, $1->line (),
  612.                               $1->column ());
  613.           }
  614.         | WHILE expression optsep opt_list END
  615.           {
  616.             maybe_warn_assign_as_truth_value ($2);
  617.             if (check_end ($5, token::while_end))
  618.               ABORT_PARSE;
  619.             looping--;
  620.             $$ = new tree_while_command ($2, $4, $1->line (),
  621.                          $1->column ());
  622.           }
  623.         | FOR variable '=' expression optsep opt_list END
  624.           {
  625.             if (check_end ($7, token::for_end))
  626.               ABORT_PARSE;
  627.             looping--;
  628.             $$ = new tree_for_command ($2, $4, $6,
  629.                            $1->line (), $1->column ());
  630.           }
  631.         | BREAK
  632.           {
  633.             if (! (looping || defining_func))
  634.               {
  635.             yyerror ("break: only meaningful within a loop\
  636.  or function body");
  637.             ABORT_PARSE;
  638.               }
  639.             $$ = new tree_break_command ($1->line (), $1->column ());
  640.           }
  641.         | CONTINUE
  642.           {
  643.             if (! looping)
  644.               {
  645.             yyerror ("continue: only meaningful within a\
  646.  `for' or `while' loop");
  647.             ABORT_PARSE;
  648.               }
  649.             $$ = new tree_continue_command ($1->line (),
  650.                             $1->column ());
  651.           }
  652.         | FUNC_RET
  653.           {
  654.             if (! defining_func)
  655.               {
  656.             yyerror ("return: only meaningful within a function");
  657.             ABORT_PARSE;
  658.               }
  659.             $$ = new tree_return_command ($1->line (), $1->column ());
  660.           }
  661.         ;
  662.  
  663. if_command    : IF if_cmd_list END
  664.           {
  665.             if (check_end ($3, token::if_end))
  666.               ABORT_PARSE;
  667.             $$ = new tree_if_command ($2, $1->line (), $1->column ());
  668.           }
  669.         ;
  670.  
  671. if_cmd_list    : if_cmd_list1
  672.           { $$ = $1 }
  673.         | if_cmd_list1 else_clause
  674.           { $1->append ($2); }
  675.         ;
  676.  
  677. if_cmd_list1    : expression optsep opt_list
  678.           {
  679.             maybe_warn_assign_as_truth_value ($1);
  680.             tree_if_clause *t = new tree_if_clause ($1, $3);
  681.             $$ = new tree_if_command_list (t);
  682.           }
  683.         | if_cmd_list1 elseif_clause
  684.           { $1->append ($2); }
  685.         ;
  686.  
  687. elseif_clause    : ELSEIF optsep expression optsep opt_list
  688.           {
  689.             maybe_warn_assign_as_truth_value ($3);
  690.             $$ = new tree_if_clause ($3, $5);
  691.           }
  692.         ;
  693.  
  694. else_clause    : ELSE optsep opt_list
  695.           { $$ = new tree_if_clause ($3); }
  696.         ;
  697.  
  698. optsep        : // empty
  699.         | sep
  700.         ;
  701.  
  702. sep        : ','
  703.         | ';'
  704.         | '\n'
  705.         | sep ','
  706.         | sep ';'
  707.         | sep '\n'
  708.         ;
  709.  
  710. screwed_again    : // empty
  711.           { maybe_screwed_again++; }
  712.         ;
  713.  
  714. expression    : variable '=' expression
  715.           { $$ = new tree_simple_assignment_expression
  716.               ($1, $3, 0, 0, $2->line (), $2->column ()); }
  717.         | NUM '=' expression
  718.           {
  719.             yyerror ("invalid assignment to a number");
  720.             $$ = 0;
  721.             ABORT_PARSE;
  722.           }
  723.         | '[' screwed_again matrix_row SCREW_TWO '=' expression
  724.           {
  725.             $$ = make_multi_val_ret ($6, $5->line (), $5->column ());
  726.  
  727.             if (! $$)
  728.               ABORT_PARSE;
  729.           }
  730.         | simple_expr
  731.           { $$ = $1; }
  732.         ;
  733.  
  734. simple_expr    : simple_expr1
  735.           { $$ = $1; }
  736.         | identifier PLUS_PLUS
  737.           { $$ = make_postfix_op (PLUS_PLUS, $1, $2); }
  738.         | identifier MINUS_MINUS
  739.           { $$ = make_postfix_op (MINUS_MINUS, $1, $2); }
  740.         | simple_expr QUOTE
  741.           { $$ = make_unary_op (QUOTE, $1, $2); }
  742.         | simple_expr TRANSPOSE
  743.           { $$ = make_unary_op (TRANSPOSE, $1, $2); }
  744.         | simple_expr POW simple_expr
  745.           { $$ = make_binary_op (POW, $1, $2, $3); }
  746.         | simple_expr EPOW simple_expr
  747.           { $$ = make_binary_op (EPOW, $1, $2, $3); }
  748.         | simple_expr '+' simple_expr
  749.           { $$ = make_binary_op ('+', $1, $2, $3); }
  750.         | simple_expr '-' simple_expr
  751.           { $$ = make_binary_op ('-', $1, $2, $3); }
  752.         | simple_expr '*' simple_expr
  753.           { $$ = make_binary_op ('*', $1, $2, $3); }
  754.         | simple_expr '/' simple_expr
  755.           { $$ = make_binary_op ('/', $1, $2, $3); }
  756.         | simple_expr EMUL simple_expr
  757.           { $$ = make_binary_op (EMUL, $1, $2, $3); }
  758.         | simple_expr EDIV simple_expr
  759.           { $$ = make_binary_op (EDIV, $1, $2, $3); }
  760.         | simple_expr LEFTDIV simple_expr
  761.           { $$ = make_binary_op (LEFTDIV, $1, $2, $3); }
  762.         | simple_expr ELEFTDIV simple_expr
  763.           { $$ = make_binary_op (ELEFTDIV, $1, $2, $3); }
  764.         | simple_expr EXPR_LT simple_expr
  765.           { $$ = make_binary_op (EXPR_LT, $1, $2, $3); }
  766.         | simple_expr EXPR_LE simple_expr
  767.           { $$ = make_binary_op (EXPR_LE, $1, $2, $3); }
  768.         | simple_expr EXPR_EQ simple_expr
  769.           { $$ = make_binary_op (EXPR_EQ, $1, $2, $3); }
  770.         | simple_expr EXPR_GE simple_expr
  771.           { $$ = make_binary_op (EXPR_GE, $1, $2, $3); }
  772.         | simple_expr EXPR_GT simple_expr
  773.           { $$ = make_binary_op (EXPR_GT, $1, $2, $3); }
  774.         | simple_expr EXPR_NE simple_expr
  775.           { $$ = make_binary_op (EXPR_NE, $1, $2, $3); }
  776.         | simple_expr EXPR_AND_AND simple_expr
  777.           { $$ = make_binary_op (EXPR_AND_AND, $1, $2, $3); }
  778.         | simple_expr EXPR_OR_OR simple_expr
  779.           { $$ = make_binary_op (EXPR_OR_OR, $1, $2, $3); }
  780.         | simple_expr EXPR_AND simple_expr
  781.           { $$ = make_binary_op (EXPR_AND, $1, $2, $3); }
  782.         | simple_expr EXPR_OR simple_expr
  783.           { $$ = make_binary_op (EXPR_OR, $1, $2, $3); }
  784.         ;
  785.  
  786. simple_expr1    : NUM
  787.           {
  788.             tree_constant *tmp = new tree_constant ($1->number ());
  789.             tmp->stash_original_text ($1->text_rep ());
  790.             $$ = tmp;
  791.           }
  792.         | IMAG_NUM
  793.           {
  794.             Complex c (0.0, $1->number ());
  795.             tree_constant *tmp = new tree_constant (c);
  796.             tmp->stash_original_text ($1->text_rep ());
  797.             $$ = tmp;
  798.           }
  799.         | TEXT
  800.           { $$ = new tree_constant ($1->string ()); }
  801.         | '(' expression ')'
  802.           {
  803.             $2->in_parens++;
  804.             $$ = $2;
  805.           }
  806.         | word_list_cmd
  807.           { $$ = $1; }
  808.         | variable
  809.           { $$ = $1; }
  810.         | matrix
  811.           { $$ = $1; }
  812.         | '[' ']'
  813.           {
  814.             mlnm.pop ();
  815.             $$ = new tree_constant (Matrix ());
  816.           }
  817.         | '[' ';' ']'
  818.           {
  819.             mlnm.pop ();
  820.             $$ = new tree_constant (Matrix ());
  821.           }
  822.         | colon_expr
  823.           { $$ = $1; }
  824.         | PLUS_PLUS identifier %prec UNARY
  825.           { $$ = make_prefix_op (PLUS_PLUS, $2, $1); }
  826.         | MINUS_MINUS identifier %prec UNARY
  827.           { $$ = make_prefix_op (MINUS_MINUS, $2, $1); }
  828.         | EXPR_NOT simple_expr
  829.           { $$ = make_unary_op (EXPR_NOT, $2, $1); }
  830.         | '+' simple_expr %prec UNARY
  831.           { $$ = $2; }
  832.         | '-' simple_expr %prec UNARY
  833.           { $$ = make_unary_op ('-', $2, $1); }
  834.         ;
  835.  
  836. colon_expr    : simple_expr ':' simple_expr
  837.           { $$ = new tree_colon_expression
  838.               ($1, $3, $2->line (), $2->column ()); }
  839.         | colon_expr ':' simple_expr
  840.           {
  841.             $$ = $1->chain ($3);
  842.             if (! $$)
  843.               ABORT_PARSE;
  844.           }
  845.         ;
  846.  
  847. word_list_cmd    : identifier word_list
  848.           {
  849.             $$ = new tree_index_expression
  850.                ($1, $2, $1->line (), $1->column ());
  851.           }
  852.         ;
  853.  
  854. word_list    : TEXT
  855.           {
  856.             tree_constant *tmp = new tree_constant ($1->string ());
  857.             $$ = new tree_argument_list (tmp);
  858.           }
  859.         | word_list TEXT
  860.           {
  861.             tree_constant *tmp = new tree_constant ($2->string ());
  862.             $1->append (tmp);
  863.           }
  864.         ;
  865.  
  866. // This is truly disgusting.
  867.  
  868. g_symtab    : // empty
  869.           { curr_sym_tab = global_sym_tab; }
  870.         ;
  871.  
  872. local_symtab    : // empty
  873.           { curr_sym_tab = tmp_local_sym_tab; }
  874.         ;
  875.  
  876. safe        : // empty
  877.           { maybe_screwed = 0; }
  878.         ;
  879.  
  880. are_we_screwed    : // empty
  881.           { maybe_screwed = 1; }
  882.         ;
  883.  
  884. func_def    : FCN g_symtab are_we_screwed func_def1
  885.           {
  886.             curr_sym_tab = top_level_sym_tab;
  887.             defining_func = 0;
  888.             $$ = 0;
  889.           }
  890.         | FCN g_symtab are_we_screwed func_def2
  891.           {
  892.             curr_sym_tab = top_level_sym_tab;
  893.             defining_func = 0;
  894.             $$ = 0;
  895.           }
  896.         ;
  897.  
  898. func_def1    : SCREW safe g_symtab '=' func_def2
  899.           {
  900.             tree_identifier *tmp = new tree_identifier
  901.               ($1->sym_rec (), $1->line (), $1->column ());
  902.             tree_parameter_list *tpl = new tree_parameter_list (tmp);
  903.             tpl->mark_as_formal_parameters ();
  904.             $$ = $5->define_ret_list (tpl);
  905.           }
  906.         | return_list g_symtab '=' func_def2
  907.           {
  908.             $1->mark_as_formal_parameters ();
  909.             $$ = $4->define_ret_list ($1);
  910.           }
  911.         ;
  912.  
  913. return_list_x    : '[' safe local_symtab
  914.         ;
  915.  
  916. return_list    : return_list_x ']'
  917.           { $$ = new tree_parameter_list (); }
  918.         | return_list_x ELLIPSIS ']'
  919.           {
  920.             tree_parameter_list *tmp = new tree_parameter_list ();
  921.             tmp->mark_varargs_only ();
  922.             $$ = tmp;
  923.           }
  924.         | return_list1 ']'
  925.           { $$ = $1; }
  926.         | return_list1 ',' ELLIPSIS ']'
  927.           {
  928.             $1->mark_varargs ();
  929.             $$ = $1;
  930.           }
  931.         ;
  932.  
  933. return_list1    : return_list_x identifier
  934.           { $$ = new tree_parameter_list ($2); }
  935.         | return_list_x error
  936.           {
  937.             yyerror ("invalid function return list");
  938.             ABORT_PARSE;
  939.           }
  940.         | return_list1 ',' identifier
  941.           { $1->append ($3); }
  942.         ;
  943.  
  944. func_def2    : identifier safe local_symtab func_def3
  945.           {
  946.             char *id_name = $1->name ();
  947. //            if (is_text_function_name (id_name))
  948. //              {
  949. //            yyerror ("invalid use of reserved word %s", id_name);
  950. //            ABORT_PARSE;
  951. //              }
  952.  
  953. // If input is coming from a file, issue a warning if the name of the
  954. // file does not match the name of the function stated in the file.
  955. // Matlab doesn't provide a diagnostic (it ignores the stated name).
  956.  
  957.             $4->stash_function_name (id_name);
  958.  
  959.             if (reading_fcn_file)
  960.               {
  961.             if (strcmp (curr_fcn_file_name, id_name) != 0)
  962.               {
  963.                 if (user_pref.warn_function_name_clash)
  964.                   warning ("function name `%s' does not agree\
  965.  with function file name `%s.m'", id_name, curr_fcn_file_name);
  966.  
  967.                 global_sym_tab->rename (id_name,
  968.                             curr_fcn_file_name);
  969.  
  970.                 if (error_state)
  971.                   ABORT_PARSE;
  972.  
  973.                 id_name = $1->name ();
  974.               }
  975.  
  976.             $4->stash_function_name (id_name);
  977.             $4->stash_fcn_file_name ();
  978.             $4->stash_fcn_file_time (time (0));
  979.             $4->mark_as_system_fcn_file ();
  980.               }
  981.             else if (! (input_from_tmp_history_file
  982.                 || input_from_startup_file)
  983.                  && reading_script_file
  984.                  && strcmp (curr_fcn_file_name, id_name) == 0)
  985.               {
  986.             warning ("function `%s' defined within\
  987.  script file `%s.m'", id_name, curr_fcn_file_name);
  988.               }
  989.  
  990.             top_level_sym_tab->clear (id_name);
  991.  
  992.             $1->define ($4);
  993.             $1->document (help_buf);
  994.  
  995.             $$ = $4;
  996.           }
  997.         ;
  998.  
  999. func_def3    : param_list optsep opt_list fcn_end_or_eof
  1000.           {
  1001.             tree_function *fcn = new tree_function ($3, curr_sym_tab);
  1002.             $$ = fcn->define_param_list ($1);
  1003.           }
  1004.         | optsep opt_list fcn_end_or_eof
  1005.           { $$ = new tree_function ($2, curr_sym_tab); }
  1006.         ;
  1007.  
  1008. fcn_end_or_eof    : END
  1009.           {
  1010.             if (check_end ($1, token::function_end))
  1011.             ABORT_PARSE;
  1012.  
  1013.             if (reading_fcn_file)
  1014.               check_for_garbage_after_fcn_def ();
  1015.           }
  1016.         | END_OF_INPUT
  1017.           {
  1018.             if (! (reading_fcn_file || reading_script_file))
  1019.               YYABORT;
  1020.           }
  1021.         ;
  1022.  
  1023. indirect_ref    : indirect_ref1
  1024.           {
  1025.             looking_at_indirect_ref = 0;
  1026.             $$ = $1;
  1027.           }
  1028.  
  1029. indirect_ref1    : identifier
  1030.           {
  1031.             $$ = new tree_indirect_ref ($1, $1->line (),
  1032.                         $1->column ());
  1033.           }
  1034.         | indirect_ref1 '.' { looking_at_indirect_ref = 1; } TEXT_ID
  1035.           { $$ = $1->chain ($4->string ()); }
  1036.         ;
  1037.  
  1038. variable    : indirect_ref
  1039.           { $$ = make_index_expression ($1, 0); }
  1040.         | indirect_ref '(' ')'
  1041.           { $$ = make_index_expression ($1, 0); }
  1042.         | indirect_ref '(' arg_list ')'
  1043.           { $$ = make_index_expression ($1, $3); }
  1044.         | indirect_ref '['
  1045.           {
  1046.             yyerror ("use `(\' and `)\' as index operators, not\
  1047.  `[\' and `]\'"); 
  1048.             $$ = 0;
  1049.             ABORT_PARSE;
  1050.           }
  1051.         ;
  1052.  
  1053. param_list    : '(' ')'
  1054.           {
  1055.             quote_is_transpose = 0;
  1056.             $$ = 0;
  1057.           }
  1058.         | '(' ELLIPSIS ')'
  1059.           {
  1060.             quote_is_transpose = 0;
  1061.             tree_parameter_list *tmp = new tree_parameter_list ();
  1062.             tmp->mark_varargs_only ();
  1063.             $$ = tmp;
  1064.           }
  1065.         | param_list1 ')'
  1066.           {
  1067.             quote_is_transpose = 0;
  1068.             $1->mark_as_formal_parameters ();
  1069.           }
  1070.         | param_list1 ',' ELLIPSIS ')'
  1071.           {
  1072.             quote_is_transpose = 0;
  1073.             $1->mark_as_formal_parameters ();
  1074.             $1->mark_varargs ();
  1075.           }
  1076.         ;
  1077.  
  1078. param_list1    : '(' identifier
  1079.           { $$ = new tree_parameter_list ($2); }
  1080.         | param_list1 ',' identifier
  1081.           { $1->append ($3); }
  1082.         | '(' error
  1083.           {
  1084.             yyerror ("invalid parameter list");
  1085.             ABORT_PARSE;
  1086.           }
  1087.         | param_list1 ',' error
  1088.           {
  1089.             yyerror ("invalid parameter list");
  1090.             ABORT_PARSE;
  1091.           }
  1092.         ;
  1093.  
  1094. identifier    : NAME
  1095.           {
  1096.             $$ = new tree_identifier
  1097.               ($1->sym_rec (), $1->line (), $1->column ());
  1098.           }
  1099.         ;
  1100.  
  1101. arg_list    : ':'
  1102.           {
  1103.             tree_constant *colon;
  1104.             tree_constant::magic_colon t;
  1105.             colon = new tree_constant (t);
  1106.             $$ = new tree_argument_list (colon);
  1107.           }
  1108.         | expression
  1109.           { $$ = new tree_argument_list ($1); }
  1110.         | ALL_VA_ARGS
  1111.           {
  1112.             tree_constant *all_va_args;
  1113.             tree_constant::all_va_args t;
  1114.             all_va_args = new tree_constant (t);
  1115.             $$ = new tree_argument_list (all_va_args);
  1116.           }
  1117.         | arg_list ',' ':'
  1118.           {
  1119.             tree_constant *colon;
  1120.             tree_constant::magic_colon t;
  1121.             colon = new tree_constant (t);
  1122.             $1->append (colon);
  1123.           }
  1124.         | arg_list ',' expression
  1125.           { $1->append ($3); }
  1126.         | arg_list ',' ALL_VA_ARGS
  1127.           {
  1128.             tree_constant *all_va_args;
  1129.             tree_constant::all_va_args t;
  1130.             all_va_args = new tree_constant (t);
  1131.             $1->append (all_va_args);
  1132.           }
  1133.         ;
  1134.  
  1135. matrix        : '[' screwed_again rows ']'
  1136.           {
  1137.             mlnm.pop ();
  1138.             maybe_screwed_again--;
  1139.             tree_matrix *tmp = ml.pop ();
  1140.             $$ = tmp->reverse ();
  1141.           }
  1142.         ;
  1143.  
  1144. rows        : rows1
  1145.         | rows1 ';'    // Ignore trailing semicolon.
  1146.         ;
  1147.  
  1148. rows1        : matrix_row
  1149.         | rows1 ';' matrix_row
  1150.         ;
  1151.  
  1152. matrix_row    : matrix_row1
  1153.         | matrix_row1 ','    // Ignore trailing comma.
  1154.         ;
  1155.  
  1156. matrix_row1    : expression        // First element on row.
  1157.           {
  1158.             if (mlnm.top ())
  1159.               {
  1160.             mlnm.pop ();
  1161.             mlnm.push (0);
  1162.             tree_matrix *tmp = new tree_matrix
  1163.               ($1, tree_matrix::md_none);
  1164.             ml.push (tmp);
  1165.               }
  1166.             else
  1167.               {
  1168.             tree_matrix *tmp = ml.pop ();
  1169.             tmp = tmp->chain ($1, tree_matrix::md_down);
  1170.             ml.push (tmp);
  1171.               }
  1172.           }
  1173.         | matrix_row1 ',' expression
  1174.           {
  1175.             tree_matrix *tmp = ml.pop ();
  1176.             tmp = tmp->chain ($3, tree_matrix::md_right);
  1177.             ml.push (tmp);
  1178.           }
  1179.         ;
  1180.  
  1181. %%
  1182.  
  1183. // Generic error messages.
  1184.  
  1185. static void
  1186. yyerror (char *s)
  1187. {
  1188.   char *line = current_input_line;
  1189.   int err_col = current_input_column - 1;
  1190.  
  1191.   ostrstream output_buf;
  1192.  
  1193.   if (reading_fcn_file || reading_script_file)
  1194.     output_buf << "parse error near line " << input_line_number
  1195.            << " of file " << curr_fcn_file_name << ".m:";
  1196.   else
  1197.     output_buf << "parse error:";
  1198.  
  1199.   if (s && strcmp (s, "parse error") != 0)
  1200.     output_buf << "\n\n  " << s;
  1201.  
  1202.   output_buf << "\n\n";
  1203.  
  1204.   if (line)
  1205.     {
  1206.       int len = strlen (line);
  1207.  
  1208.       if (line[len-1] == '\n')
  1209.         {
  1210.           len--;
  1211.           line[len] = '\0';
  1212.         }
  1213.  
  1214. // Print the line, maybe with a pointer near the error token.
  1215.  
  1216.       output_buf << ">>> " << line << "\n";
  1217.  
  1218.       if (err_col == 0)
  1219.     err_col = len;
  1220.  
  1221.       for (int i = 0; i < err_col + 3; i++)
  1222.     output_buf << " ";
  1223.  
  1224.       output_buf << "^";
  1225.     }
  1226.  
  1227.   output_buf << "\n" << ends;
  1228.  
  1229.   char *msg = output_buf.str ();
  1230.  
  1231.   parse_error ("%s", msg);
  1232.  
  1233.   delete [] msg;
  1234. }
  1235.  
  1236. // Error mesages for mismatched end tokens.
  1237.  
  1238. static void
  1239. end_error (char *type, token::end_tok_type ettype, int l, int c)
  1240. {
  1241.   static char *fmt = "`%s' command matched by `%s' near line %d column %d";
  1242.  
  1243.   switch (ettype)
  1244.     {
  1245.     case token::simple_end:
  1246.       error (fmt, type, "end", l, c);
  1247.       break;
  1248.  
  1249.     case token::for_end:
  1250.       error (fmt, type, "endfor", l, c);
  1251.       break;
  1252.  
  1253.     case token::function_end:
  1254.       error (fmt, type, "endfunction", l, c);
  1255.       break;
  1256.  
  1257.     case token::if_end:
  1258.       error (fmt, type, "endif", l, c);
  1259.       break;
  1260.  
  1261.     case token::while_end:
  1262.       error (fmt, type, "endwhile", l, c); 
  1263.       break;
  1264.  
  1265.     default:
  1266.       panic_impossible ();
  1267.       break;
  1268.     }
  1269. }
  1270.  
  1271. // Check to see that end tokens are properly matched.
  1272.  
  1273. static int
  1274. check_end (token *tok, token::end_tok_type expected)
  1275. {
  1276.   token::end_tok_type ettype = tok->ettype ();
  1277.   if (ettype != expected && ettype != token::simple_end)
  1278.     {
  1279.       yyerror ("parse error");
  1280.  
  1281.       int l = tok->line ();
  1282.       int c = tok->column ();
  1283.  
  1284.       switch (expected)
  1285.     {
  1286.     case token::for_end:
  1287.       end_error ("for", ettype, l, c);
  1288.       break;
  1289.  
  1290.     case token::function_end:
  1291.       end_error ("function", ettype, l, c);
  1292.       break;
  1293.  
  1294.     case token::if_end:
  1295.       end_error ("if", ettype, l, c);
  1296.       break;
  1297.  
  1298.     case token::while_end:
  1299.       end_error ("while", ettype, l, c);
  1300.       break;
  1301.  
  1302.     default:
  1303.       panic_impossible ();
  1304.       break;
  1305.     }
  1306.       return 1;
  1307.     }
  1308.   else
  1309.     return 0;
  1310. }
  1311.  
  1312. // Try to figure out early if an expression should become an
  1313. // assignment to the builtin variable ans.
  1314. //
  1315. // Need to make sure that the expression isn't already an identifier
  1316. // that has a name, or an assignment expression.
  1317. //
  1318. // Note that an expression can't be just an identifier anymore -- it
  1319. // must at least be an index expression (see the definition of the
  1320. // non-terminal `variable' above).
  1321. //
  1322. // XXX FIXME XXX.  This isn't quite sufficient.  For example, try the
  1323. // command `x = 4, x' for `x' previously undefined.
  1324. //
  1325. // XXX FIXME XXX -- we should probably delay doing this until eval-time.
  1326.  
  1327. static tree_expression *
  1328. maybe_convert_to_ans_assign (tree_expression *expr)
  1329. {
  1330.   if (expr->is_index_expression ())
  1331.     {
  1332.       expr->mark_for_possible_ans_assign ();
  1333.       return expr;
  1334.     }
  1335.   else if (expr->is_assignment_expression ()
  1336.        || expr->is_prefix_expression ())
  1337.     {
  1338.       return expr;
  1339.     }
  1340.   else
  1341.     {
  1342.       symbol_record *sr = global_sym_tab->lookup ("ans", 1, 0);
  1343.  
  1344.       assert (sr);
  1345.       
  1346.       tree_identifier *ans = new tree_identifier (sr);
  1347.  
  1348.       return new tree_simple_assignment_expression (ans, expr, 0, 1);
  1349.     }
  1350. }
  1351.  
  1352. // Maybe print a warning if an assignment expression is used as the
  1353. // test in a logical expression.
  1354.  
  1355. static void
  1356. maybe_warn_assign_as_truth_value (tree_expression *expr)
  1357. {
  1358.   if (user_pref.warn_assign_as_truth_value
  1359.       && expr->is_assignment_expression ()
  1360.       && expr->in_parens < 2)
  1361.     {
  1362.       warning ("suggest parenthesis around assignment used as truth value");
  1363.     }
  1364. }
  1365.  
  1366. // Build a binary expression.
  1367.  
  1368. static tree_expression *
  1369. make_binary_op (int op, tree_expression *op1, token *tok_val,
  1370.         tree_expression *op2)
  1371. {
  1372.   tree_expression::type t;
  1373.   switch (op)
  1374.     {
  1375.     case POW:
  1376.       t = tree_expression::power;
  1377.       break;
  1378.  
  1379.     case EPOW:
  1380.       t = tree_expression::elem_pow;
  1381.       break;
  1382.  
  1383.     case '+':
  1384.       t = tree_expression::add;
  1385.       break;
  1386.  
  1387.     case '-':
  1388.       t = tree_expression::subtract;
  1389.       break;
  1390.  
  1391.     case '*':
  1392.       t = tree_expression::multiply;
  1393.       break;
  1394.  
  1395.     case '/':
  1396.       t = tree_expression::divide;
  1397.       break;
  1398.  
  1399.     case EMUL:
  1400.       t = tree_expression::el_mul;
  1401.       break;
  1402.  
  1403.     case EDIV:
  1404.       t = tree_expression::el_div;
  1405.       break;
  1406.  
  1407.     case LEFTDIV:
  1408.       t = tree_expression::leftdiv;
  1409.       break;
  1410.  
  1411.     case ELEFTDIV:
  1412.       t = tree_expression::el_leftdiv;
  1413.       break;
  1414.  
  1415.     case EXPR_LT:
  1416.       t = tree_expression::cmp_lt;
  1417.       break;
  1418.  
  1419.     case EXPR_LE:
  1420.       t = tree_expression::cmp_le;
  1421.       break;
  1422.  
  1423.     case EXPR_EQ:
  1424.       t = tree_expression::cmp_eq;
  1425.       break;
  1426.  
  1427.     case EXPR_GE:
  1428.       t = tree_expression::cmp_ge;
  1429.       break;
  1430.  
  1431.     case EXPR_GT:
  1432.       t = tree_expression::cmp_gt;
  1433.       break;
  1434.  
  1435.     case EXPR_NE:
  1436.       t = tree_expression::cmp_ne;
  1437.       break;
  1438.  
  1439.     case EXPR_AND_AND:
  1440.       t = tree_expression::and_and;
  1441.       break;
  1442.  
  1443.     case EXPR_OR_OR:
  1444.       t = tree_expression::or_or;
  1445.       break;
  1446.  
  1447.     case EXPR_AND:
  1448.       t = tree_expression::and;
  1449.       break;
  1450.  
  1451.     case EXPR_OR:
  1452.       t = tree_expression::or;
  1453.       break;
  1454.  
  1455.     default:
  1456.       panic_impossible ();
  1457.       break;
  1458.     }
  1459.  
  1460.   int l = tok_val->line ();
  1461.   int c = tok_val->column ();
  1462.  
  1463.   return new tree_binary_expression (op1, op2, t, l, c);
  1464. }
  1465.  
  1466. // Build a prefix expression.
  1467.  
  1468. static tree_expression *
  1469. make_prefix_op (int op, tree_identifier *op1, token *tok_val)
  1470. {
  1471.   tree_expression::type t;
  1472.   switch (op)
  1473.     {
  1474.     case PLUS_PLUS:
  1475.       t = tree_expression::increment;
  1476.       break;
  1477.  
  1478.     case MINUS_MINUS:
  1479.       t = tree_expression::decrement;
  1480.       break;
  1481.  
  1482.     default:
  1483.       panic_impossible ();
  1484.       break;
  1485.     }
  1486.  
  1487.   int l = tok_val->line ();
  1488.   int c = tok_val->column ();
  1489.  
  1490.   return new tree_prefix_expression (op1, t, l, c);
  1491. }
  1492.  
  1493. // Build a postfix expression.
  1494.  
  1495. static tree_expression *
  1496. make_postfix_op (int op, tree_identifier *op1, token *tok_val)
  1497. {
  1498.   tree_expression::type t;
  1499.   switch (op)
  1500.     {
  1501.     case PLUS_PLUS:
  1502.       t = tree_expression::increment;
  1503.       break;
  1504.  
  1505.     case MINUS_MINUS:
  1506.       t = tree_expression::decrement;
  1507.       break;
  1508.  
  1509.     default:
  1510.       panic_impossible ();
  1511.       break;
  1512.     }
  1513.  
  1514.   int l = tok_val->line ();
  1515.   int c = tok_val->column ();
  1516.  
  1517.   return new tree_postfix_expression (op1, t, l, c);
  1518. }
  1519.  
  1520. // Build a unary expression.
  1521.  
  1522. static tree_expression *
  1523. make_unary_op (int op, tree_expression *op1, token *tok_val)
  1524. {
  1525.   tree_expression::type t;
  1526.   switch (op)
  1527.     {
  1528.     case QUOTE:
  1529.       t = tree_expression::hermitian;
  1530.       break;
  1531.  
  1532.     case TRANSPOSE:
  1533.       t = tree_expression::transpose;
  1534.       break;
  1535.  
  1536.     case EXPR_NOT:
  1537.       t = tree_expression::not;
  1538.       break;
  1539.  
  1540.     case '-':
  1541.       t = tree_expression::uminus;
  1542.       break;
  1543.  
  1544.     default:
  1545.       panic_impossible ();
  1546.       break;
  1547.     }
  1548.  
  1549.   int l = tok_val->line ();
  1550.   int c = tok_val->column ();
  1551.  
  1552.   return new tree_unary_expression (op1, t, l, c);
  1553. }
  1554.  
  1555. // Make an expression that handles assignment of multiple values.
  1556.  
  1557. static tree_expression *
  1558. make_multi_val_ret (tree_expression *rhs, int l, int c) 
  1559. {
  1560. // Convert the matrix list to a list of identifiers.  If that fails,
  1561. // we can abort here, without losing anything -- no other possible
  1562. // syntax is valid if we've seen the equals sign as the next token
  1563. // after the `]'. 
  1564.  
  1565.   tree_expression *retval = 0;
  1566.  
  1567.   maybe_screwed_again--;
  1568.  
  1569.   tree_matrix *tmp = ml.pop ();
  1570.  
  1571.   tmp = tmp->reverse ();
  1572.  
  1573.   tree_return_list *id_list = tmp->to_return_list ();
  1574.  
  1575.   if (id_list)
  1576.     {
  1577.       int list_len = id_list->length ();
  1578.  
  1579.       if (list_len == 1)
  1580.     {
  1581.       tree_index_expression *lhs = id_list->remove_front ();
  1582.       retval = new tree_simple_assignment_expression (lhs, rhs,
  1583.                               0, 0, l, c);
  1584.       
  1585.     }
  1586.       else if (list_len > 1)
  1587.     {
  1588.       if (rhs->is_multi_val_ret_expression ())
  1589.         {
  1590.           tree_multi_val_ret *t = (tree_multi_val_ret *) rhs;
  1591.           retval = new tree_multi_assignment_expression (id_list, t, l, c);
  1592.         }
  1593.       else
  1594.         yyerror ("RHS must be an expression that returns multiple values");
  1595.     }
  1596.       else
  1597.     panic_impossible ();
  1598.     }
  1599.   else
  1600.     yyerror ("invalid identifier list for assignment");
  1601.  
  1602.   return retval;
  1603. }
  1604.  
  1605. static tree_index_expression *
  1606. make_index_expression (tree_indirect_ref *indir, tree_argument_list *args)
  1607. {
  1608.   tree_index_expression *retval = 0;
  1609.  
  1610.   int l = indir->line ();
  1611.   int c = indir->column ();
  1612.  
  1613.   if (indir->is_identifier_only ())
  1614.     {
  1615.       indir->preserve_identifier ();
  1616.       retval = new tree_index_expression (indir->ident (), args, l, c);
  1617.       delete indir;
  1618.     }
  1619.   else
  1620.     retval =  new tree_index_expression (indir, args, l, c);
  1621.  
  1622.   return retval;
  1623. }
  1624.