Hi all,

I'm working on a fairly large patch (cleaning up Karel Zak's
PREPARE/EXECUTE work), and I'm having some problems with bison (I'm
a yacc newbie). In fact, my grammar currently has an obscene
20 shift/reduce and 4 reduce/reduce conflicts!

Would someone to be kind enough to let me know what I'm doing wrong,
and what I'll need to change? (Unfortunately, bison isn't very
helpful: it doesn't provide line-numbers when it warns me about
the # of conflicts). The patch for gram.y is below.

Thanks in advance,

Neil

-- 
Neil Conway <neilconway@rogers.com>
PGP Key ID: DB3C29FC

Index: gram.y
===================================================================
RCS file: /var/lib/cvs/pgsql/src/backend/parser/gram.y,v
retrieving revision 2.299
diff -c -r2.299 gram.y
*** gram.y	1 Apr 2002 04:35:38 -0000	2.299
--- gram.y	11 Apr 2002 01:26:21 -0000
***************
*** 133,144 ****
  		ClosePortalStmt, ClusterStmt, CommentStmt, ConstraintsSetStmt,
  		CopyStmt, CreateAsStmt, CreateDomainStmt, CreateGroupStmt, CreatePLangStmt,
  		CreateSchemaStmt, CreateSeqStmt, CreateStmt, CreateTrigStmt,
! 		CreateUserStmt, CreatedbStmt, CursorStmt, DefineStmt, DeleteStmt,
! 		DropGroupStmt, DropPLangStmt, DropSchemaStmt, DropStmt, DropTrigStmt,
! 		DropUserStmt, DropdbStmt, ExplainStmt, FetchStmt,
  		GrantStmt, IndexStmt, InsertStmt, ListenStmt, LoadStmt, LockStmt,
! 		NotifyStmt, OptimizableStmt, ProcedureStmt, ReindexStmt,
! 		RemoveAggrStmt, RemoveFuncStmt, RemoveOperStmt,
  		RenameStmt, RevokeStmt, RuleActionStmt, RuleActionStmtOrEmpty,
  		RuleStmt, SelectStmt, TransactionStmt, TruncateStmt,
  		UnlistenStmt, UpdateStmt, VacuumStmt, VariableResetStmt,
--- 133,145 ----
  		ClosePortalStmt, ClusterStmt, CommentStmt, ConstraintsSetStmt,
  		CopyStmt, CreateAsStmt, CreateDomainStmt, CreateGroupStmt, CreatePLangStmt,
  		CreateSchemaStmt, CreateSeqStmt, CreateStmt, CreateTrigStmt,
! 		CreateUserStmt, CreatedbStmt, CursorStmt, DeallocatePrepareStmt,
! 		DefineStmt, DeleteStmt, DropGroupStmt,
! 		DropPLangStmt, DropSchemaStmt, DropStmt, DropTrigStmt,
! 		DropUserStmt, DropdbStmt, ExecuteStmt, ExplainStmt, FetchStmt,
  		GrantStmt, IndexStmt, InsertStmt, ListenStmt, LoadStmt, LockStmt,
! 		NotifyStmt, OptimizableStmt, ProcedureStmt, PrepareStmt, prepare_query,
! 		ReindexStmt, RemoveAggrStmt, RemoveFuncStmt, RemoveOperStmt,
  		RenameStmt, RevokeStmt, RuleActionStmt, RuleActionStmtOrEmpty,
  		RuleStmt, SelectStmt, TransactionStmt, TruncateStmt,
  		UnlistenStmt, UpdateStmt, VacuumStmt, VariableResetStmt,
***************
*** 204,210 ****
  		any_name, any_name_list, expr_list, dotted_name, attrs,
  		target_list, update_target_list, insert_column_list,
  		def_list, opt_indirection, group_clause, TriggerFuncArgs,
! 		select_limit, opt_select_limit
  
  %type <range>	into_clause, OptTempTableName
  
--- 205,214 ----
  		any_name, any_name_list, expr_list, dotted_name, attrs,
  		target_list, update_target_list, insert_column_list,
  		def_list, opt_indirection, group_clause, TriggerFuncArgs,
! 		select_limit, opt_select_limit, types_list,
! 		types_prepare_clause, execute_using
! 
! %type <ival>	prepare_store
  
  %type <range>	into_clause, OptTempTableName
  
***************
*** 319,325 ****
  		COALESCE, COLLATE, COLUMN, COMMIT,
  		CONSTRAINT, CONSTRAINTS, CREATE, CROSS, CURRENT_DATE,
  		CURRENT_TIME, CURRENT_TIMESTAMP, CURRENT_USER, CURSOR,
! 		DAY_P, DEC, DECIMAL, DECLARE, DEFAULT, DELETE, DESC,
  		DISTINCT, DOUBLE, DROP,
  		ELSE, ENCRYPTED, END_TRANS, ESCAPE, EXCEPT, EXECUTE, EXISTS, EXTRACT,
  		FALSE_P, FETCH, FLOAT, FOR, FOREIGN, FROM, FULL,
--- 323,329 ----
  		COALESCE, COLLATE, COLUMN, COMMIT,
  		CONSTRAINT, CONSTRAINTS, CREATE, CROSS, CURRENT_DATE,
  		CURRENT_TIME, CURRENT_TIMESTAMP, CURRENT_USER, CURSOR,
! 		DAY_P, DEALLOCATE, DEC, DECIMAL, DECLARE, DEFAULT, DELETE, DESC,
  		DISTINCT, DOUBLE, DROP,
  		ELSE, ENCRYPTED, END_TRANS, ESCAPE, EXCEPT, EXECUTE, EXISTS, EXTRACT,
  		FALSE_P, FETCH, FLOAT, FOR, FOREIGN, FROM, FULL,
***************
*** 329,335 ****
  		MATCH, MINUTE_P, MONTH_P, NAMES,
  		NATIONAL, NATURAL, NCHAR, NEXT, NO, NOT, NULLIF, NULL_P, NUMERIC,
  		OF, OLD, ON, ONLY, OPTION, OR, ORDER, OUTER_P, OVERLAPS,
! 		PARTIAL, POSITION, PRECISION, PRIMARY, PRIOR, PRIVILEGES, PROCEDURE, PUBLIC,
  		READ, REFERENCES, RELATIVE, REVOKE, RIGHT, ROLLBACK,
  		SCHEMA, SCROLL, SECOND_P, SELECT, SESSION, SESSION_USER, SET, SOME, SUBSTRING,
  		TABLE, TEMPORARY, THEN, TIME, TIMESTAMP,
