[Top][All Lists]
[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) {