BETWEEN SYMMETRIC/ASYMMETRIC

Started by Christopher Kings-Lynnealmost 24 years ago3 messages
#1Christopher Kings-Lynne
chriskl@familyhealth.com.au

Hi All,

As part of my ongoing quest to understand grammar files, I've been trying to
implement BETWEEN SYMMETRIC/ASYMMETRIC.

I've attached my current work. Can someone please look and tell me if I'm
on the right track? With this patch, I get parse errors after BETWEEN if I
go:

SELECT 2 BETWEEN ASYMMETRIC 1 and 3;

or

SELECT 2 BETWEEN SYMMETRIC 1 and 3;

So it doesn't seem to be working - I don't know why!!

Don't look at the NOT BETWEEN stuff - I've not done it yet.

I was forced to put SYMMETRIC and ASYMMETRIC as reserved words - anything
else seemed to give shift/reduce errors. Is there anything I can do about
that?

Chris

#2Christopher Kings-Lynne
chriskl@familyhealth.com.au
In reply to: Christopher Kings-Lynne (#1)
1 attachment(s)
Re: BETWEEN SYMMETRIC/ASYMMETRIC

*sigh*

I actually attached the diff this time...

Chris

Show quoted text

-----Original Message-----
From: pgsql-hackers-owner@postgresql.org
[mailto:pgsql-hackers-owner@postgresql.org]On Behalf Of Christopher
Kings-Lynne
Sent: Wednesday, 3 April 2002 12:26 PM
To: Hackers
Subject: [HACKERS] BETWEEN SYMMETRIC/ASYMMETRIC

Hi All,

As part of my ongoing quest to understand grammar files, I've
been trying to
implement BETWEEN SYMMETRIC/ASYMMETRIC.

I've attached my current work. Can someone please look and tell me if I'm
on the right track? With this patch, I get parse errors after
BETWEEN if I
go:

SELECT 2 BETWEEN ASYMMETRIC 1 and 3;

or

SELECT 2 BETWEEN SYMMETRIC 1 and 3;

So it doesn't seem to be working - I don't know why!!

Don't look at the NOT BETWEEN stuff - I've not done it yet.

I was forced to put SYMMETRIC and ASYMMETRIC as reserved words - anything
else seemed to give shift/reduce errors. Is there anything I can do about
that?

Chris

---------------------------(end of broadcast)---------------------------
TIP 2: you can get off all lists at once with the unregister command
(send "unregister YourEmailAddressHere" to majordomo@postgresql.org)

Attachments:

between.txttext/plain; name=between.txtDownload
Index: src/backend/parser/gram.y
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/parser/gram.y,v
retrieving revision 2.299
diff -c -r2.299 gram.y
*** src/backend/parser/gram.y	2002/04/01 04:35:38	2.299
--- src/backend/parser/gram.y	2002/04/03 04:21:13
***************
*** 148,154 ****
  				simple_select
  
  %type <node>    alter_column_default
! %type <ival>    drop_behavior, opt_drop_behavior
  
  %type <list>	createdb_opt_list, createdb_opt_item
  %type <boolean>	opt_equal
--- 148,154 ----
  				simple_select
  
  %type <node>    alter_column_default
! %type <ival>    drop_behavior, opt_drop_behavior, opt_asymmetry
  
  %type <list>	createdb_opt_list, createdb_opt_item
  %type <boolean>	opt_equal
***************
*** 344,350 ****
  		IMMEDIATE, INITIALLY, INOUT,
  		OFF, OUT,
  		PATH_P, PENDANT,
! 		REPLACE, RESTRICT,
          TRIGGER,
  		WITHOUT
  
--- 344,350 ----
  		IMMEDIATE, INITIALLY, INOUT,
  		OFF, OUT,
  		PATH_P, PENDANT,
! 		REPLACE, RESTRICT, SYMMETRIC, ASYMMETRIC,
          TRIGGER,
  		WITHOUT
  
***************
*** 4948,4964 ****
  					b->booltesttype = IS_NOT_UNKNOWN;
  					$$ = (Node *)b;
  				}
! 		| a_expr BETWEEN b_expr AND b_expr			%prec BETWEEN
  				{
! 					$$ = makeA_Expr(AND, NULL,
! 						makeA_Expr(OP, ">=", $1, $3),
! 						makeA_Expr(OP, "<=", $1, $5));
  				}
! 		| a_expr NOT BETWEEN b_expr AND b_expr		%prec BETWEEN
  				{
  					$$ = makeA_Expr(OR, NULL,
! 						makeA_Expr(OP, "<", $1, $4),
! 						makeA_Expr(OP, ">", $1, $6));
  				}
  		| a_expr IN in_expr
  				{
--- 4948,4975 ----
  					b->booltesttype = IS_NOT_UNKNOWN;
  					$$ = (Node *)b;
  				}