--- 333,339 ----
  		MATCH, MINUTE_P, MONTH_P, NAMES,
  		NATIONAL, NATURAL, NCHAR, NEXT, NO, NOT, NULLIF, NULL_P, NUMERIC,
  		OF, OLD, ON, ONLY, OPTION, OR, ORDER, OUTER_P, OVERLAPS,
! 		PARTIAL, POSITION, PRECISION, PREPARE, PRIMARY, PRIOR, PRIVILEGES, PROCEDURE, PUBLIC,
  		READ, REFERENCES, RELATIVE, REVOKE, RIGHT, ROLLBACK,
  		SCHEMA, SCROLL, SECOND_P, SELECT, SESSION, SESSION_USER, SET, SOME, SUBSTRING,
  		TABLE, TEMPORARY, THEN, TIME, TIMESTAMP,
***************
*** 363,372 ****
  		DATABASE, DELIMITERS, DO,
  		EACH, ENCODING, EXCLUSIVE, EXPLAIN,
  		FORCE, FORWARD, FREEZE, FUNCTION, HANDLER,
! 		ILIKE, INCREMENT, INDEX, INHERITS, INSTEAD, ISNULL,
  		LANCOMPILER, LIMIT, LISTEN, LOAD, LOCATION, LOCK_P,
  		MAXVALUE, MINVALUE, MODE, MOVE,
! 		NEW, NOCREATEDB, NOCREATEUSER, NONE, NOTHING, NOTIFY, NOTNULL,
  		OFFSET, OIDS, OPERATOR, OWNER, PASSWORD, PROCEDURAL,
  		REINDEX, RENAME, RESET, RETURNS, ROW, RULE,
  		SEQUENCE, SETOF, SHARE, SHOW, START, STATEMENT,
--- 367,376 ----
  		DATABASE, DELIMITERS, DO,
  		EACH, ENCODING, EXCLUSIVE, EXPLAIN,
  		FORCE, FORWARD, FREEZE, FUNCTION, HANDLER,
! 		ILIKE, INCREMENT, INDEX, INHERITS, INSTEAD, ISNULL, INTERNAL,
  		LANCOMPILER, LIMIT, LISTEN, LOAD, LOCATION, LOCK_P,
  		MAXVALUE, MINVALUE, MODE, MOVE,
! 		NEW, NOCREATEDB, NOCREATEUSER, NONE, NOSHARE, NOTHING, NOTIFY, NOTNULL,
  		OFFSET, OIDS, OPERATOR, OWNER, PASSWORD, PROCEDURAL,
  		REINDEX, RENAME, RESET, RETURNS, ROW, RULE,
  		SEQUENCE, SETOF, SHARE, SHOW, START, STATEMENT,
***************
*** 460,465 ****
--- 464,470 ----
  		| CreateTrigStmt
  		| CreateUserStmt
  		| ClusterStmt
+ 		| DeallocatePrepareStmt
  		| DefineStmt
  		| DropStmt		
  		| DropSchemaStmt
***************
*** 469,474 ****
--- 474,480 ----
  		| DropPLangStmt
  		| DropTrigStmt
  		| DropUserStmt
+ 		| ExecuteStmt
  		| ExplainStmt
  		| FetchStmt
  		| GrantStmt
***************
*** 477,482 ****
--- 483,489 ----
  		| UnlistenStmt
  		| LockStmt
  		| NotifyStmt
+ 		| PrepareStmt
  		| ProcedureStmt
  		| ReindexStmt
  		| RemoveAggrStmt
***************
*** 3489,3494 ****
--- 3496,3594 ----
  		| DeleteStmt					/* by default all are $$=$1 */
  		;
  
