bug-gnu-utils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: BUG? report on Gawk


From: Stepan Kasal
Subject: Re: BUG? report on Gawk
Date: Mon, 16 Sep 2002 12:27:40 +0200
User-agent: Mutt/1.2.5.1i

Good morning,

On Fri, Sep 13, 2002 at 09:40:48PM +0900, Kenshu KAMIYA wrote about
a bug in gawk, versions 3.0.4 till 3.1.1 (current):
>
>     { x[1,1] /= 2 }
>
is parsed incorrectly.

Arnold Robbins has immediately provided a patch.  But the patch has
problems with parsing eg. this:

        y[ x[1,1] /= 2 ] = 1

I've chosen another approach to fix the bug, try it if you want.

Since my patch is a bit longer then Arnold's, there is a bigger chance
that it will break something else.  But hopefully not :-).

Stepan Kasal


diff -urpN gawk-3.1.1.orig/awkgram.y gawk-3.1.1/awkgram.y
--- gawk-3.1.1.orig/awkgram.y   Tue Apr 16 13:40:13 2002
+++ gawk-3.1.1/awkgram.y        Mon Sep 16 12:12:28 2002
@@ -63,7 +63,6 @@ enum defref { FUNC_DEFINE, FUNC_USE };
 static void func_use P((char *name, enum defref how));
 static void check_funcs P((void));
 
-static int want_assign;                /* lexical scanning kludge */
 static int want_regexp;                /* lexical scanning kludge */
 static int can_return;         /* lexical scanning kludge */
 static int io_allowed = TRUE;  /* lexical scanning kludge */
@@ -115,6 +114,7 @@ extern NODE *end_block;
 %type <nodeval> opt_exp opt_variable regexp 
 %type <nodeval> input_redir output_redir
 %type <nodetypeval> print
+%type <nodetypeval> assign_operator
 %type <sval> func_name
 %type <lval> lex_builtin
 
@@ -122,7 +122,7 @@ extern NODE *end_block;
 %token <lval> ERROR
 %token <nodeval> YNUMBER YSTRING
 %token <nodetypeval> RELOP APPEND_OP
-%token <nodetypeval> ASSIGNOP MATCHOP NEWLINE CONCAT_OP
+%token <nodetypeval> ASSIGNOP ASSIGN MATCHOP CONCAT_OP
 %token <nodetypeval> LEX_BEGIN LEX_END LEX_IF LEX_ELSE LEX_RETURN LEX_DELETE
 %token <nodetypeval> LEX_WHILE LEX_DO LEX_FOR LEX_BREAK LEX_CONTINUE
 %token <nodetypeval> LEX_PRINT LEX_PRINTF LEX_NEXT LEX_EXIT LEX_FUNCTION
@@ -130,11 +130,12 @@ extern NODE *end_block;
 %token <nodetypeval> LEX_IN
 %token <lval> LEX_AND LEX_OR INCREMENT DECREMENT
 %token <lval> LEX_BUILTIN LEX_LENGTH
+%token NEWLINE
 
 /* these are just yylval numbers */
 
 /* Lowest to highest */
-%right ASSIGNOP
+%right ASSIGNOP ASSIGN SLASH_BEFORE_EQUAL
 %right '?' ':'
 %left LEX_OR
 %left LEX_AND
@@ -328,7 +329,7 @@ regexp
         * In this rule, want_regexp tells yylex that the next thing
         * is a regexp so it should read up to the closing slash.
         */
-       : '/'
+       : a_slash
                { ++want_regexp; }
          REGEXP '/'
                {
@@ -347,6 +348,11 @@ regexp
                }
        ;
 
+a_slash
+       : '/'
+       | SLASH_BEFORE_EQUAL
+       ;
+
 action
        : l_brace statements r_brace opt_semi opt_nls
                { $$ = $2; }
@@ -572,7 +578,6 @@ if_statement
 
 nls
        : NEWLINE
-               { want_assign = FALSE; }
        | nls NEWLINE
        ;
 
@@ -686,14 +691,20 @@ expression_list
                { $$ = NULL; }
        ;
 
