From bd6aa17bde428b4b9db1459ff9f5ec290d61e60a Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Thu, 7 Sep 2017 22:11:39 -0700 Subject: parser: fix precedence of DOTDOT. The problem is that a.b .. c.d parses as (qref a b..c d), which is useless and counterintuitive. Let's fix it, but with a backward compatibility switch to give more leeway to any hapless people out there whose code happens to depend on this unfortunate situation. We basically use two token numbers for the .. token: OLD_DOTDOT, and DOTDOT. Both are wired into the grammar. In backward compatibility mode, the lexer pumps out OLD_DOTDOT. Otherwise DOTDOT. * parser.l (grammar): When .. is scanned, return OLD_DOTDOT when in compatibility with 185 or earlier. Otherwise DOTDOT. * parser.y (OLD_DOTDOT): New terminal symbol; introduced at the same high precedence previously occupied by DOTDOT. (DOTDOT): Changes precedence to lower than '.' and UREFDOT. (n_expr): Two productions added involving OLD_DOTDOT. These are copy and paste of the existing productions involving DOTDOT; the only difference is that OLD_DOTDOT replaces DOTDOT. (yybadtoken): Handle OLD_DOTDOT. * txr.1: Compat notes added. --- parser.l | 2 +- parser.y | 15 ++++++++++++++- txr.1 | 19 +++++++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/parser.l b/parser.l index 501f878c..3f595e4f 100644 --- a/parser.l +++ b/parser.l @@ -702,7 +702,7 @@ UONLY {U2}{U}|{U3}{U}{U}|{U4}{U}{U}{U} {WS}\.\. { yylval->lineno = yyextra->lineno; - return DOTDOT; + return (opt_compat && opt_compat <= 185) ? OLD_DOTDOT : DOTDOT; } @ { diff --git a/parser.y b/parser.y index a29403f0..72dff861 100644 --- a/parser.y +++ b/parser.y @@ -122,6 +122,7 @@ INLINE val expand_form_ver(val form, int ver) %token HASH_B_QUOTE %token WORDS WSPLICE QWORDS QWSPLICE %token SECRET_ESCAPE_R SECRET_ESCAPE_E SECRET_ESCAPE_I +%token OLD_DOTDOT %token NUMBER METANUM %token HASH_N_EQUALS HASH_N_HASH @@ -162,8 +163,9 @@ INLINE val expand_form_ver(val form, int ver) %left '|' '/' %left '&' %right '~' '*' '?' '+' '%' -%right '.' CONSDOT LAMBDOT UREFDOT REGCHAR REGTOKEN LITCHAR %right DOTDOT +%right '.' CONSDOT LAMBDOT UREFDOT REGCHAR REGTOKEN LITCHAR +%right OLD_DOTDOT %% @@ -1015,6 +1017,16 @@ n_expr : SYMTOK { $$ = symhlpr($1, t); } uref_helper(parser, $4), nao), or2($1, $4)); } + | n_expr OLD_DOTDOT n_expr + { uses_or2; + $$ = rlcp(list(rcons_s, $1, $3, nao), + or2($1, $3)); } + | n_expr OLD_DOTDOT '.' n_expr + { uses_or2; + $$ = rlcp(list(rcons_s, $1, + uref_helper(parser, $4), + nao), + or2($1, $4)); } | n_expr '.' n_expr { uses_or2; if (consp($3) && car($3) == qref_s) { rplacd($3, rlcp(cons($1, cdr($3)), $1)); @@ -1782,6 +1794,7 @@ void yybadtoken(parser_t *parser, int tok, val context) case CONSDOT: problem = lit("consing dot"); break; case LAMBDOT: problem = lit("consing dot"); break; case DOTDOT: problem = lit(".."); break; + case OLD_DOTDOT: problem = lit(".."); break; case HASH_BACKSLASH: problem = lit("#\\"); break; case HASH_SLASH: problem = lit("#/"); break; case HASH_H: problem = lit("#H"); break; diff --git a/txr.1 b/txr.1 index e288d7ab..ec7ca80f 100644 --- a/txr.1 +++ b/txr.1 @@ -61407,6 +61407,25 @@ is that user code which binds custom macros to or .code sys:expr may be affected by 184 or lower compatibility. +.IP 185 +A value of 185 or lower restores the old precedence of the +double dot notation for expressing ranges, relative to the +referencing dot. Until \*(TX 185, the expression +.code a.b..c.d +parsed as +.codn "(qref a (rcons b c) d)" . +What is worse, it parsed this way even if written as +.codn "a.b .. c.d" . +Starting in \*(TX 186, +.code .. +has a lower precedence, producing the more useful and intuitive parse +.codn "(rcons (qref a b) (qref c d))" : +in other words, the range with endpoints given by +.code a.b +and +.codn c.d . + + .IP 183 A value of 183 or lower restores an inconsistent behavior in the .code "@(bind)" -- cgit v1.2.3