+ /*****************************************************************************
+  *
+  *				PREPARE STATEMENTS
+  *
+  *****************************************************************************/
+ PrepareStmt:  PREPARE name AS prepare_query types_prepare_clause prepare_store
+   				{
+ 					PrepareStmt *n = makeNode(PrepareStmt);
+ 					n->name = $2;
+ 					n->query = (Query *) $4;
+ 					n->types = (List *) $5;
+ 					n->store = $6;
+ 					$$ = (Node *) n;
+ 				}
+ 		;
+ 
+ prepare_query:  SelectStmt
+ 		| UpdateStmt
+ 		| InsertStmt
+ 		| DeleteStmt
+ 		;
+ 
+ types_list:  SimpleTypename
+ 				{ $$ = makeList1($1); }
+ 		| types_list ',' SimpleTypename
+ 				{ $$ = lappend($1, $3); }
+ 		;
+ 
+ types_prepare_clause:  USING types_list		{ $$ = $2; }
+ 		| /*EMPTY*/							{ $$ = NIL; }
+ 		;
+ 
+ prepare_store: NOSHARE		{ $$ = 1; }
+ 		| GLOBAL			{ $$ = 2; }
+ 		| SHARE				{ $$ = 0; }	/* default */
+ 		| /* EMPTY */		{ $$ = 0; }
+ 		;	
+ 
+ /*****************************************************************************
+  *
+  *				EXECUTE STATEMENTS
+  *
+  *****************************************************************************/
+ ExecuteStmt: EXECUTE name into_clause USING execute_using prepare_store
+ 				{
+ 					ExecuteStmt *n = makeNode(ExecuteStmt);
+ 					n->name = $2;
+ 					n->into = $3;
+ 					n->using = $5;
+ 					n->store = $6;
+ 					$$ = (Node *) n;					
+ 				}
+ 		;
+ 
+ execute_using: a_expr
+ 				{ $$ = makeList1($1); }
+ 		| execute_using ',' a_expr
+ 				{ $$ = lappend($1, $3); }
+ 		;
+ 
+ /*****************************************************************************
+  *
+  *				DEALLOCATE PREPARE STATEMENTS
+  *
+  *****************************************************************************/
+ DeallocatePrepareStmt: DEALLOCATE PREPARE ALL
+ 				{
+ 					DeallocatePrepareStmt *n = makeNode(DeallocatePrepareStmt);
+ 					n->name = NULL;
+ 					n->store = 0;
+ 					n->all = TRUE;
+ 					n->internal = FALSE;
+ 					$$ = (Node *) n;
+ 				}
+ 		| DEALLOCATE PREPARE ALL INTERNAL
+ 				{
+ 					DeallocatePrepareStmt *n = makeNode(DeallocatePrepareStmt);
+ 					n->name = NULL;
+ 					n->store = 0;
+ 					n->all = FALSE;
+ 					n->internal = TRUE;
+ 					$$ = (Node *) n;
+ 				}
+ 		| DEALLOCATE PREPARE name prepare_store 
+ 				{
+ 					DeallocatePrepareStmt *n = makeNode(DeallocatePrepareStmt);
+ 					n->name = $3;
+ 					n->store = $4;
+ 					n->all = FALSE;
+ 					n->internal = FALSE;
+ 					$$ = (Node *) n;
+ 				}
+ 		;
  
  /*****************************************************************************
   *

Wed, 10 Apr 2002 21:28:53 -0400
Neil Conway <nconway@klamath.dyndns.org>
help with bison
Neil Conway <nconway@klamath.dyndns.org> writes:
> Unfortunately, bison isn't very
> helpful: it doesn't provide line-numbers when it warns me about
> the # of conflicts.

Run bison with -v switch (thus, "bison -y -d -v gram.y") and look at
the y.output file it produces.  More detail than you really wanted ;-)

			regards, tom lane

Wed, 10 Apr 2002 21:55:08 -0400
Tom Lane <tgl@sss.pgh.pa.us>
Re: help with bison 
I don't see in this patch that you've added your new keywords to any of the
lists of reserved words towards the bottom of gram.y.  Have a look down and
see the lists.  You need to add the keywords to the first list in the file
that doesn't give a shift/reduce error.  (ie. make the words the least
reserved as possible.)

Also, make sure you've put them in keywords.c as well.

Chris

> -----Original Message-----
> From: pgsql-hackers-owner@postgresql.org
> [mailto:pgsql-hackers-owner@postgresql.org]On Behalf Of Neil Conway
> Sent: Thursday, 11 April 2002 9:29 AM
> To: PostgreSQL Hackers
> Subject: [HACKERS] help with bison
>
>
> Hi all,
>
> I'm working on a fairly large patch (cleaning up Karel Zak's
> PREPARE/EXECUTE work), and I'm having some problems with bison (I'm
> a yacc newbie). In fact, my grammar currently has an obscene
> 20 shift/reduce and 4 reduce/reduce conflicts!
>
> Would someone to be kind enough to let me know what I'm doing wrong,
> and what I'll need to change? (Unfortunately, bison isn't very
> helpful: it doesn't provide line-numbers when it warns me about
> the # of conflicts). The patch for gram.y is below.
>
> Thanks in advance,
>
> Neil
>
> --
> Neil Conway <neilconway@rogers.com>
> PGP Key ID: DB3C29FC
>
> Index: gram.y
> ===================================================================
> RCS file: /var/lib/cvs/pgsql/src/backend/parser/gram.y,v
> retrieving revision 2.299
> diff -c -r2.299 gram.y
> *** gram.y	1 Apr 2002 04:35:38 -0000	2.299
> --- gram.y	11 Apr 2002 01:26:21 -0000
> ***************
> *** 133,144 ****
>   		ClosePortalStmt, ClusterStmt, CommentStmt,
> ConstraintsSetStmt,
>   		CopyStmt, CreateAsStmt, CreateDomainStmt,
> CreateGroupStmt, CreatePLangStmt,
>   		CreateSchemaStmt, CreateSeqStmt, CreateStmt, CreateTrigStmt,
> ! 		CreateUserStmt, CreatedbStmt, CursorStmt,
> DefineStmt, DeleteStmt,
> ! 		DropGroupStmt, DropPLangStmt, DropSchemaStmt,
> DropStmt, DropTrigStmt,
> ! 		DropUserStmt, DropdbStmt, ExplainStmt, FetchStmt,
>   		GrantStmt, IndexStmt, InsertStmt, ListenStmt,
> LoadStmt, LockStmt,
> ! 		NotifyStmt, OptimizableStmt, ProcedureStmt, ReindexStmt,
> ! 		RemoveAggrStmt, RemoveFuncStmt, RemoveOperStmt,
>   		RenameStmt, RevokeStmt, RuleActionStmt,
> RuleActionStmtOrEmpty,
>   		RuleStmt, SelectStmt, TransactionStmt, TruncateStmt,
>   		UnlistenStmt, UpdateStmt, VacuumStmt, VariableResetStmt,
> --- 133,145 ----
>   		ClosePortalStmt, ClusterStmt, CommentStmt,
> ConstraintsSetStmt,
>   		CopyStmt, CreateAsStmt, CreateDomainStmt,
> CreateGroupStmt, CreatePLangStmt,
>   		CreateSchemaStmt, CreateSeqStmt, CreateStmt, CreateTrigStmt,
> ! 		CreateUserStmt, CreatedbStmt, CursorStmt,
> DeallocatePrepareStmt,
> ! 		DefineStmt, DeleteStmt, DropGroupStmt,
> ! 		DropPLangStmt, DropSchemaStmt, DropStmt, DropTrigStmt,
> ! 		DropUserStmt, DropdbStmt, ExecuteStmt, ExplainStmt,
> FetchStmt,
>   		GrantStmt, IndexStmt, InsertStmt, ListenStmt,
> LoadStmt, LockStmt,
> ! 		NotifyStmt, OptimizableStmt, ProcedureStmt,
> PrepareStmt, prepare_query,
> ! 		ReindexStmt, RemoveAggrStmt, RemoveFuncStmt, RemoveOperStmt,
>   		RenameStmt, RevokeStmt, RuleActionStmt,
> RuleActionStmtOrEmpty,
>   		RuleStmt, SelectStmt, TransactionStmt, TruncateStmt,
>   		UnlistenStmt, UpdateStmt, VacuumStmt, VariableResetStmt,
> ***************
> *** 204,210 ****
>   		any_name, any_name_list, expr_list, dotted_name, attrs,
>   		target_list, update_target_list, insert_column_list,
>   		def_list, opt_indirection, group_clause, TriggerFuncArgs,
> ! 		select_limit, opt_select_limit
>
>   %type <range>	into_clause, OptTempTableName
>
> --- 205,214 ----
>   		any_name, any_name_list, expr_list, dotted_name, attrs,
>   		target_list, update_target_list, insert_column_list,
>   		def_list, opt_indirection, group_clause, TriggerFuncArgs,
> ! 		select_limit, opt_select_limit, types_list,
> ! 		types_prepare_clause, execute_using
> !
> ! %type <ival>	prepare_store
>
>   %type <range>	into_clause, OptTempTableName
>
> ***************
> *** 319,325 ****
>   		COALESCE, COLLATE, COLUMN, COMMIT,
>   		CONSTRAINT, CONSTRAINTS, CREATE, CROSS, CURRENT_DATE,
>   		CURRENT_TIME, CURRENT_TIMESTAMP, CURRENT_USER, CURSOR,
> ! 		DAY_P, DEC, DECIMAL, DECLARE, DEFAULT, DELETE, DESC,
>   		DISTINCT, DOUBLE, DROP,
>   		ELSE, ENCRYPTED, END_TRANS, ESCAPE, EXCEPT,
> EXECUTE, EXISTS, EXTRACT,
>   		FALSE_P, FETCH, FLOAT, FOR, FOREIGN, FROM, FULL,
> --- 323,329 ----
>   		COALESCE, COLLATE, COLUMN, COMMIT,
>   		CONSTRAINT, CONSTRAINTS, CREATE, CROSS, CURRENT_DATE,
>   		CURRENT_TIME, CURRENT_TIMESTAMP, CURRENT_USER, CURSOR,
> ! 		DAY_P, DEALLOCATE, DEC, DECIMAL, DECLARE, DEFAULT,
> DELETE, DESC,
>   		DISTINCT, DOUBLE, DROP,
>   		ELSE, ENCRYPTED, END_TRANS, ESCAPE, EXCEPT,
> EXECUTE, EXISTS, EXTRACT,
>   		FALSE_P, FETCH, FLOAT, FOR, FOREIGN, FROM, FULL,
> ***************
> *** 329,335 ****
>   		MATCH, MINUTE_P, MONTH_P, NAMES,
>   		NATIONAL, NATURAL, NCHAR, NEXT, NO, NOT, NULLIF,
> NULL_P, NUMERIC,
>   		OF, OLD, ON, ONLY, OPTION, OR, ORDER, OUTER_P, OVERLAPS,
> ! 		PARTIAL, POSITION, PRECISION, PRIMARY, PRIOR,
> PRIVILEGES, PROCEDURE, PUBLIC,
>   		READ, REFERENCES, RELATIVE, REVOKE, RIGHT, ROLLBACK,
>   		SCHEMA, SCROLL, SECOND_P, SELECT, SESSION,
> SESSION_USER, SET, SOME, SUBSTRING,
>   		TABLE, TEMPORARY, THEN, TIME, TIMESTAMP,
> --- 333,339 ----
>   		MATCH, MINUTE_P, MONTH_P, NAMES,
>   		NATIONAL, NATURAL, NCHAR, NEXT, NO, NOT, NULLIF,
> NULL_P, NUMERIC,
>   		OF, OLD, ON, ONLY, OPTION, OR, ORDER, OUTER_P, OVERLAPS,
> ! 		PARTIAL, POSITION, PRECISION, PREPARE, PRIMARY,
> PRIOR, PRIVILEGES, PROCEDURE, PUBLIC,
>   		READ, REFERENCES, RELATIVE, REVOKE, RIGHT, ROLLBACK,
>   		SCHEMA, SCROLL, SECOND_P, SELECT, SESSION,
> SESSION_USER, SET, SOME, SUBSTRING,
>   		TABLE, TEMPORARY, THEN, TIME, TIMESTAMP,
> ***************
> *** 363,372 ****
>   		DATABASE, DELIMITERS, DO,
>   		EACH, ENCODING, EXCLUSIVE, EXPLAIN,
>   		FORCE, FORWARD, FREEZE, FUNCTION, HANDLER,
> ! 		ILIKE, INCREMENT, INDEX, INHERITS, INSTEAD, ISNULL,
>   		LANCOMPILER, LIMIT, LISTEN, LOAD, LOCATION, LOCK_P,
>   		MAXVALUE, MINVALUE, MODE, MOVE,
> ! 		NEW, NOCREATEDB, NOCREATEUSER, NONE, NOTHING,
> NOTIFY, NOTNULL,
>   		OFFSET, OIDS, OPERATOR, OWNER, PASSWORD, PROCEDURAL,
>   		REINDEX, RENAME, RESET, RETURNS, ROW, RULE,
>   		SEQUENCE, SETOF, SHARE, SHOW, START, STATEMENT,
> --- 367,376 ----
>   		DATABASE, DELIMITERS, DO,
>   		EACH, ENCODING, EXCLUSIVE, EXPLAIN,
>   		FORCE, FORWARD, FREEZE, FUNCTION, HANDLER,
> ! 		ILIKE, INCREMENT, INDEX, INHERITS, INSTEAD, ISNULL,
> INTERNAL,
>   		LANCOMPILER, LIMIT, LISTEN, LOAD, LOCATION, LOCK_P,
>   		MAXVALUE, MINVALUE, MODE, MOVE,
> ! 		NEW, NOCREATEDB, NOCREATEUSER, NONE, NOSHARE,
> NOTHING, NOTIFY, NOTNULL,
>   		OFFSET, OIDS, OPERATOR, OWNER, PASSWORD, PROCEDURAL,
>   		REINDEX, RENAME, RESET, RETURNS, ROW, RULE,
>   		SEQUENCE, SETOF, SHARE, SHOW, START, STATEMENT,
> ***************
> *** 460,465 ****
> --- 464,470 ----
>   		| CreateTrigStmt
>   		| CreateUserStmt
>   		| ClusterStmt
> + 		| DeallocatePrepareStmt
>   		| DefineStmt
>   		| DropStmt
>   		| DropSchemaStmt
> ***************
> *** 469,474 ****
> --- 474,480 ----
>   		| DropPLangStmt
>   		| DropTrigStmt
>   		| DropUserStmt
> + 		| ExecuteStmt
>   		| ExplainStmt
>   		| FetchStmt
>   		| GrantStmt
> ***************
> *** 477,482 ****
> --- 483,489 ----
>   		| UnlistenStmt
>   		| LockStmt
>   		| NotifyStmt
> + 		| PrepareStmt
>   		| ProcedureStmt
>   		| ReindexStmt
>   		| RemoveAggrStmt
> ***************
> *** 3489,3494 ****
> --- 3496,3594 ----
>   		| DeleteStmt					/*
> by default all are $$=$1 */
>   		;
>
> +
> /*****************************************************************
> ************
> +  *
> +  *				PREPARE STATEMENTS
> +  *
> +
> ******************************************************************
> ***********/
> + PrepareStmt:  PREPARE name AS prepare_query
> types_prepare_clause prepare_store
> +   				{
> + 					PrepareStmt *n =
> makeNode(PrepareStmt);
> + 					n->name = $2;
> + 					n->query = (Query *) $4;
> + 					n->types = (List *) $5;
> + 					n->store = $6;
> + 					$$ = (Node *) n;
> + 				}
> + 		;
> +
> + prepare_query:  SelectStmt
> + 		| UpdateStmt
> + 		| InsertStmt
> + 		| DeleteStmt
> + 		;
> +
> + types_list:  SimpleTypename
> + 				{ $$ = makeList1($1); }
> + 		| types_list ',' SimpleTypename
> + 				{ $$ = lappend($1, $3); }
> + 		;
> +
> + types_prepare_clause:  USING types_list		{ $$ = $2; }
> + 		| /*EMPTY*/
> 	{ $$ = NIL; }
> + 		;
> +
> + prepare_store: NOSHARE		{ $$ = 1; }
> + 		| GLOBAL			{ $$ = 2; }
> + 		| SHARE				{ $$ = 0; }	/*
> default */
> + 		| /* EMPTY */		{ $$ = 0; }
> + 		;
> +
> +
> /*****************************************************************
> ************
> +  *
> +  *				EXECUTE STATEMENTS
> +  *
> +
> ******************************************************************
> ***********/
> + ExecuteStmt: EXECUTE name into_clause USING execute_using prepare_store
> + 				{
> + 					ExecuteStmt *n =
> makeNode(ExecuteStmt);
> + 					n->name = $2;
> + 					n->into = $3;
> + 					n->using = $5;
> + 					n->store = $6;
> + 					$$ = (Node *) n;
>
> + 				}
> + 		;
> +
> + execute_using: a_expr
> + 				{ $$ = makeList1($1); }
> + 		| execute_using ',' a_expr
> + 				{ $$ = lappend($1, $3); }
> + 		;
> +
> +
> /*****************************************************************
> ************
> +  *
> +  *				DEALLOCATE PREPARE STATEMENTS
> +  *
> +
> ******************************************************************
> ***********/
> + DeallocatePrepareStmt: DEALLOCATE PREPARE ALL
> + 				{
> + 					DeallocatePrepareStmt *n =
> makeNode(DeallocatePrepareStmt);
> + 					n->name = NULL;
> + 					n->store = 0;
> + 					n->all = TRUE;
> + 					n->internal = FALSE;
> + 					$$ = (Node *) n;
> + 				}
> + 		| DEALLOCATE PREPARE ALL INTERNAL
> + 				{
> + 					DeallocatePrepareStmt *n =
> makeNode(DeallocatePrepareStmt);
> + 					n->name = NULL;
> + 					n->store = 0;
> + 					n->all = FALSE;
> + 					n->internal = TRUE;
> + 					$$ = (Node *) n;
> + 				}
> + 		| DEALLOCATE PREPARE name prepare_store
> + 				{
> + 					DeallocatePrepareStmt *n =
> makeNode(DeallocatePrepareStmt);
> + 					n->name = $3;
> + 					n->store = $4;
> + 					n->all = FALSE;
> + 					n->internal = FALSE;
> + 					$$ = (Node *) n;
> + 				}
> + 		;
>
>
> /*****************************************************************
> ************
>    *
>
> ---------------------------(end of broadcast)---------------------------
> TIP 5: Have you checked our extensive FAQ?
>
> http://www.postgresql.org/users-lounge/docs/faq.html
>


Thu, 11 Apr 2002 10:14:39 +0800
"Christopher Kings-Lynne" <chriskl@familyhealth.com.au>
Re: help with bison
> In fact, my grammar currently has an obscene
> 20 shift/reduce and 4 reduce/reduce conflicts!

A shift/reduce conflict, IIRC, usually indicates a situation where
the grammar is unambiguous but may be inefficient.  Eliminating them
is nice, but not critical.

A R/R conflict, in contrast, is a point where the grammar is ambiguous
and you *must* fix it.

> (Unfortunately, bison isn't very
> helpful: it doesn't provide line-numbers when it warns me about
> the # of conflicts).

Turn on the verbose flag (-v|--verbose).  Near the top it should
list the S/R and R/R states.  You can then examine the states and
rules and see exactly where the problem is.

Cutting to the chase, the R/R problems are due to "TEMP" and
"TEMPORARY" being both "unreserved keywords" and part of
OptTempTableName.  If you comment them out in 'unreserved keywords'
the R/R error goes away but this may introduce errors elsewhere.

What is probably better is to move those tokens someplace else
where there's some context:

  into_clause : INTO OptTempTableName
	| /* EMPTY */
	;