! 		| a_expr BETWEEN opt_asymmetry b_expr AND b_expr			%prec BETWEEN
  				{
! 					if ($3 == SYMMETRIC)
! 						$$ = makeA_Expr(OR, NULL,
! 							makeA_Expr(AND, NULL,
! 								makeA_Expr(OP, ">=", $1, $4),
! 								makeA_Expr(OP, "<=", $1, $6)),
! 							makeA_Expr(AND, NULL,
! 								makeA_Expr(OP, ">=", $1, $6),
! 								makeA_Expr(OP, "<=", $1, $4))
! 						);
! 					else
! 						$$ = makeA_Expr(AND, NULL,
! 								makeA_Expr(OP, ">=", $1, $4),
! 								makeA_Expr(OP, "<=", $1, $6));
! 
  				}
! 		| a_expr NOT BETWEEN opt_asymmetry b_expr AND b_expr		%prec BETWEEN
  				{
  					$$ = makeA_Expr(OR, NULL,
! 						makeA_Expr(OP, "<", $1, $5),
! 						makeA_Expr(OP, ">", $1, $7));
  				}
  		| a_expr IN in_expr
  				{
***************
*** 5663,5668 ****
--- 5674,5685 ----
  					| /*EMPTY*/ { $$ = TRUE; }
  		;
  
+ opt_asymmetry: ASYMMETRIC			{ $$ = ASYMMETRIC; }
+ 		| SYMMETRIC						{ $$ = SYMMETRIC; }
+ 		| /* EMPTY */					{ $$ = ASYMMETRIC; /* default */ }
+ 		;
+ 
+ 
  /*****************************************************************************
   *
   *	target lists
***************
*** 6190,6195 ****
--- 6207,6213 ----
  		| AND							{ $$ = "and"; }
  		| ANY							{ $$ = "any"; }
  		| AS							{ $$ = "as"; }
+ 		| ASYMMETRIC						{ $$ = "asymmetric"; }
  		| ASC							{ $$ = "asc"; }
  		| BOTH							{ $$ = "both"; }
  		| CASE							{ $$ = "case"; }
***************
*** 6238,6243 ****
--- 6256,6262 ----
  		| SELECT						{ $$ = "select"; }
  		| SESSION_USER					{ $$ = "session_user"; }
  		| SOME							{ $$ = "some"; }
+ 		| SYMMETRIC						{ $$ = "symmetric"; }
  		| TABLE							{ $$ = "table"; }
  		| THEN							{ $$ = "then"; }
  		| TO							{ $$ = "to"; }
#3Tom Lane
tgl@sss.pgh.pa.us
In reply to: Christopher Kings-Lynne (#1)
Re: BETWEEN SYMMETRIC/ASYMMETRIC

"Christopher Kings-Lynne" <chriskl@familyhealth.com.au> writes:

I was forced to put SYMMETRIC and ASYMMETRIC as reserved words - anything
else seemed to give shift/reduce errors. Is there anything I can do about
that?

First thought is "don't try to be cute": forget the opt_asymmetry
clause, and instead spell out six productions

a_expr BETWEEN b_expr AND b_expr
a_expr NOT BETWEEN b_expr AND b_expr
a_expr BETWEEN SYMMETRIC b_expr AND b_expr
a_expr NOT BETWEEN SYMMETRIC b_expr AND b_expr
a_expr BETWEEN ASYMMETRIC b_expr AND b_expr
a_expr NOT BETWEEN ASYMMETRIC b_expr AND b_expr

I have not checked that this will work, but usually the cure for parse
conflicts is to postpone the decision about which production applies.
The reason opt_asymmetry forces SYMMETRIC and ASYMMETRIC to become
reserved is that it requires a premature decision. Given, say

a_expr BETWEEN . SYMMETRIC

(where . means "where we are now" and SYMMETRIC is the current lookahead
token), an LR(1) parser *must* decide whether to reduce opt_asymmetry as
null, or to shift (implying that opt_asymmetry will be SYMMETRIC); it
has to make this choice before it can look beyond the SYMMETRIC token.
If SYMMETRIC might be a regular identifier then this is unresolvable
without more lookahead. The six-production approach avoids this problem
by not requiring any shift/reduce decisions to be made until an entire
clause is available.

On second thought there may be no other way out. Consider

foo BETWEEN SYMMETRIC - bar AND baz

Is SYMMETRIC a keyword (with "-" a prefix operator) or an identifier
(with "-" infix)? This example makes me think that SYMMETRIC has to
become reserved. But I wanted to point out that opt_asymmetry is
certainly a loser based on lookahead distance.

regards, tom lane