Mercurial > octave-dspies
comparison src/lex.l @ 146:edfa5a96c5f1
[project @ 1993-10-05 04:02:15 by jwe]
(handle_identifier): New function.
({IDENT}/{S}*=, {IDENT}{S}*): Use it instead of duplicating code.
author | jwe |
---|---|
date | Tue, 05 Oct 1993 04:02:15 +0000 |
parents | 7849db4b6dbc |
children | 8f91a9cbf451 |
comparison
equal
deleted
inserted
replaced
145:6beb84c3320e | 146:edfa5a96c5f1 |
---|---|
80 // 1 -> brace, spaces are important (they can turn into commas) | 80 // 1 -> brace, spaces are important (they can turn into commas) |
81 // 0 -> paren, spaces are not important | 81 // 0 -> paren, spaces are not important |
82 // | 82 // |
83 static SLStack <int> in_brace_or_paren; | 83 static SLStack <int> in_brace_or_paren; |
84 | 84 |
85 // Forward declarations for functions defined at the bottom of this | |
86 // file. | |
87 | |
85 static void do_string_escapes (char *s); | 88 static void do_string_escapes (char *s); |
86 static void fixup_column_count (char *s); | 89 static void fixup_column_count (char *s); |
87 static int do_comma_insert_check (void); | 90 static void do_comma_insert_check (void); |
88 static int is_plot_keyword (char *s); | 91 static int is_plot_keyword (char *s); |
89 static int is_keyword (char *s); | 92 static int is_keyword (char *s); |
90 static char *plot_style_token (char *s); | 93 static char *plot_style_token (char *s); |
91 static symbol_record *lookup_identifier (char *s); | 94 static symbol_record *lookup_identifier (char *s); |
92 static void grab_help_text (void); | 95 static void grab_help_text (void); |
93 static int match_any (char c, char *s); | 96 static int match_any (char c, char *s); |
94 static int next_token_is_bin_op (int spc_prev, char *yytext); | 97 static int next_token_is_bin_op (int spc_prev, char *yytext); |
95 static int next_token_is_postfix_unary_op (int spc_prev, char *yytext); | 98 static int next_token_is_postfix_unary_op (int spc_prev, char *yytext); |
96 static char *strip_trailing_whitespace (char *s); | 99 static char *strip_trailing_whitespace (char *s); |
100 static int handle_identifier (char *s, int next_tok_is_eq); | |
97 | 101 |
98 %} | 102 %} |
99 | 103 |
100 D [0-9] | 104 D [0-9] |
101 S [ \t] | 105 S [ \t] |
425 yylval.tok_val = new token (value, | 429 yylval.tok_val = new token (value, |
426 input_line_number, | 430 input_line_number, |
427 current_input_column); | 431 current_input_column); |
428 token_stack.push (yylval.tok_val); | 432 token_stack.push (yylval.tok_val); |
429 current_input_column += yyleng; | 433 current_input_column += yyleng; |
430 DO_COMMA_INSERT_CHECK; | 434 do_comma_insert_check (); |
431 return IMAG_NUM; | 435 return IMAG_NUM; |
432 } | 436 } |
433 | 437 |
434 {D}+{EXPON}? | | 438 {D}+{EXPON}? | |
435 {D}+\.{D}*{EXPON}? | | 439 {D}+\.{D}*{EXPON}? | |
446 yylval.tok_val = new token (value, | 450 yylval.tok_val = new token (value, |
447 input_line_number, | 451 input_line_number, |
448 current_input_column); | 452 current_input_column); |
449 token_stack.push (yylval.tok_val); | 453 token_stack.push (yylval.tok_val); |
450 current_input_column += yyleng; | 454 current_input_column += yyleng; |
451 DO_COMMA_INSERT_CHECK; | 455 do_comma_insert_check (); |
452 return NUM; | 456 return NUM; |
453 } | 457 } |
454 | 458 |
455 \[{S}* { | 459 \[{S}* { |
456 in_brace_or_paren.push (1); | 460 in_brace_or_paren.push (1); |
497 // directly on yytext. | 501 // directly on yytext. |
498 | 502 |
499 static char *tok = (char *) NULL; | 503 static char *tok = (char *) NULL; |
500 delete [] tok; | 504 delete [] tok; |
501 tok = strip_trailing_whitespace (yytext); | 505 tok = strip_trailing_whitespace (yytext); |
502 | 506 return handle_identifier (tok, 0); |
503 int kw_token = is_keyword (tok); | |
504 if (kw_token) | |
505 TOK_RETURN (kw_token); | |
506 | |
507 if (plotting && cant_be_identifier) | |
508 { | |
509 int plot_option_kw = is_plot_keyword (tok); | |
510 if (plot_option_kw) | |
511 { | |
512 quote_is_transpose = 0; | |
513 cant_be_identifier = 0; | |
514 convert_spaces_to_comma = 1; | |
515 current_input_column += yyleng; | |
516 return plot_option_kw; | |
517 } | |
518 } | |
519 | |
520 if (plotting && ! in_plot_range) | |
521 past_plot_range = 1; | |
522 | |
523 if (plotting && in_plot_style) | |
524 { | |
525 char *sty = plot_style_token (&tok[1]); | |
526 if (sty != (char *) NULL) | |
527 { | |
528 yylval.tok_val = new token (sty); | |
529 token_stack.push (yylval.tok_val); | |
530 if (in_plot_style) | |
531 { | |
532 in_plot_style = 0; | |
533 TOK_RETURN (STYLE); | |
534 } | |
535 } | |
536 } | |
537 | |
538 cant_be_identifier = 1; | |
539 | |
540 // If we are looking at a text style function, set up to gobble its | |
541 // arguments. These are also reserved words, but only because it | |
542 // would be very difficult to do anything intelligent with them if | |
543 // they were not reserved. | |
544 | |
545 if (is_text_function_name (tok)) | |
546 { | |
547 BEGIN TEXT_FCN; | |
548 | |
549 if (strcmp (tok, "clear") == 0) | |
550 { | |
551 symbol_record *sr = | |
552 global_sym_tab->lookup ("clear", 1, 0); | |
553 assert (sr != (symbol_record *) NULL); | |
554 yylval.tok_val = new token (sr, input_line_number, | |
555 current_input_column); | |
556 token_stack.push (yylval.tok_val); | |
557 return CLEAR; | |
558 } | |
559 else if (strcmp (tok, "help") == 0) | |
560 BEGIN HELP_FCN; | |
561 else if (strcmp (tok, "set") == 0) | |
562 doing_set = 1; | |
563 } | |
564 | |
565 yylval.tok_val = new token (lookup_identifier (tok), | |
566 input_line_number, | |
567 current_input_column); | |
568 token_stack.push (yylval.tok_val); | |
569 | |
570 quote_is_transpose = 1; | |
571 current_input_column += yyleng; | |
572 DO_COMMA_INSERT_CHECK; | |
573 | |
574 if (! in_brace_or_paren.empty () | |
575 && in_brace_or_paren.top ()) | |
576 { | |
577 int c0 = yytext[yyleng-1]; | |
578 int spc_prev = (c0 == ' ' || c0 == '\t'); | |
579 int bin_op = next_token_is_bin_op (spc_prev, yytext); | |
580 | |
581 int postfix_un_op | |
582 = next_token_is_postfix_unary_op (spc_prev, yytext); | |
583 | |
584 int c1 = yyinput (); | |
585 unput (c1); | |
586 int other_op = match_any (c1, ",;\n]("); | |
587 | |
588 if (! (postfix_un_op || bin_op || other_op)) | |
589 unput (','); | |
590 } | |
591 | |
592 convert_spaces_to_comma = 1; | |
593 return NAME; | |
594 } | 507 } |
595 | 508 |
596 {IDENT}/{S}*= { | 509 {IDENT}/{S}*= { return handle_identifier (yytext, 1); } |
597 | |
598 // We've found an identifier followed by some space and an equals | |
599 // sign. If we are working on a function definition and the previous | |
600 // token was `function', we have something like this | |
601 // | |
602 // function x = y <list> end | |
603 // | |
604 // which is a function named y returning a variable named x. The | |
605 // symbol y belongs in the global symbol table (nested function | |
606 // definitions are illegal) and the symbol x belongs in the | |
607 // symbol table local to the function. | |
608 // | |
609 // If we're not defining a function, this should function exactly like | |
610 // the case above. I suppose it would be nice to avoid duplicating | |
611 // all the code, eh? | |
612 | |
613 int kw_token = is_keyword (yytext); | |
614 if (kw_token) | |
615 TOK_RETURN (kw_token); | |
616 | |
617 if (plotting && cant_be_identifier) | |
618 { | |
619 int plot_option_kw = is_plot_keyword (yytext); | |
620 if (plot_option_kw) | |
621 { | |
622 quote_is_transpose = 0; | |
623 convert_spaces_to_comma = 1; | |
624 current_input_column += yyleng; | |
625 return plot_option_kw; | |
626 } | |
627 } | |
628 | |
629 cant_be_identifier = 1; | |
630 | |
631 // If we are looking at a text style function, set up to gobble its | |
632 // arguments. These are also reserved words, but only because it | |
633 // would be very difficult to do anything intelligent with them if | |
634 // they were not reserved. | |
635 | |
636 if (is_text_function_name (yytext)) | |
637 { | |
638 BEGIN TEXT_FCN; | |
639 | |
640 if (strcmp (yytext, "clear") == 0) | |
641 { | |
642 symbol_record *sr = | |
643 global_sym_tab->lookup ("clear", 1, 0); | |
644 assert (sr != (symbol_record *) NULL); | |
645 yylval.tok_val = new token (sr, input_line_number, | |
646 current_input_column); | |
647 token_stack.push (yylval.tok_val); | |
648 return CLEAR; | |
649 } | |
650 else if (strcmp (yytext, "help") == 0) | |
651 BEGIN HELP_FCN; | |
652 else if (strcmp (yytext, "set") == 0) | |
653 doing_set = 1; | |
654 } | |
655 | |
656 if (defining_func && maybe_screwed) | |
657 curr_sym_tab = tmp_local_sym_tab; | |
658 | |
659 yylval.tok_val = new token (lookup_identifier (yytext), | |
660 input_line_number, | |
661 current_input_column); | |
662 token_stack.push (yylval.tok_val); | |
663 | |
664 convert_spaces_to_comma = 1; | |
665 current_input_column += yyleng; | |
666 if (defining_func && maybe_screwed) | |
667 { | |
668 return SCREW; | |
669 } | |
670 else | |
671 { | |
672 quote_is_transpose = 1; | |
673 DO_COMMA_INSERT_CHECK; | |
674 return NAME; | |
675 } | |
676 } | |
677 | 510 |
678 "\n" { | 511 "\n" { |
679 quote_is_transpose = 0; | 512 quote_is_transpose = 0; |
680 cant_be_identifier = 0; | 513 cant_be_identifier = 0; |
681 current_input_column = 1; | 514 current_input_column = 1; |
687 current_input_column++; | 520 current_input_column++; |
688 convert_spaces_to_comma = 1; | 521 convert_spaces_to_comma = 1; |
689 | 522 |
690 if (quote_is_transpose) | 523 if (quote_is_transpose) |
691 { | 524 { |
692 DO_COMMA_INSERT_CHECK; | 525 do_comma_insert_check (); |
693 return QUOTE; | 526 return QUOTE; |
694 } | 527 } |
695 else | 528 else |
696 BEGIN STRING; | 529 BEGIN STRING; |
697 } | 530 } |
707 ".**" { BIN_OP_RETURN (EPOW, 0); } | 540 ".**" { BIN_OP_RETURN (EPOW, 0); } |
708 ".*" { BIN_OP_RETURN (EMUL, 0); } | 541 ".*" { BIN_OP_RETURN (EMUL, 0); } |
709 "./" { BIN_OP_RETURN (EDIV, 0); } | 542 "./" { BIN_OP_RETURN (EDIV, 0); } |
710 ".\\" { BIN_OP_RETURN (ELEFTDIV, 0); } | 543 ".\\" { BIN_OP_RETURN (ELEFTDIV, 0); } |
711 ".^" { BIN_OP_RETURN (EPOW, 0); } | 544 ".^" { BIN_OP_RETURN (EPOW, 0); } |
712 ".'" { DO_COMMA_INSERT_CHECK; BIN_OP_RETURN (TRANSPOSE, 1); } | 545 ".'" { do_comma_insert_check (); BIN_OP_RETURN (TRANSPOSE, 1); } |
713 "++" { DO_COMMA_INSERT_CHECK; BIN_OP_RETURN (PLUS_PLUS, 1); } | 546 "++" { do_comma_insert_check (); BIN_OP_RETURN (PLUS_PLUS, 1); } |
714 "--" { DO_COMMA_INSERT_CHECK; BIN_OP_RETURN (MINUS_MINUS, 1); } | 547 "--" { do_comma_insert_check (); BIN_OP_RETURN (MINUS_MINUS, 1); } |
715 "<=" { BIN_OP_RETURN (EXPR_LE, 0); } | 548 "<=" { BIN_OP_RETURN (EXPR_LE, 0); } |
716 "==" { BIN_OP_RETURN (EXPR_EQ, 0); } | 549 "==" { BIN_OP_RETURN (EXPR_EQ, 0); } |
717 "~=" { BIN_OP_RETURN (EXPR_NE, 0); } | 550 "~=" { BIN_OP_RETURN (EXPR_NE, 0); } |
718 "!=" { BIN_OP_RETURN (EXPR_NE, 0); } | 551 "!=" { BIN_OP_RETURN (EXPR_NE, 0); } |
719 "<>" { BIN_OP_RETURN (EXPR_NE, 0); } | 552 "<>" { BIN_OP_RETURN (EXPR_NE, 0); } |
759 TOK_RETURN ('('); | 592 TOK_RETURN ('('); |
760 } | 593 } |
761 ")" { | 594 ")" { |
762 if (! in_brace_or_paren.empty ()) | 595 if (! in_brace_or_paren.empty ()) |
763 in_brace_or_paren.pop (); | 596 in_brace_or_paren.pop (); |
764 DO_COMMA_INSERT_CHECK; | 597 do_comma_insert_check (); |
765 current_input_column++; | 598 current_input_column++; |
766 quote_is_transpose = 1; | 599 quote_is_transpose = 1; |
767 return ')'; | 600 return ')'; |
768 } | 601 } |
769 | 602 |
781 * GAG. | 614 * GAG. |
782 * | 615 * |
783 * If we're reading a matrix and the next character is '[', make sure | 616 * If we're reading a matrix and the next character is '[', make sure |
784 * that we insert a comma ahead of it. | 617 * that we insert a comma ahead of it. |
785 */ | 618 */ |
786 int | 619 void |
787 do_comma_insert_check (void) | 620 do_comma_insert_check (void) |
788 { | 621 { |
789 int tmp_len = yyleng; | |
790 int c = yyinput (); | 622 int c = yyinput (); |
623 yyunput (c, yytext); | |
791 do_comma_insert = (braceflag && c == '['); | 624 do_comma_insert = (braceflag && c == '['); |
792 return tmp_len; | |
793 } | 625 } |
794 | 626 |
795 /* | 627 /* |
796 * Fix things up for errors or interrupts. This could use a few | 628 * Fix things up for errors or interrupts. This could use a few |
797 * comments now, eh? | 629 * comments now, eh? |
829 while (! token_stack.empty ()) | 661 while (! token_stack.empty ()) |
830 delete token_stack.pop (); | 662 delete token_stack.pop (); |
831 yyrestart (stdin); | 663 yyrestart (stdin); |
832 } | 664 } |
833 | 665 |
666 /* | |
667 * Replace backslash escapes in a string with the real values. | |
668 */ | |
834 static void | 669 static void |
835 do_string_escapes (char *s) | 670 do_string_escapes (char *s) |
836 { | 671 { |
837 char *p1 = s; | 672 char *p1 = s; |
838 char *p2 = s; | 673 char *p2 = s; |
894 } | 729 } |
895 | 730 |
896 *p1 = '\0'; | 731 *p1 = '\0'; |
897 } | 732 } |
898 | 733 |
734 /* | |
735 * If we read some newlines, we need figure out what column we're | |
736 * really looking at. | |
737 */ | |
899 static void | 738 static void |
900 fixup_column_count (char *s) | 739 fixup_column_count (char *s) |
901 { | 740 { |
902 char c; | 741 char c; |
903 while ((c = *s++) != '\0') | 742 while ((c = *s++) != '\0') |
970 delete_input_buffer (void *buf) | 809 delete_input_buffer (void *buf) |
971 { | 810 { |
972 delete_buffer ((YY_BUFFER_STATE) buf); | 811 delete_buffer ((YY_BUFFER_STATE) buf); |
973 } | 812 } |
974 | 813 |
975 static char *plot_styles[] = | 814 /* |
976 { | 815 * Check to see if a character string matches any of the possible line |
977 "dots", | 816 * styles for plots. |
978 "dots", | 817 */ |
979 "errorbars", | |
980 "impulses", | |
981 "lines", | |
982 "linespoints", | |
983 "points", | |
984 (char *) NULL, | |
985 }; | |
986 | |
987 static char * | 818 static char * |
988 plot_style_token (char *s) | 819 plot_style_token (char *s) |
989 { | 820 { |
821 static char *plot_styles[] = | |
822 { | |
823 "dots", | |
824 "errorbars", | |
825 "impulses", | |
826 "lines", | |
827 "linespoints", | |
828 "points", | |
829 (char *) NULL, | |
830 }; | |
831 | |
990 char **tmp = plot_styles; | 832 char **tmp = plot_styles; |
991 while (*tmp != (char *) NULL) | 833 while (*tmp != (char *) NULL) |
992 { | 834 { |
993 if (almost_match (*tmp, s)) | 835 if (almost_match (*tmp, s)) |
994 return *tmp; | 836 return *tmp; |
997 } | 839 } |
998 | 840 |
999 return (char *) NULL; | 841 return (char *) NULL; |
1000 } | 842 } |
1001 | 843 |
844 /* | |
845 * Check to see if a character string matches any one of the plot | |
846 * option keywords. | |
847 */ | |
1002 static int | 848 static int |
1003 is_plot_keyword (char *s) | 849 is_plot_keyword (char *s) |
1004 { | 850 { |
1005 if (almost_match ("title", s)) | 851 if (almost_match ("title", s)) |
1006 return TITLE; | 852 { |
853 return TITLE; | |
854 } | |
1007 else if (almost_match ("using", s)) | 855 else if (almost_match ("using", s)) |
1008 { in_plot_using = 1; past_plot_range = 1; return USING; } | 856 { |
857 in_plot_using = 1; | |
858 past_plot_range = 1; | |
859 return USING; | |
860 } | |
1009 else if (almost_match ("with", s)) | 861 else if (almost_match ("with", s)) |
1010 { in_plot_style = 1; past_plot_range = 1; return WITH; } | 862 { |
863 in_plot_style = 1; | |
864 past_plot_range = 1; | |
865 return WITH; | |
866 } | |
1011 else | 867 else |
1012 return 0; | 868 { |
869 return 0; | |
870 } | |
1013 } | 871 } |
1014 | 872 |
1015 /* | 873 /* |
1016 * Handle keywords. Could probably be more efficient... | 874 * Handle keywords. Could probably be more efficient... |
1017 */ | 875 */ |
1147 } | 1005 } |
1148 | 1006 |
1149 return 0; | 1007 return 0; |
1150 } | 1008 } |
1151 | 1009 |
1010 /* | |
1011 * Try to find an identifier in one symbol table or another. Insert | |
1012 * it in the local symbol table it is is not already there and it does | |
1013 * not already have global scope. | |
1014 */ | |
1152 static symbol_record * | 1015 static symbol_record * |
1153 lookup_identifier (char *name) | 1016 lookup_identifier (char *name) |
1154 { | 1017 { |
1155 symbol_record *lsr = curr_sym_tab->lookup (name, 0, 0); | 1018 symbol_record *lsr = curr_sym_tab->lookup (name, 0, 0); |
1156 if (lsr != (symbol_record *) NULL) | 1019 if (lsr != (symbol_record *) NULL) |
1161 return gsr; | 1024 return gsr; |
1162 | 1025 |
1163 return curr_sym_tab->lookup (name, 1, 0); | 1026 return curr_sym_tab->lookup (name, 1, 0); |
1164 } | 1027 } |
1165 | 1028 |
1029 /* | |
1030 * Grab the help text from an M-file. | |
1031 */ | |
1166 static void | 1032 static void |
1167 grab_help_text (void) | 1033 grab_help_text (void) |
1168 { | 1034 { |
1169 int max_len = HELP_BUF_LENGTH - 1; | 1035 int max_len = HELP_BUF_LENGTH - 1; |
1170 | 1036 |
1215 yyunput ('\n', yytext); | 1081 yyunput ('\n', yytext); |
1216 | 1082 |
1217 help_buf[len] = '\0'; | 1083 help_buf[len] = '\0'; |
1218 } | 1084 } |
1219 | 1085 |
1086 /* | |
1087 * Return 1 if the given character matches any character in the given | |
1088 * string. | |
1089 */ | |
1220 static int | 1090 static int |
1221 match_any (char c, char *s) | 1091 match_any (char c, char *s) |
1222 { | 1092 { |
1223 char tmp; | 1093 char tmp; |
1224 while ((tmp = *s++) != '\0') | 1094 while ((tmp = *s++) != '\0') |
1227 return 1; | 1097 return 1; |
1228 } | 1098 } |
1229 return 0; | 1099 return 0; |
1230 } | 1100 } |
1231 | 1101 |
1102 /* | |
1103 * Given information about the spacing surrounding an operator, | |
1104 * return 1 if it looks like it should be treated as a binary | |
1105 * operator. For example, | |
1106 * | |
1107 * [ 1 + 2 ] or [ 1+2 ] ==> binary | |
1108 * | |
1109 * The case of [ 1+ 2 ] should also be treated as a binary operator, | |
1110 * but it is handled by the caller. | |
1111 */ | |
1232 static int | 1112 static int |
1233 looks_like_bin_op (int spc_prev, int spc_next) | 1113 looks_like_bin_op (int spc_prev, int spc_next) |
1234 { | 1114 { |
1235 return ((spc_prev && spc_next) || ! (spc_prev || spc_next)); | 1115 return ((spc_prev && spc_next) || ! (spc_prev || spc_next)); |
1236 } | 1116 } |
1237 | 1117 |
1118 /* | |
1119 * Duh. | |
1120 */ | |
1238 static int | 1121 static int |
1239 next_char_is_space (void) | 1122 next_char_is_space (void) |
1240 { | 1123 { |
1241 int c = yyinput (); | 1124 int c = yyinput (); |
1242 yyunput (c, yytext); | 1125 yyunput (c, yytext); |
1243 return (c == ' ' || c == '\t'); | 1126 return (c == ' ' || c == '\t'); |
1244 } | 1127 } |
1245 | 1128 |
1129 /* | |
1130 * Try to determine if the next token should be treated as a postfix | |
1131 * unary operator. This is ugly, but it seems to do the right thing. | |
1132 */ | |
1246 static int | 1133 static int |
1247 next_token_is_postfix_unary_op (int spc_prev, char *yytext) | 1134 next_token_is_postfix_unary_op (int spc_prev, char *yytext) |
1248 { | 1135 { |
1249 int un_op = 0; | 1136 int un_op = 0; |
1250 | 1137 |
1260 un_op = (transpose || (hermitian && ! spc_prev)); | 1147 un_op = (transpose || (hermitian && ! spc_prev)); |
1261 | 1148 |
1262 return un_op; | 1149 return un_op; |
1263 } | 1150 } |
1264 | 1151 |
1152 /* | |
1153 * Try to determine if the next token should be treated as a binary | |
1154 * operator. This is even uglier, but it also seems to do the right | |
1155 * thing. | |
1156 */ | |
1265 static int | 1157 static int |
1266 next_token_is_bin_op (int spc_prev, char *yytext) | 1158 next_token_is_bin_op (int spc_prev, char *yytext) |
1267 { | 1159 { |
1268 int bin_op = 0; | 1160 int bin_op = 0; |
1269 int spc_next = 0; | 1161 int spc_next = 0; |
1347 yyunput (c0, yytext); | 1239 yyunput (c0, yytext); |
1348 | 1240 |
1349 return bin_op; | 1241 return bin_op; |
1350 } | 1242 } |
1351 | 1243 |
1352 char * | 1244 /* |
1245 * Used to delete trailing white space from tokens. | |
1246 */ | |
1247 static char * | |
1353 strip_trailing_whitespace (char *s) | 1248 strip_trailing_whitespace (char *s) |
1354 { | 1249 { |
1355 char *retval = strsave (s); | 1250 char *retval = strsave (s); |
1356 | 1251 |
1357 char *t = strchr (retval, ' '); | 1252 char *t = strchr (retval, ' '); |
1363 *t = '\0'; | 1258 *t = '\0'; |
1364 | 1259 |
1365 return retval; | 1260 return retval; |
1366 } | 1261 } |
1367 | 1262 |
1263 /* | |
1264 * Figure out exactly what kind of token to return when we have seen | |
1265 * an identifier. Handles keywords. | |
1266 */ | |
1267 static int | |
1268 handle_identifier (char *tok, int next_tok_is_eq) | |
1269 { | |
1270 // If we have a regular keyword, or a plot STYLE, return it. STYLE is | |
1271 // special only because it can't be followed by an identifier. | |
1272 | |
1273 int kw_token = is_keyword (tok); | |
1274 if (kw_token) | |
1275 { | |
1276 if (kw_token == STYLE) | |
1277 { | |
1278 current_input_column += yyleng; | |
1279 quote_is_transpose = 0; | |
1280 cant_be_identifier = 1; | |
1281 convert_spaces_to_comma = 1; | |
1282 return kw_token; | |
1283 } | |
1284 else | |
1285 TOK_RETURN (kw_token); | |
1286 } | |
1287 | |
1288 // See if we have a plot keyword (title, using, or with). | |
1289 | |
1290 if (plotting && cant_be_identifier && is_plot_keyword (tok); | |
1291 TOK_RETURN (plot_option_kw); | |
1292 | |
1293 // Yes, we really do need both of these plot_range variables. One | |
1294 // is used to mark when we are past all possiblity of a plot range, | |
1295 // the other is used to mark when we are actually between the square | |
1296 // brackets that surround the range. | |
1297 | |
1298 if (plotting && ! in_plot_range) | |
1299 past_plot_range = 1; | |
1300 | |
1301 // It is always an error for an identifier to be followed directly by | |
1302 // another identifier. | |
1303 | |
1304 cant_be_identifier = 1; | |
1305 | |
1306 // If we are looking at a text style function, set up to gobble its | |
1307 // arguments. These are also reserved words, but only because it | |
1308 // would be very difficult to do anything intelligent with them if | |
1309 // they were not reserved. | |
1310 | |
1311 if (is_text_function_name (tok)) | |
1312 { | |
1313 BEGIN TEXT_FCN; | |
1314 | |
1315 if (strcmp (tok, "clear") == 0) | |
1316 { | |
1317 symbol_record *sr = global_sym_tab->lookup ("clear", 1, 0); | |
1318 | |
1319 assert (sr != (symbol_record *) NULL); | |
1320 | |
1321 yylval.tok_val = new token (sr, input_line_number, | |
1322 current_input_column); | |
1323 | |
1324 token_stack.push (yylval.tok_val); | |
1325 | |
1326 return CLEAR; | |
1327 } | |
1328 else if (strcmp (tok, "help") == 0) | |
1329 BEGIN HELP_FCN; | |
1330 else if (strcmp (tok, "set") == 0) | |
1331 doing_set = 1; | |
1332 } | |
1333 | |
1334 // Make sure we put the return values of a function in the symbol | |
1335 // table that is local to the function. | |
1336 | |
1337 if (next_tok_is_eq && defining_func && maybe_screwed) | |
1338 curr_sym_tab = tmp_local_sym_tab; | |
1339 | |
1340 // Find the token in the symbol table. | |
1341 | |
1342 yylval.tok_val = new token (lookup_identifier (tok), | |
1343 input_line_number, | |
1344 current_input_column); | |
1345 | |
1346 token_stack.push (yylval.tok_val); | |
1347 | |
1348 // After seeing an identifer, it is ok to convert spaces to a comma | |
1349 // (if needed). | |
1350 | |
1351 convert_spaces_to_comma = 1; | |
1352 current_input_column += yyleng; | |
1353 | |
1354 // If we are defining a function and we have not seen the parameter | |
1355 // list yet and the next token is `=', return a token that represents | |
1356 // the only return value for the function. For example, | |
1357 // | |
1358 // function SCREW = f (args); | |
1359 // | |
1360 // The variable maybe_screwed is reset in parse.y. | |
1361 | |
1362 if (next_tok_is_eq) | |
1363 { | |
1364 if (defining_func && maybe_screwed) | |
1365 return SCREW; | |
1366 else | |
1367 return NAME; | |
1368 } | |
1369 | |
1370 // At this point, we are only dealing with identifiers that are not | |
1371 // followed by `=' (if the next token is `=', there is no need to | |
1372 // check to see if we should insert a comma (invalid syntax), or allow | |
1373 // a following `'' to be treated as a transpose (the next token is | |
1374 // `=', so it can't be `''. | |
1375 | |
1376 quote_is_transpose = 1; | |
1377 do_comma_insert_check (); | |
1378 | |
1379 // Check to see if we should insert a comma. | |
1380 | |
1381 if (! in_brace_or_paren.empty () && in_brace_or_paren.top ()) | |
1382 { | |
1383 int c0 = yytext[yyleng-1]; | |
1384 int spc_prev = (c0 == ' ' || c0 == '\t'); | |
1385 int bin_op = next_token_is_bin_op (spc_prev, yytext); | |
1386 | |
1387 int postfix_un_op = next_token_is_postfix_unary_op (spc_prev, | |
1388 yytext); | |
1389 | |
1390 int c1 = yyinput (); | |
1391 unput (c1); | |
1392 int other_op = match_any (c1, ",;\n]("); | |
1393 | |
1394 if (! (postfix_un_op || bin_op || other_op)) | |
1395 unput (','); | |
1396 } | |
1397 | |
1398 return NAME; | |
1399 } | |
1400 | |
1401 /* | |
1402 * Print a warning if an M-file that defines a function has anything | |
1403 * other than comments and whitespace following the END token that | |
1404 * matches the FUNCTION statement. | |
1405 */ | |
1368 void | 1406 void |
1369 check_for_garbage_after_fcn_def (void) | 1407 check_for_garbage_after_fcn_def (void) |
1370 { | 1408 { |
1371 // By making a newline be the next character to be read, we will force | 1409 // By making a newline be the next character to be read, we will force |
1372 // the parser to return after reading the function. Calling yyunput | 1410 // the parser to return after reading the function. Calling yyunput |