needs to be replaced with something like

  into_options : /* EMPTY */
	| TEMPORARY
	| TEMP
	;

  into_clause : INTO into_options OptTempTableName
	| /* EMPTY */
	;

with the corresponding modifiers removed from the OptTempTableName

Unfortunately, when I quickly tested that the number of S/R conflicts 
ballooned to 378.

As an aside, is there any reason to treat TEMP and TEMPORARY as two
separate identifiers?  It's common practice to have synonyms mapped
to a single identifier in the lexical analyzer, and the grammar itself
looks like it could benefit from some helper rules such as:

  temporary
	: TEMPORARY  { $$ = 1; }
	| TEMP	     { $$ = 1; }
	| 	     { $$ = 0; }
	;

  scope
	: GLOBAL     { $$ = 1; }
 	| LOCAL      { $$ = 2; }
	|            { $$ = 0; }
	;

  something : scope temporary somethingelse { ... }

Bear

Wed, 10 Apr 2002 20:20:12 -0600 (MDT)
Bear Giles <bgiles@coyotesong.com>
Re: help with bison
On Wed, 10 Apr 2002, Bear Giles wrote:

> > In fact, my grammar currently has an obscene
> > 20 shift/reduce and 4 reduce/reduce conflicts!
> 
> A shift/reduce conflict, IIRC, usually indicates a situation where
> the grammar is unambiguous but may be inefficient.  Eliminating them
> is nice, but not critical.