+assign_operator
+       : ASSIGN
+               { $$ = $1; }
+       | ASSIGNOP
+               { $$ = $1; }
+       | SLASH_BEFORE_EQUAL ASSIGN   /* `/=' */
+               { $$ = Node_assign_quotient; }
+
 /* Expressions, not including the comma operator.  */
-exp    : variable ASSIGNOP 
-               { want_assign = FALSE; }
-         exp
+exp    : variable assign_operator exp
                {
-                 if (do_lint && $4->type == Node_regex)
+                 if (do_lint && $3->type == Node_regex)
                        lintwarn(_("regular expression on right of 
assignment"));
-                 $$ = node($1, $2, $4);
+                 $$ = node($1, $2, $3);
                }
        | '(' expression_list r_paren LEX_IN NAME
                { $$ = node(variable($5, CAN_FREE, Node_var_array), 
Node_in_array, $2); }
@@ -762,10 +773,8 @@ exp        : variable ASSIGNOP 
        ;
 
 rexp   
-       : variable ASSIGNOP 
-               { want_assign = FALSE; }
-         rexp
-               { $$ = node($1, $2, $4); }
+       : variable assign_operator rexp
+               { $$ = node($1, $2, $3); }
        | rexp LEX_AND rexp
                { $$ = node($1, Node_and, $3); }
        | rexp LEX_OR rexp
@@ -910,7 +919,7 @@ opt_semi
        ;
 
 semi
-       : ';'   { yyerrok; want_assign = FALSE; }
+       : ';'   { yyerrok; }
        ;
 
 comma  : ',' opt_nls   { yyerrok; }
@@ -1624,7 +1633,6 @@ retry:
                break;
 
        case '$':
-               want_assign = TRUE;
                return lasttok = '$';
 
        case ':':
@@ -1638,8 +1646,6 @@ retry:
        case ';':
        case '{':
        case ',':
-               want_assign = FALSE;
-               /* fall through */
        case '[':
        case ']':
                return lasttok = c;
@@ -1681,13 +1687,11 @@ retry:
                return lasttok = '*';
 
        case '/':
-               if (want_assign) {
-                       if (nextc() == '=') {
-                               yylval.nodetypeval = Node_assign_quotient;
-                               return lasttok = ASSIGNOP;
-                       }
+               if (nextc() == '=') {
                        pushback();
+                       return lasttok = SLASH_BEFORE_EQUAL;
                }
+               pushback();
                return lasttok = '/';
 
        case '%':
@@ -1735,7 +1739,6 @@ retry:
                }
                if (c == '~') {
                        yylval.nodetypeval = Node_nomatch;
-                       want_assign = FALSE;
                        return lasttok = MATCHOP;
                }
                pushback();
@@ -1757,7 +1760,7 @@ retry:
                }
                yylval.nodetypeval = Node_assign;
                pushback();
-               return lasttok = ASSIGNOP;
+               return lasttok = ASSIGN;
 
        case '>':
                if ((c = nextc()) == '=') {
@@ -1773,7 +1776,6 @@ retry:
 
        case '~':
                yylval.nodetypeval = Node_match;
-               want_assign = FALSE;
                return lasttok = MATCHOP;
 
        case '}':
@@ -1947,7 +1949,6 @@ retry:
                if ((c = nextc()) == '&') {
                        yylval.nodetypeval = Node_and;
                        allow_newline();
-                       want_assign = FALSE;
                        return lasttok = LEX_AND;
                }
                pushback();
@@ -1957,11 +1958,9 @@ retry:
                if ((c = nextc()) == '|') {
                        yylval.nodetypeval = Node_or;
                        allow_newline();
-                       want_assign = FALSE;
                        return lasttok = LEX_OR;
                } else if (! do_traditional && c == '&') {
                        yylval.nodetypeval = Node_redirect_twoway;
-                       want_assign = FALSE;
                        return lasttok = TWOWAYIO;
                }
                pushback();
@@ -2062,7 +2061,6 @@ retry:
        else {
                static short goto_warned = FALSE;
 
-               want_assign = TRUE;
 #define SMART_ALECK    1
                if (SMART_ALECK && do_lint
                    && ! goto_warned && strcasecmp(tokkey, "goto") == 0) {




reply via email to

[Prev in Thread] Current Thread [Next in Thread]