[TUHS] Archaic yacc C grammar

Lars Brinkhoff lars at nocrew.org
Mon Oct 29 07:34:49 AEST 2018


Hello,

This is Alan Snyder's C grammar.  It's supposedly for yacc, but it's
probably using some really ancient version.  Maybe from when Alan did a
stint at Bell labs and converted yacc from B to C.

Does anyone recognize this type of yacc input?  I don't have the
corresponding yacc version, and the one in V6 isn't happy about this
file.  What would it take to update the grammar for V6 yacc?  Add in
some %term, replace \\ with %%?



	#     C GRAMMAR     #
	#    28 May 1978    #
	#    Alan Snyder    #


#	26 acceptable conflicts:

	2 S/R conflicts for (parsing) ambiguity between
		declarators and function_declarators
	1 S/R conflict for the C ELSE ambiguity
	4 R/R conflicts for the (parsing) problem with regard
		to integer constants as initial_values
	12 R/R conflicts for the (parsing) problem with regard
		to identifiers in function calls
	1 R/R conflict for the (parsing) problem with regard
		to identifiers in goto statements
	4 R/R conflicts and 1 S/R conflict for TYPEDEFs
	1 S/R conflict for ambiguous cast types
		(int ()) = (int x()) not (int (x))

	Approximate description:

 18	S/R	(	shift 37	reduce 141
 50	S/R	(	shift 37	reduce 71
 81	S/R	(	shift 37	reduce 71
113	R/R	(	reduce 141	reduce 140
113	R/R	(	reduce 159	reduce 140
113	R/R	*	reduce 159	reduce 141
113	S/R	:	shift 199	reduce 141
183	R/R	,	reduce 203	reduce 24
183	R/R	}	reduce 203	reduce 24
204	R/R	(	reduce 159	reduce 140
206	R/R	(	reduce 148	reduce 139
207	R/R	(	reduce 147	reduce 139
208	R/R	(	reduce 145	reduce 139
209	R/R	(	reduce 144	reduce 139
210	R/R	(	reduce 146	reduce 139
211	R/R	(	reduce 149	reduce 139
212	R/R	(	reduce 150	reduce 139
215	R/R	(	reduce 159	reduce 140
215	R/R	;	reduce 159	reduce 138
225	R/R	(	reduce 151	reduce 139
228	R/R	(	reduce 159	reduce 140
284	R/R	,	reduce 203	reduce 25
284	R/R	}	reduce 203	reduce 25
291	S/R	)	shift 339	reduce 165
343	R/R	(	reduce 153	reduce 139
360	S/R	ELSE	shift 369	reduce 94

#

	#     terminal symbols     #

';' '}' '{' ']' '[' ')' '(' ':'
',' '.' '?' '~' '!' '&' '|' '^'
'%' '/' '*' '-' '+' '=' '<' '>'
'++' '--' '==' '!=' '<=' '>=' '<<' '>>'
'->' '=op' '&&' '||' 'c'
INT CHAR FLOAT DOUBLE STRUCT AUTO STATIC
EXTERN RETURN GOTO IF ELSE SWITCH
BREAK CONTINUE WHILE DO FOR DEFAULT CASE
ENTRY REGISTER SIZEOF LONG SHORT UNSIGNED TYPEDEF 'l'
'm' 'n' 'o' 'p' 'q' 'r' 's'
identifier integer floatcon string

	#     precedence information     #

\< ','
\> '=' '=op'
\> '?' ':'
\< '||'
\< '&&'
\< '|'
\< '^'
\< '&'
\< '==' '!='
\< '<' '>' '<=' '>='
\< '<<' '>>'
\< '+' '-'
\< '*' '/' '%'
\> '!' '~'
\> '++' '--' SIZEOF
\< '[' '(' '.' '->'

\\

	#     external definitions     #

program:
	  program external_definition
	|

external_definition:
	  declaration
	| function_definition

function_definition:
	  function_specification function_body		{afdef(#1,#2);}

function_specification:
	  decl_specifiers function_declarator		{val=afdcl(1);}
	| function_declarator				{val=afdcl(0);}

function_body:
	  formal_declarations compound_statement	{val=#2;}

formal_declarations:
	  formal_decl_list				{afpdcl();}
	| 						{afpdcl();}

compound_statement:
	  begin declaration_list statement_list end	{val=#3;}
	| begin statement_list end			{val=#2;}

init_declarator_list:
	  init_declarator
	| init_declarator_list ',' init_declarator 

init_declarator:
	  $declarator initializer		{aidecl();}
	| declarator				{aidecl();}
	| function_declarator			{adeclr(maktyp());}

initializer:
	  initial_value
	| '{' initial_value_expression_list '}'
	| '{' initial_value_expression_list ',' '}'

initial_value_expression_list:
	  initial_value_expression
	| initial_value_expression_list ',' initial_value_expression

initial_value:
	  integer				{inz(i_int,#1);}
	| '-' integer				{inz(i_int,-#2);}
	| floatcon				{inz(i_float,#1);}
	| '-' floatcon				{inz(i_negfloat,#2);}
	| identifier				{inz(i_idn,#1);}
	| '&' identifier			{inz(i_idn,#2);}
	| string 				{inz(i_string,#1);}

initial_value_expression:
	  constant				{inz(i_int,#1);}
	| initial_value

	#     declarations     #

declaration_list:
	  declaration
	| declaration_list declaration

declaration:
	  decl_specifiers init_declarator_list ';'
	| literal_type_specifier ';'

decl_specifiers:
	  type_specifier			{attrib(-1,#1);}
	| sc_specifier type_specifier		{attrib(#1,#2);}
	| type_specifier sc_specifier		{attrib(#2,#1);}

type_specifier:
	  type_identifier
	| literal_type_specifier

literal_type_specifier:
	  INT					{val=TINT;}
	| CHAR					{val=TCHAR;}
	| FLOAT					{val=TFLOAT;}
	| DOUBLE				{val=TDOUBLE;}
	| LONG					{val=TINT;}
	| LONG INT				{val=TINT;}
	| SHORT					{val=TINT;}
	| SHORT INT				{val=TINT;}
	| LONG FLOAT				{val=TDOUBLE;}
	| UNSIGNED				{val=TINT;}
	| UNSIGNED INT				{val=TINT;}
	| struct '{' type_decl_list '}'			{val=astruct(NULL,#3);}
	| struct $identifier '{' type_decl_list '}'	{val=astruct(#2,#4);}
	| struct identifier	 			{val=aostruct(#2);}

sc_specifier:
	  AUTO					{val=c_auto;}
	| STATIC				{val=c_static;}
	| EXTERN				{val=c_extern;}
	| REGISTER				{val=c_auto;}
	| TYPEDEF				{val=c_typedef;}

declarator_list:
	  declarator
	| declarator_list ',' declarator 

declarator:
	  dclr					{val=adeclr(maktyp());}
	| identifier ':' constant		{val=adeclr(afield(#1,#3));}
	| ':' constant				{val=adeclr(afield(-1,#2));}

$declarator:
	  dclr					{aiinz(adeclr(maktyp()));}

dclr:
	'*' dclr				{val=adclr(#2,MPTR);}
	| dclr '(' ')'				{val=adclr(#1,MFUNC);}
	| dclr '[' ']'				{val=adclr(#1,MARRAY,1);}
	| dclr '[' constant ']'			{val=adclr(#1,MARRAY,#3);}
	| identifier  				{val=adclr(0,0);}
	| '(' dclr ')' 				{val=#2;}

function_declarator:
	  '*' function_declarator		{val=adclr(#2,MPTR);}
	| function_declarator '(' ')'		{val=adclr(#1,MFUNC);}
	| function_declarator '[' ']'		{val=adclr(#1,MARRAY,1);}
	| function_declarator '[' constant ']'	{val=adclr(#1,MARRAY,#3);}
	| identifier '(' ')'			{val=adclr(adclr(0,0),MFUNC);
							parml=0;}
	| identifier '(' parameter_list ')'	{val=adclr(adclr(0,0),MFUNC);
							parml=#3;}
	| '(' function_declarator ')'		{val=#2;}

parameter_list:
	  identifier				{val=push(#1);}
	| parameter_list ',' identifier		{push(#3);}

formal_decl_list:
	  formal_declaration
	| formal_decl_list formal_declaration

formal_declaration:
	  type_declaration
	| REGISTER type_declaration

type_decl_list:
	  type_declaration
	| type_decl_list type_declaration

type_declaration:
	  $type_specifier declarator_list ';'	{in_type_def=0;
						val=#2;}

$type_specifier:
	  type_specifier			{in_type_def=1;
						attrib(-1,#1);}

	#     statements     #

statement_list:
	  statement
	| statement_list statement		{val=astmtl(#1,#2);}

statement:
	  expression  ';'					{val=aexprstmt(#1);}
	| compound_statement
	| IF '(' expression ')' statement	 		{val=aif(#3,#5,0);}
	| IF '(' expression ')' statement ELSE statement	{val=aif(#3,#5,#7);}
	| while '(' expression ')' statement	 		{val=awhile(#3,#5);}
	| for '(' .expression ';' .expression ';' .expression ')' statement
								{val=afor(#3,#5,#7,#9);}
	| do statement WHILE '(' expression ')' ';'		{val=ado(#2,#5);}
	| switch '(' expression ')' statement			{val=aswitch(#3,#5);}
	| CASE constant ':' statement				{val=acase(#2,#4);}
	| DEFAULT ':' statement					{val=adefault(#3);}
	| BREAK ';'						{val=abreak();}
	| CONTINUE ';'						{val=acontinue();}
	| RETURN ';'						{val=areturn(0);}
	| RETURN expression ';'					{val=areturn(#2);}
	| GOTO lexpression ';'					{val=agoto(#2);}
	| identifier ':' statement				{val=alabel(#1,#3);}
	| ENTRY identifier ':' statement			{val=aentry(#2,#4);}
	| ';' 							{val=anull();} 


	#     expressions     #

.expression:
	  expression
	|			{val=0;}

expression_list:
	  expression	\= '='
	| expression_list ',' expression 		{val=aelist(#1,#3);}

expression:
	  expression '*' expression		{val=node(n_times,#1,#3);}
	| expression '/' expression		{val=node(n_div,#1,#3);}
	| expression '%' expression		{val=node(n_mod,#1,#3);}
	| expression '+' expression		{val=node(n_plus,#1,#3);}
	| expression '-' expression		{val=node(n_minus,#1,#3);}
	| expression '<<' expression		{val=node(n_ls,#1,#3);}
	| expression '>>' expression		{val=node(n_rs,#1,#3);}
	| expression '<' expression		{val=node(n_lt,#1,#3);}
	| expression '>' expression		{val=node(n_gt,#1,#3);}
	| expression '<=' expression		{val=node(n_le,#1,#3);}
	| expression '>='  expression		{val=node(n_ge,#1,#3);}
	| expression '=='  expression		{val=node(n_eq,#1,#3);}
	| expression '!='  expression		{val=node(n_ne,#1,#3);}
	| expression '&' expression		{val=node(n_band,#1,#3);}
	| expression '^' expression		{val=node(n_bxor,#1,#3);}
	| expression '|' expression		{val=node(n_bior,#1,#3);}
	| expression '&&' expression		{val=node(n_tv_and,#1,#3);}
	| expression '||' expression		{val=node(n_tv_or,#1,#3);}
	| expression '?' expression ':' expression
				{val=node(n_qmark,#1,node(n_colon,#3,#5));}
	| expression '=' expression		{val=node(n_assign,#1,#3);}
	| expression '=op' expression		{val=node(n_ars+#2,#1,#3);}
	| expression ',' expression		{val=node(n_comma,#1,#3);}
	| term 

# the following productions are ordered very carefully so that the
  desired thing is done in the case of a R/R conflict #

lexpression:
	  expression
	| identifier			{val=aidn(alidn(#1));}

fterm:
	  term
	| identifier			{val=aidn(afidn(#1));}

type_identifier:
	  identifier			{val=atidn(#1);}

term:
	  term '++'			{val=node(n_inca,#1);}
	| term '--'			{val=node(n_deca,#1);}
	| '*' term			{val=node(n_star,#2);}
	| '&' term			{val=node(n_addr,#2);}
	| '-' term			{val=node(n_uminus,#2);}
	| '!' term			{val=node(n_tvnot,#2);}
	| '~' term			{val=node(n_bnot,#2);}
	| '++' term			{val=node(n_incb,#2);}
	| '--' term			{val=node(n_decb,#2);}
	| SIZEOF term			{val=node(n_sizeof,#2);}
	| SIZEOF '(' cast_type ')' \= SIZEOF
					{val=node(n_int,1);} # hack #
	| '(' cast_type ')' term \= '++'
					{val=#4;} # hack #
	| term '[' expression ']'	{val=asubscript(#1,#3);}
	| fterm '(' expression_list ')'	{val=acall(#1,#3);}
	| fterm '(' ')'			{val=acall(#1,0);}
	| term '.' identifier		{val=adot(#1,#3);}
	| term '->' identifier		{val=aptr(#1,#3);}
	| identifier			{val=aidn(aeidn(#1));}
	| integer			{val=node(n_int,#1);}
	| floatcon			{val=node(n_float,#1);}
	| string			{val=node(n_string,#1);}
	| '(' expression ')' 		{val=#2;}

cast_type:	   literal_type_specifier null_decl

null_decl:	   # empty #
		|  '(' ')'
		|  '(' null_decl ')' '(' ')'
		|  '*' null_decl
		|  null_decl '[' ']'
		|  null_decl '[' constant ']'
		|  '(' null_decl ')'

while:		  WHILE			{apshw();}
do:		  DO			{apshd();}
for:		  FOR			{apshf();}
switch:		  SWITCH		{apshs();}
struct:		  STRUCT		{strlev++;}
$identifier:	  identifier		{val=astridn(#1);}
begin:		  '{'			{abegin();}
end:		  '}'			{aend();}

constant:
	  constant '*' constant		{val=#1*#3;}
	| constant '/' constant		{val=#1/#3;}
	| constant '%' constant		{val=#1%#3;}
	| constant '+' constant		{val=#1+#3;}
	| constant '-' constant		{val=#1-#3;}
	| constant '<<' constant	{val=#1<<#3;}
	| constant '>>' constant	{val=#1>>#3;}
	| constant '<' constant		{val=#1<#3;}
	| constant '>' constant		{val=#1>#3;}
	| constant '<=' constant	{val=#1<=#3;}
	| constant '>='  constant	{val=#1>=#3;}
	| constant '=='  constant	{val=#1==#3;}
	| constant '!='  constant	{val=#1!=#3;}
	| constant '&' constant		{val=#1}
	| constant '^' constant		{val=#1^#3;}
	| constant '|' constant		{val=#1|#3;}
	| constant '&&' constant	{val=#1&}
	| constant '||' constant	{val=#1||#3;}
	| constant '?' constant ':' constant
					{val=(#1?#3:#5);}
	| c_term 

c_term:
	  '-' c_term		{val= -#2;}
	| '!' c_term		{val= !#2;}
	| '~' c_term		{val= ~#2;}
	| integer
	| '(' constant ')'	{val=#2;}




More information about the TUHS mailing list