This is not correct. A shift/reduce conflict is where the grammar is
ambiguous.

> 
> A R/R conflict, in contrast, is a point where the grammar is ambiguous
> and you *must* fix it.

A reduce/reduce conflict is where there is more than one rule which could
be used for the reduction of the grammar.

Gavin


Thu, 11 Apr 2002 12:44:13 +1000 (EST)
Gavin Sherry <swm@linuxworld.com.au>
Re: help with bison
Out of interest, since the FE/BE protocol apprently doesn't support prepared
statements (bound variables), what does this patch actually _do_?

Chris

> -----Original Message-----
> From: pgsql-hackers-owner@postgresql.org
> [mailto:pgsql-hackers-owner@postgresql.org]On Behalf Of Neil Conway
> Sent: Thursday, 11 April 2002 9:29 AM
> To: PostgreSQL Hackers
> Subject: [HACKERS] help with bison
>
>
> Hi all,
>
> I'm working on a fairly large patch (cleaning up Karel Zak's
> PREPARE/EXECUTE work), and I'm having some problems with bison (I'm
> a yacc newbie). In fact, my grammar currently has an obscene
> 20 shift/reduce and 4 reduce/reduce conflicts!
>
> Would someone to be kind enough to let me know what I'm doing wrong,
> and what I'll need to change? (Unfortunately, bison isn't very
> helpful: it doesn't provide line-numbers when it warns me about
> the # of conflicts). The patch for gram.y is below.
>
> Thanks in advance,
>
> Neil
>
> --
> Neil Conway <neilconway@rogers.com>
> PGP Key ID: DB3C29FC


