mirror of
https://github.com/stedolan/jq.git
synced 2024-05-11 05:55:39 +00:00
Resolve shift/reduce conflict of 'def' vs '|'
This was an important conflict. In the following expression: def a: 0; . | a Bison needs to decide between these two equally valid parses: (def a: 0; .) | a def a: 0; (. | a) For jq we want the second one, because the first results in "a/0 is not defined". In the current parser the first parse is a reduce and the second parse is a shift. Since Bison prefers to shift in shift/reduce conflicts, we accidentally got the correct behavior. This commit adds a precedence level FUNCDEF which is lower precedence than '|', meaning we explicitly choose the correct parse. Of course many unit tests already cover this case, but I added one specifically for it.
This commit is contained in:
6
parser.h
6
parser.h
@@ -105,7 +105,8 @@ struct lexer_param;
|
||||
QQSTRING_TEXT = 296,
|
||||
QQSTRING_INTERP_START = 297,
|
||||
QQSTRING_INTERP_END = 298,
|
||||
QQSTRING_END = 299
|
||||
QQSTRING_END = 299,
|
||||
FUNCDEF = 300
|
||||
};
|
||||
#endif
|
||||
/* Tokens. */
|
||||
@@ -151,6 +152,7 @@ struct lexer_param;
|
||||
#define QQSTRING_INTERP_START 297
|
||||
#define QQSTRING_INTERP_END 298
|
||||
#define QQSTRING_END 299
|
||||
#define FUNCDEF 300
|
||||
|
||||
/* Value type. */
|
||||
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
||||
@@ -162,7 +164,7 @@ union YYSTYPE
|
||||
jv literal;
|
||||
block blk;
|
||||
|
||||
#line 166 "parser.h" /* yacc.c:1909 */
|
||||
#line 168 "parser.h" /* yacc.c:1909 */
|
||||
};
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
# define YYSTYPE_IS_DECLARED 1
|
||||
|
5
parser.y
5
parser.y
@@ -91,8 +91,9 @@ struct lexer_param;
|
||||
%token QQSTRING_END
|
||||
|
||||
/* see Exp '?' rule */
|
||||
%expect 34
|
||||
%expect 9
|
||||
|
||||
%precedence FUNCDEF
|
||||
%right '|'
|
||||
%left ','
|
||||
%right "//"
|
||||
@@ -306,7 +307,7 @@ FuncDef FuncDefs {
|
||||
}
|
||||
|
||||
Exp:
|
||||
FuncDef Exp %prec ';' {
|
||||
FuncDef Exp %prec FUNCDEF {
|
||||
$$ = block_bind_referenced($1, $2, OP_IS_CALL_PSEUDO);
|
||||
} |
|
||||
|
||||
|
@@ -553,6 +553,11 @@ def f(a;b;c;d;e;f): [a+1,b,c,d,e,f]; f(.[0];.[1];.[0];.[0];.[0];.[0])
|
||||
[1,2]
|
||||
[2,2,1,1,1,1]
|
||||
|
||||
# Test precedence of 'def' vs '|'
|
||||
def a: 0; . | a
|
||||
null
|
||||
0
|
||||
|
||||
# Many arguments
|
||||
def f(a;b;c;d;e;f;g;h;i;j): [j,i,h,g,f,e,d,c,b,a]; f(.[0];.[1];.[2];.[3];.[4];.[5];.[6];.[7];.[8];.[9])
|
||||
[0,1,2,3,4,5,6,7,8,9]
|
||||
|
Reference in New Issue
Block a user