Thu, 11 Apr 2002 10:54:14 +0800
"Christopher Kings-Lynne" <chriskl@familyhealth.com.au>
Re: help with bison
On Thu, 11 Apr 2002 10:54:14 +0800
"Christopher Kings-Lynne" <chriskl@familyhealth.com.au> wrote:
> Out of interest, since the FE/BE protocol apprently doesn't support prepared
> statements (bound variables), what does this patch actually _do_?

It implements preparable statements, by adding 3 new SQL statements:

PREPARE <plan> AS <query>;
EXECUTE <plan> USING <parameters>;
DEALLOCATE <plan>;

I didn't write the original patch -- that was done by Karel Zak.
But since that was several years ago, I'm working on cleaning it up,
getting it to apply to current sources (which has taken a while),
and fixing the remaining issues with it. Karel describes his work
here:

http://groups.google.com/groups?q=query+cache+plan&hl=en&selm=8l4jua%242fo0%241%40FreeBSD.csie.NCTU.edu.tw&rnum=1

(If that's messed up due to newlines, search for "query cache plan"
on Google Groups, it's the first result)

Cheers,

Neil

-- 
Neil Conway <neilconway@rogers.com>
PGP Key ID: DB3C29FC

Wed, 10 Apr 2002 23:03:09 -0400
Neil Conway <nconway@klamath.dyndns.org>
Re: help with bison
> PREPARE <plan> AS <query>;
> EXECUTE <plan> USING <parameters>;
> DEALLOCATE <plan>;
>
> I didn't write the original patch -- that was done by Karel Zak.
> But since that was several years ago, I'm working on cleaning it up,
> getting it to apply to current sources (which has taken a while),
> and fixing the remaining issues with it. Karel describes his work
> here:

OK, fair enough.  What I don't get is how this patch is related to the FE/BE
not supporting variable binding problem?  Am I getting confused here?

Chris


Thu, 11 Apr 2002 11:21:50 +0800
"Christopher Kings-Lynne" <chriskl@familyhealth.com.au>
Re: help with bison
Bear Giles <bgiles@coyotesong.com> writes:
> As an aside, is there any reason to treat TEMP and TEMPORARY as two
> separate identifiers?

Yes: if the lexer folds them together then unreserved_keyword can't
regenerate the equivalent name properly.  (Possibly this could be fixed
by making the lexer pass the input string as the value of a keyword
token, but I've not looked at details.)

You might be right that the grammar could benefit from some refactoring,
though I'm not at all sure if that really helps from an
execution-efficiency (number of states) standpoint.

			regards, tom lane

Wed, 10 Apr 2002 23:24:08 -0400
Tom Lane <tgl@sss.pgh.pa.us>
Re: help with bison 
> > As an aside, is there any reason to treat TEMP and TEMPORARY as two
> > separate identifiers?
> 
> Yes: if the lexer folds them together then unreserved_keyword can't
> regenerate the equivalent name properly.

But if they're synonyms, is that necessary?  I'm not indifferent to the
benefits of being able to recreate an input string exactly when all other
things are equal, but things aren't equal here.  TEMPORARY is a SQL92
keyword, TEMP is described as a "Keyword for Postgres support," but the
grammar shows that one never appears without the other.

So why not deprecate TEMP and always show TEMPORARY when reconstructing
the query?

> You might be right that the grammar could benefit from some refactoring,
> though I'm not at all sure if that really helps from an
> execution-efficiency (number of states) standpoint.

The goal of the refactoring wouldn't be execution efficiency, it would 
be simplifying maintenance of the grammar.  And it looks like it's the
common practice elsewhere, just not in the OptTemp and OptTempTableName
rules.

Bear

Wed, 10 Apr 2002 21:52:06 -0600 (MDT)
Bear Giles <bgiles@coyotesong.com>
Re: help with bison
Bear Giles <bgiles@coyotesong.com> writes:
>> Yes: if the lexer folds them together then unreserved_keyword can't
>> regenerate the equivalent name properly.

> But if they're synonyms, is that necessary?

If I say
	create table foo (temp int);
I will be annoyed if the system decides that the column is named
"temporary".  Being synonyms in the SQL grammar does not make them
equivalent when used as plain identifiers.

			regards, tom lane

Thu, 11 Apr 2002 00:33:39 -0400
Tom Lane <tgl@sss.pgh.pa.us>
Re: help with bison 
On Wed, 10 Apr 2002, Neil Conway wrote:

> Hi all,
> 
> I'm working on a fairly large patch (cleaning up Karel Zak's
> PREPARE/EXECUTE work), and I'm having some problems with bison (I'm
> a yacc newbie). In fact, my grammar currently has an obscene
> 20 shift/reduce and 4 reduce/reduce conflicts!

Your first set of problems is coming from PrepareStmt:

---

PrepareStmt:  PREPARE name AS prepare_query types_prepare_clause
prepare_store

---

There is a reasonably clear problem here. prepare_query encompasses much
of the grammar of the parser so it will definately cause shift/reduce and
reduce/reduce conflicts with the other two productions which follow
it. Easy solution?

PrepareStmt:  PREPARE name types_prepare_clause prepare_store AS
prepare_query

Your second problem is in ExecuteStmt:

ExecuteStmt: EXECUTE name into_clause USING execute_using prepare_store

Here your problem is with execute_using and prepare_store. I am not sure
why.

Gavin


Thu, 11 Apr 2002 15:02:49 +1000 (EST)
Gavin Sherry <swm@linuxworld.com.au>
Re: help with bison
Neil,

Will this allow you to pass bytea data as binary data in the parameters 
section (ability to bind values to parameters) or will this still 
require that the data be passed as a text string that the parser needs 
to parse.  When passing bytea data that is on the order of Megs in size 
(thus the insert/update statement is multiple Megs in size) it takes a 
lot of CPU cycles for the parser to chug through sql statements that 
long.  (In fact a posting to the jdbc mail list in the last couple of 
days shows that postgres is 22 times slower than oracle when handling a 
1Meg value in a bytea column).

thanks,
--Barry

Neil Conway wrote:
> On Thu, 11 Apr 2002 10:54:14 +0800
> "Christopher Kings-Lynne" <chriskl@familyhealth.com.au> wrote:
> 
>>Out of interest, since the FE/BE protocol apprently doesn't support prepared
>>statements (bound variables), what does this patch actually _do_?
> 
> 
> It implements preparable statements, by adding 3 new SQL statements:
> 
> PREPARE <plan> AS <query>;
> EXECUTE <plan> USING <parameters>;
> DEALLOCATE <plan>;
> 
> I didn't write the original patch -- that was done by Karel Zak.
> But since that was several years ago, I'm working on cleaning it up,
> getting it to apply to current sources (which has taken a while),
> and fixing the remaining issues with it. Karel describes his work
> here:
> 
> http://groups.google.com/groups?q=query+cache+plan&hl=en&selm=8l4jua%242fo0%241%40FreeBSD.csie.NCTU.edu.tw&rnum=1
> 
> (If that's messed up due to newlines, search for "query cache plan"
> on Google Groups, it's the first result)
> 
> Cheers,
> 
> Neil
> 



Wed, 10 Apr 2002 22:36:49 -0700
Barry Lind <barry@xythos.com>
Re: help with bison
Gavin Sherry <swm@linuxworld.com.au> writes:
> PrepareStmt:  PREPARE name AS prepare_query types_prepare_clause
> prepare_store

> There is a reasonably clear problem here. prepare_query encompasses much
> of the grammar of the parser so it will definately cause shift/reduce and
> reduce/reduce conflicts with the other two productions which follow
> it. Easy solution?

> PrepareStmt:  PREPARE name types_prepare_clause prepare_store AS
> prepare_query

Is there any existing standard to follow for the syntax of these
commands?

			regards, tom lane

Thu, 11 Apr 2002 11:46:03 -0400
Tom Lane <tgl@sss.pgh.pa.us>
Re: help with bison 
On Wed, 10 Apr 2002 22:36:49 -0700
"Barry Lind" <barry@xythos.com> wrote:
> Neil,
> 
> Will this allow you to pass bytea data as binary data in the parameters 
> section (ability to bind values to parameters) or will this still 
> require that the data be passed as a text string that the parser needs 
> to parse.

The patch I'm working on would require that the parameters
are still parsed, so it would likely suffer from the same
performance problems.

I'm unsure how to fix this without a change to the FE/BE
protocol (and even then, it wouldn't be trivial). Suggestions?

Cheers,

Neil

-- 
Neil Conway <neilconway@rogers.com>
PGP Key ID: DB3C29FC

Thu, 11 Apr 2002 12:02:38 -0400
Neil Conway <nconway@klamath.dyndns.org>
Re: help with bison
On Thu, 11 Apr 2002 15:02:49 +1000 (EST)
"Gavin Sherry" <swm@linuxworld.com.au> wrote:
> On Wed, 10 Apr 2002, Neil Conway wrote:
> 
> > Hi all,
> > 
> > I'm working on a fairly large patch (cleaning up Karel Zak's
> > PREPARE/EXECUTE work), and I'm having some problems with bison (I'm
> > a yacc newbie). In fact, my grammar currently has an obscene
> > 20 shift/reduce and 4 reduce/reduce conflicts!
> 
> Your first set of problems is coming from PrepareStmt:
> [...]

> Your second problem is in ExecuteStmt:
> [...]

Great, thanks Gavin! (I owe you a beer!)

I re-arranged PrepareStmt as you suggested, as well as
ExecuteStmt, and the conflicts have disappeared. I'm not sure
if the new syntax is ideal, but I'm happy to leave it as it is
until I've got the patch mostly working. I'd welcome any
suggestions for improvements to the syntax that still allow
for sane parsing.

Thanks again,

Neil

-- 
Neil Conway <neilconway@rogers.com>
PGP Key ID: DB3C29FC

Thu, 11 Apr 2002 12:16:34 -0400
Neil Conway <nconway@klamath.dyndns.org>
Re: help with bison
Neil Conway wrote:
 > On Wed, 10 Apr 2002 22:36:49 -0700 "Barry Lind" <barry@xythos.com>
 > wrote:
 >
 >> Neil,
 >>
 >> Will this allow you to pass bytea data as binary data in the
 >> parameters section (ability to bind values to parameters) or will
 >> this still require that the data be passed as a text string that
 >> the parser needs to parse.
 >
 >
 > The patch I'm working on would require that the parameters are still
 > parsed, so it would likely suffer from the same performance
 > problems.
 >
 > I'm unsure how to fix this without a change to the FE/BE protocol
 > (and even then, it wouldn't be trivial). Suggestions?
 >


The other day there was a discussion around the fact that X'ffff' will
get converted into an integer constant, e.g.

test=# select X'ffff';
  ?column?
----------
     65535
(1 row)

, while SQL99 says that this syntax *should* be used to specify a 
"binary string". It looks like the hex-to-integer magic actually occurs 
in the lexer, and then the integer value of 65535 is passed to the 
parser as an ICONST. I'm wondering if changing the lexer to make this a 
conversion to a properly escaped bytea input string, and passing it to 
the parser as a string constant would speed things up?

Joe





Thu, 11 Apr 2002 09:26:19 -0700
Joe Conway <mail@joeconway.com>
Re: help with bison
On Thu, 11 Apr 2002, Tom Lane wrote:

> Gavin Sherry <swm@linuxworld.com.au> writes:
> > PrepareStmt:  PREPARE name AS prepare_query types_prepare_clause
> > prepare_store
> 
> > There is a reasonably clear problem here. prepare_query encompasses much
> > of the grammar of the parser so it will definately cause shift/reduce and
> > reduce/reduce conflicts with the other two productions which follow
> > it. Easy solution?
> 
> > PrepareStmt:  PREPARE name types_prepare_clause prepare_store AS
> > prepare_query
> 
> Is there any existing standard to follow for the syntax of these
> commands?

SQL92 lists:

         <prepare statement> ::=
              PREPARE <SQL statement name> FROM <SQL statement variable>

Where <SQL statement variable> can resolve to:

         <preparable statement> ::=
                <preparable SQL data statement>
              | <preparable SQL schema statement>
              | <preparable SQL transaction statement>
              | <preparable SQL session statement>
              | <preparable implementation-defined statement>

         <preparable SQL data statement> ::=
                <delete statement: searched>
              | <dynamic single row select statement>
              | <insert statement>
              | <dynamic select statement>
              | <update statement: searched>
              | <preparable dynamic delete statement: positioned>
              | <preparable dynamic update statement: positioned>

         <preparable SQL schema statement> ::=
                <SQL schema statement>

         <preparable SQL transaction statement> ::=
                <SQL transaction statement>

         <preparable SQL session statement> ::=
                <SQL session statement>

         <dynamic select statement> ::= <cursor specification>

         <dynamic single row select statement> ::= <query specification>



So, the form is (according to the yacc code):

PREPARE name FROM prepare_query

This seems a lot simpler. What is 'types_prepare_clause' used for? I
presume storage relates to whether or not all backends can see the
prepared statement? (As a note to those interested in statement
preparation, this is not the same as variable binding and so requires no
modification of the FE/BE protocol).

As a side note, I'm not sure I really see the point of preparable SQL. The
only real use I can think of is if the query could be prepared on the
client side. This would require modification of the parser (a few
#ifdefs), a few client side functions, some memory storage and a
modification of the FE/BE protocol to be able to accept parsed query
nodes. This would allow the backend to spend as little time in the parser
as possible, if that is desirable. It removes the ability to share
prepared queries between backends however.

Gavin





Fri, 12 Apr 2002 02:26:47 +1000 (EST)
Gavin Sherry <swm@linuxworld.com.au>
Re: help with bison 
Joe Conway writes:

> The other day there was a discussion around the fact that X'ffff' will
> get converted into an integer constant, e.g.

> , while SQL99 says that this syntax *should* be used to specify a
> "binary string".

Actually, SQL99 is ambiguous regarding whether it represents a blob or a
bit string.  But either of these would be better than an integer.

-- 
Peter Eisentraut   peter_e@gmx.net


Thu, 11 Apr 2002 14:00:28 -0400 (EDT)
Peter Eisentraut <peter_e@gmx.net>
Re: help with bison
> The other day there was a discussion around the fact that X'ffff' will
> get converted into an integer constant...
> ... while SQL99 says that this syntax *should* be used to specify a
> "binary string". It looks like the hex-to-integer magic actually occurs
> in the lexer, and then the integer value of 65535 is passed to the
> parser as an ICONST. I'm wondering if changing the lexer to make this a
> conversion to a properly escaped bytea input string, and passing it to
> the parser as a string constant would speed things up?

What else is described as a "binary string" in the spec? I would have
guessed that this would map to a bit field type (and maybe even had
looked it up at one time).

Is B'00010001' also described as a "binary string" also, or is it more
explicitly tied to bit fields?

                    - Thomas

Thu, 11 Apr 2002 22:29:20 -0700
Thomas Lockhart <lockhart@fourpalms.org>
Re: help with bison
Thomas Lockhart wrote:
 >> The other day there was a discussion around the fact that X'ffff'
 >> will get converted into an integer constant... ... while SQL99
 >> says that this syntax *should* be used to specify a "binary
 >> string". It looks like the hex-to-integer magic actually occurs in
 >> the lexer, and then the integer value of 65535 is passed to the parser
 >> as an ICONST. I'm wondering if changing the lexer to make this a 
conversion
 >> to a properly escaped bytea input string, and passing it to the
 >> parser as a string constant would speed things up?
 >
 >
 > What else is described as a "binary string" in the spec? I would
 > have guessed that this would map to a bit field type (and maybe even
 > had looked it up at one time).
 >
 > Is B'00010001' also described as a "binary string" also, or is it
 > more explicitly tied to bit fields?
 >
 > - Thomas

In SQL99, Section "5.3 <literal>", I see this:

   <national character string literal> ::=
      N <quote> [ <character representation>... ] <quote>
      [ { <separator> <quote> [ <character representation>... ]
      <quote> }... ]
   <bit string literal> ::=
      B <quote> [ <bit>... ] <quote>
      [ { <separator> <quote> [ <bit>... ] <quote> }... ]
   <hex string literal> ::=
      X <quote> [ <hexit>... ] <quote>
      [ { <separator> <quote> [ <hexit>... ] <quote> }... ]
   <binary string literal> ::=
      X <quote> [ { <hexit> <hexit> }... ] <quote>
      [ { <separator> <quote> [ { <hexit> <hexit> }... ] <quote> }... ]
   <bit> ::=
      0 | 1
   <hexit> ::=
      <digit> | A | B | C | D | E | F | a | b | c | d | e | f

and further down:

   11) The declared type of a <bit string literal> is fixed-length
       bit string. The length of a <bit string literal> is the number
       of bits that it contains.
   12) The declared type of a <hex string literal> is fixed-length bit
       string. Each <hexit> appearing in the literal is equivalent to
       a quartet of bits: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E,
       and F are interpreted as 0000, 0001, 0010, 0011, 0100, 0101,
       0110, 0111, 1000, 1001, 1010, 1011, 1100, 1101, 1110, and 1111,
       respectively. The <hexit>s a, b, c, d, e, and f have respectively
       the same values as the <hexit>s A, B, C, D, E, and F.
   13) The declared type of a <binary string literal> is binary string.
       Each <hexit> appearing in the literal is equivalent to a quartet
       of bits: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, and F are
       interpreted as 0000, 0001, 0010, 0011, 0100, 0101, 0110, 0111,
       1000, 1001, 1010, 1011, 1100, 1101, 1110, and 1111, respectively.
       The <hexit>s a, b, c, d, e, and f have respectively the same
       values as the <hexit>s A, B, C, D, E, and F.

So, as Peter pointed out, X'ffff' can be interpreted as a binary string 
*or* a bit string, but ISTM B'1111' is explicitly tied to a bit string.

Joe


Fri, 12 Apr 2002 09:21:06 -0700
Joe Conway <mail@joeconway.com>
Re: help with bison