xref: /freebsd/contrib/byacc/test/btyacc_demo.y (revision 6cec9cad762b6476313fb1f8e931a1647822db6b)
1*0c8de5b0SBaptiste Daroussin /*
2*0c8de5b0SBaptiste Daroussin  * demonstrate enhancements derived from btyacc:
3*0c8de5b0SBaptiste Daroussin  * backtracking to resolve conflicts
4*0c8de5b0SBaptiste Daroussin  * semantic disambiguation via []-actions invoking YYVALID & YYERROR
5*0c8de5b0SBaptiste Daroussin  * %locations
6*0c8de5b0SBaptiste Daroussin  * @$ & @N to refer to lhs & rhs symbol location
7*0c8de5b0SBaptiste Daroussin  * %destructor
8*0c8de5b0SBaptiste Daroussin  * syntactic suger for inherited attributes
9*0c8de5b0SBaptiste Daroussin  * extension to %type to define inherited attribute type
10*0c8de5b0SBaptiste Daroussin  */
11*0c8de5b0SBaptiste Daroussin 
12*0c8de5b0SBaptiste Daroussin %LOCATIONS
13*0c8de5b0SBaptiste Daroussin 
14*0c8de5b0SBaptiste Daroussin %{
15*0c8de5b0SBaptiste Daroussin /* dummy types just for compile check */
16*0c8de5b0SBaptiste Daroussin typedef int Code;
17*0c8de5b0SBaptiste Daroussin typedef int Decl_List;
18*0c8de5b0SBaptiste Daroussin typedef int Expr;
19*0c8de5b0SBaptiste Daroussin typedef int Expr_List;
20*0c8de5b0SBaptiste Daroussin typedef int Scope;
21*0c8de5b0SBaptiste Daroussin typedef int Type;
22*0c8de5b0SBaptiste Daroussin enum Operator { ADD, SUB, MUL, MOD, DIV, DEREF };
23*0c8de5b0SBaptiste Daroussin 
24*0c8de5b0SBaptiste Daroussin typedef unsigned char bool;
25*0c8de5b0SBaptiste Daroussin typedef struct Decl {
26*0c8de5b0SBaptiste Daroussin     Scope *scope;
27*0c8de5b0SBaptiste Daroussin     Type  *type;
28*0c8de5b0SBaptiste Daroussin     bool (*istype)(void);
29*0c8de5b0SBaptiste Daroussin } Decl;
30*0c8de5b0SBaptiste Daroussin 
31*0c8de5b0SBaptiste Daroussin #include "btyacc_demo.tab.h"
32*0c8de5b0SBaptiste Daroussin #include <stdlib.h>
33*0c8de5b0SBaptiste Daroussin #include <stdio.h>
34*0c8de5b0SBaptiste Daroussin %}
35*0c8de5b0SBaptiste Daroussin 
36*0c8de5b0SBaptiste Daroussin %union {
37*0c8de5b0SBaptiste Daroussin     Scope	*scope;
38*0c8de5b0SBaptiste Daroussin     Expr	*expr;
39*0c8de5b0SBaptiste Daroussin     Expr_List	*elist;
40*0c8de5b0SBaptiste Daroussin     Type	*type;
41*0c8de5b0SBaptiste Daroussin     Decl	*decl;
42*0c8de5b0SBaptiste Daroussin     Decl_List	*dlist;
43*0c8de5b0SBaptiste Daroussin     Code	*code;
44*0c8de5b0SBaptiste Daroussin     char	*id;
45*0c8de5b0SBaptiste Daroussin     };
46*0c8de5b0SBaptiste Daroussin 
47*0c8de5b0SBaptiste Daroussin %left '+' '-'
48*0c8de5b0SBaptiste Daroussin %left '*' '/' '%'
49*0c8de5b0SBaptiste Daroussin %nonassoc PREFIX
50*0c8de5b0SBaptiste Daroussin %nonassoc POSTFIX '(' '[' '.'
51*0c8de5b0SBaptiste Daroussin 
52*0c8de5b0SBaptiste Daroussin %token <id>	ID
53*0c8de5b0SBaptiste Daroussin %token <expr>	CONSTANT
54*0c8de5b0SBaptiste Daroussin %token		EXTERN REGISTER STATIC CONST VOLATILE IF THEN ELSE CLCL
55*0c8de5b0SBaptiste Daroussin 
56*0c8de5b0SBaptiste Daroussin %type <expr>	expr(<scope>)
57*0c8de5b0SBaptiste Daroussin %type		decl(<scope>) declarator_list(<scope>, <type>)
58*0c8de5b0SBaptiste Daroussin 		decl_list(<scope>)
59*0c8de5b0SBaptiste Daroussin %type <code>	statement(<scope>) statement_list(<scope>)
60*0c8de5b0SBaptiste Daroussin 		block_statement(<scope>)
61*0c8de5b0SBaptiste Daroussin %type <decl>	declarator(<scope>, <type>) formal_arg(<scope>)
62*0c8de5b0SBaptiste Daroussin %type <type>	decl_specs(<scope>) decl_spec(<scope>) typename(<scope>)
63*0c8de5b0SBaptiste Daroussin 		cv_quals cv_qual
64*0c8de5b0SBaptiste Daroussin %type <scope>	opt_scope(<scope>)
65*0c8de5b0SBaptiste Daroussin %type <dlist>	formal_arg_list(<scope>) nonempty_formal_arg_list(<scope>)
66*0c8de5b0SBaptiste Daroussin 
67*0c8de5b0SBaptiste Daroussin %destructor	{ // 'msg' is a 'char *' indicating the context of destructor invocation
68*0c8de5b0SBaptiste Daroussin 		  printf("%s accessed by symbol \"decl\" (case s.b. 273) @ position[%d,%d..%d,%d]\n",
69*0c8de5b0SBaptiste Daroussin 			 msg,
70*0c8de5b0SBaptiste Daroussin 			 @$.first_line, @$.first_column,
71*0c8de5b0SBaptiste Daroussin 			 @$.last_line, @$.last_column);
72*0c8de5b0SBaptiste Daroussin 		  free($<decl>$->scope); free($<decl>$->type); } decl
73*0c8de5b0SBaptiste Daroussin %destructor	{ printf("%s accessed by symbol with type <decl> (case s.b. 279 & 280) @ position[%d,%d..%d,%d]\n",
74*0c8de5b0SBaptiste Daroussin 			 msg,
75*0c8de5b0SBaptiste Daroussin 			 @$.first_line, @$.first_column,
76*0c8de5b0SBaptiste Daroussin 			 @$.last_line, @$.last_column);
77*0c8de5b0SBaptiste Daroussin 		  free($$); } <decl>
78*0c8de5b0SBaptiste Daroussin %destructor	{ printf("%s accessed by symbol of any type other than <decl>  @ position[%d,%d..%d,%d]\n",
79*0c8de5b0SBaptiste Daroussin 			 msg,
80*0c8de5b0SBaptiste Daroussin 			 @$.first_line, @$.first_column,
81*0c8de5b0SBaptiste Daroussin 			 @$.last_line, @$.last_column);
82*0c8de5b0SBaptiste Daroussin 		  free($$); } <*>
83*0c8de5b0SBaptiste Daroussin %destructor	{ printf("%s accessed by symbol with no type @ position[%d,%d..%d,%d]\n",
84*0c8de5b0SBaptiste Daroussin 			 msg,
85*0c8de5b0SBaptiste Daroussin 			 @$.first_line, @$.first_column,
86*0c8de5b0SBaptiste Daroussin 			 @$.last_line, @$.last_column);
87*0c8de5b0SBaptiste Daroussin 		  /* in this example, we don't know what to do here */ } <>
88*0c8de5b0SBaptiste Daroussin 
89*0c8de5b0SBaptiste Daroussin %start input
90*0c8de5b0SBaptiste Daroussin 
91*0c8de5b0SBaptiste Daroussin %%
92*0c8de5b0SBaptiste Daroussin 
93*0c8de5b0SBaptiste Daroussin opt_scope($e):		[ $$ = $e; ]
94*0c8de5b0SBaptiste Daroussin   | CLCL		[ $$ = global_scope; ]
95*0c8de5b0SBaptiste Daroussin   | opt_scope ID CLCL	[ Decl *d = lookup($1, $2);
96*0c8de5b0SBaptiste Daroussin 			  if (!d || !d->scope) YYERROR;
97*0c8de5b0SBaptiste Daroussin 			  $$ = d->scope; ]
98*0c8de5b0SBaptiste Daroussin   ;
99*0c8de5b0SBaptiste Daroussin 
100*0c8de5b0SBaptiste Daroussin typename($e): opt_scope ID
101*0c8de5b0SBaptiste Daroussin       [ Decl *d = lookup($1, $2);
102*0c8de5b0SBaptiste Daroussin 	if (d == NULL || d->istype() == 0) YYERROR;
103*0c8de5b0SBaptiste Daroussin 	$$ = d->type; ]
104*0c8de5b0SBaptiste Daroussin   ;
105*0c8de5b0SBaptiste Daroussin 
106*0c8de5b0SBaptiste Daroussin input: decl_list(global_scope = new_scope(0)) ;
107*0c8de5b0SBaptiste Daroussin decl_list($e): | decl_list decl($e) ;
108*0c8de5b0SBaptiste Daroussin decl($e):
109*0c8de5b0SBaptiste Daroussin     decl_specs declarator_list($e,$1) ';' [YYVALID;]
110*0c8de5b0SBaptiste Daroussin   | decl_specs declarator($e,$1) block_statement(start_fn_def($e, $2))
111*0c8de5b0SBaptiste Daroussin       { /* demonstrate use of @$ & @N, although this is just the
112*0c8de5b0SBaptiste Daroussin 	   default computation and so is not necessary */
113*0c8de5b0SBaptiste Daroussin 	@$.first_line   = @1.first_line;
114*0c8de5b0SBaptiste Daroussin 	@$.first_column = @1.first_column;
115*0c8de5b0SBaptiste Daroussin 	@$.last_line    = @3.last_line;
116*0c8de5b0SBaptiste Daroussin 	@$.last_column  = @3.last_column;
117*0c8de5b0SBaptiste Daroussin 	finish_fn_def($2, $3); }
118*0c8de5b0SBaptiste Daroussin   ;
119*0c8de5b0SBaptiste Daroussin 
120*0c8de5b0SBaptiste Daroussin decl_specs($e):
121*0c8de5b0SBaptiste Daroussin     decl_spec			[ $$ = $1; ]
122*0c8de5b0SBaptiste Daroussin   | decl_specs decl_spec($e)	[ $$ = type_combine($1, $2); ]
123*0c8de5b0SBaptiste Daroussin   ;
124*0c8de5b0SBaptiste Daroussin 
125*0c8de5b0SBaptiste Daroussin cv_quals:			[ $$ = 0; ]
126*0c8de5b0SBaptiste Daroussin   | cv_quals cv_qual		[ $$ = type_combine($1, $2); ]
127*0c8de5b0SBaptiste Daroussin   ;
128*0c8de5b0SBaptiste Daroussin 
129*0c8de5b0SBaptiste Daroussin decl_spec($e):
130*0c8de5b0SBaptiste Daroussin     cv_qual		[ $$ = $1; ]
131*0c8de5b0SBaptiste Daroussin   | typename		[ $$ = $1; ]
132*0c8de5b0SBaptiste Daroussin   | EXTERN		[ $$ = bare_extern(); ]
133*0c8de5b0SBaptiste Daroussin   | REGISTER		[ $$ = bare_register(); ]
134*0c8de5b0SBaptiste Daroussin   | STATIC		[ $$ = bare_static(); ]
135*0c8de5b0SBaptiste Daroussin   ;
136*0c8de5b0SBaptiste Daroussin 
137*0c8de5b0SBaptiste Daroussin cv_qual:
138*0c8de5b0SBaptiste Daroussin     CONST		[ $$ = bare_const(); ]
139*0c8de5b0SBaptiste Daroussin   | VOLATILE		[ $$ = bare_volatile(); ]
140*0c8de5b0SBaptiste Daroussin   ;
141*0c8de5b0SBaptiste Daroussin 
142*0c8de5b0SBaptiste Daroussin declarator_list($e, $t):
143*0c8de5b0SBaptiste Daroussin     declarator_list ',' declarator($e, $t)
144*0c8de5b0SBaptiste Daroussin   | declarator
145*0c8de5b0SBaptiste Daroussin   ;
146*0c8de5b0SBaptiste Daroussin 
declarator($e,$t)147*0c8de5b0SBaptiste Daroussin declarator($e, $t):
148*0c8de5b0SBaptiste Daroussin     /* empty */			[ if (!$t) YYERROR; ]
149*0c8de5b0SBaptiste Daroussin 				{ $$ = declare($e, 0, $t); }
150*0c8de5b0SBaptiste Daroussin   | ID				{ $$ = declare($e, $1, $t); }
151*0c8de5b0SBaptiste Daroussin   | '(' declarator($e, $t) ')'	{ $$ = $2; }
152*0c8de5b0SBaptiste Daroussin   | '*' cv_quals declarator($e, $t) %prec PREFIX
153*0c8de5b0SBaptiste Daroussin 	  { $$ = make_pointer($3, $2); }
154*0c8de5b0SBaptiste Daroussin   | declarator '[' expr($e) ']'
155*0c8de5b0SBaptiste Daroussin 	  { $$ = make_array($1->type, $3); }
156*0c8de5b0SBaptiste Daroussin   | declarator '(' formal_arg_list($e) ')' cv_quals
157*0c8de5b0SBaptiste Daroussin 	  { $$ = build_function($1, $3, $5); }
158*0c8de5b0SBaptiste Daroussin   ;
159*0c8de5b0SBaptiste Daroussin 
formal_arg_list($e)160*0c8de5b0SBaptiste Daroussin formal_arg_list($e):		{ $$ = 0; }
161*0c8de5b0SBaptiste Daroussin   | nonempty_formal_arg_list	{ $$ = $1; }
162*0c8de5b0SBaptiste Daroussin   ;
163*0c8de5b0SBaptiste Daroussin nonempty_formal_arg_list($e):
164*0c8de5b0SBaptiste Daroussin     nonempty_formal_arg_list ',' formal_arg($e)	{ $$ = append_dlist($1, $3); }
165*0c8de5b0SBaptiste Daroussin   | formal_arg					{ $$ = build_dlist($1); }
166*0c8de5b0SBaptiste Daroussin   ;
formal_arg($e)167*0c8de5b0SBaptiste Daroussin formal_arg($e):
168*0c8de5b0SBaptiste Daroussin     decl_specs declarator($e,$1)	{ $$ = $2; }
169*0c8de5b0SBaptiste Daroussin   ;
170*0c8de5b0SBaptiste Daroussin 
171*0c8de5b0SBaptiste Daroussin expr($e):
172*0c8de5b0SBaptiste Daroussin     expr '+' expr($e)		{ $$ = build_expr($1, ADD, $3); }
173*0c8de5b0SBaptiste Daroussin   | expr '-' expr($e)		{ $$ = build_expr($1, SUB, $3); }
174*0c8de5b0SBaptiste Daroussin   | expr '*' expr($e)		{ $$ = build_expr($1, MUL, $3); }
175*0c8de5b0SBaptiste Daroussin   | expr '%' expr($e)		{ $$ = build_expr($1, MOD, $3); }
176*0c8de5b0SBaptiste Daroussin   | expr '/' expr($e)		{ $$ = build_expr($1, DIV, $3); }
177*0c8de5b0SBaptiste Daroussin   | '*' expr($e) %prec PREFIX	{ $$ = build_expr(0, DEREF, $2); }
178*0c8de5b0SBaptiste Daroussin   | ID				{ $$ = var_expr($e, $1); }
179*0c8de5b0SBaptiste Daroussin   | CONSTANT			{ $$ = $1; }
180*0c8de5b0SBaptiste Daroussin   ;
181*0c8de5b0SBaptiste Daroussin 
statement($e)182*0c8de5b0SBaptiste Daroussin statement($e):
183*0c8de5b0SBaptiste Daroussin     decl			{ $$ = 0; }
184*0c8de5b0SBaptiste Daroussin   | expr($e) ';' [YYVALID;]	{ $$ = build_expr_code($1); }
185*0c8de5b0SBaptiste Daroussin   | IF '(' expr($e) ')' THEN statement($e) ELSE statement($e) [YYVALID;]
186*0c8de5b0SBaptiste Daroussin     { $$ = build_if($3, $6, $8); }
187*0c8de5b0SBaptiste Daroussin   | IF '(' expr($e) ')' THEN statement($e) [YYVALID;]
188*0c8de5b0SBaptiste Daroussin     { $$ = build_if($3, $6, 0); }
189*0c8de5b0SBaptiste Daroussin   | block_statement(new_scope($e)) [YYVALID;]{ $$ = $1; }
190*0c8de5b0SBaptiste Daroussin   ;
191*0c8de5b0SBaptiste Daroussin 
statement_list($e)192*0c8de5b0SBaptiste Daroussin statement_list($e):			{ $$ = 0; }
193*0c8de5b0SBaptiste Daroussin   | statement_list statement($e)	{ $$ = code_append($1, $2); }
194*0c8de5b0SBaptiste Daroussin   ;
195*0c8de5b0SBaptiste Daroussin 
196*0c8de5b0SBaptiste Daroussin block_statement($e):
197*0c8de5b0SBaptiste Daroussin     '{' statement_list($e) '}' { $$ = $2; }
198*0c8de5b0SBaptiste Daroussin   ;
199*0c8de5b0SBaptiste Daroussin %%
200*0c8de5b0SBaptiste Daroussin 
201*0c8de5b0SBaptiste Daroussin extern int YYLEX_DECL();
202*0c8de5b0SBaptiste Daroussin extern void YYERROR_DECL();
203*0c8de5b0SBaptiste Daroussin 
204*0c8de5b0SBaptiste Daroussin extern Scope *global_scope;
205*0c8de5b0SBaptiste Daroussin 
206*0c8de5b0SBaptiste Daroussin extern Decl * lookup(Scope *scope, char *id);
207*0c8de5b0SBaptiste Daroussin extern Scope * new_scope(Scope *outer_scope);
208*0c8de5b0SBaptiste Daroussin extern Scope * start_fn_def(Scope *scope, Decl *fn_decl);
209*0c8de5b0SBaptiste Daroussin extern void finish_fn_def(Decl *fn_decl, Code *block);
210*0c8de5b0SBaptiste Daroussin extern Type * type_combine(Type *specs, Type *spec);
211*0c8de5b0SBaptiste Daroussin extern Type * bare_extern(void);
212*0c8de5b0SBaptiste Daroussin extern Type * bare_register(void);
213*0c8de5b0SBaptiste Daroussin extern Type * bare_static(void);
214*0c8de5b0SBaptiste Daroussin extern Type * bare_const(void);
215*0c8de5b0SBaptiste Daroussin extern Type * bare_volatile(void);
216*0c8de5b0SBaptiste Daroussin extern Decl * declare(Scope *scope, char *id, Type *type);
217*0c8de5b0SBaptiste Daroussin extern Decl * make_pointer(Decl *decl, Type *type);
218*0c8de5b0SBaptiste Daroussin extern Decl * make_array(Type *type, Expr *expr);
219*0c8de5b0SBaptiste Daroussin extern Decl * build_function(Decl *decl, Decl_List *dlist, Type *type);
220*0c8de5b0SBaptiste Daroussin extern Decl_List * append_dlist(Decl_List *dlist, Decl *decl);
221*0c8de5b0SBaptiste Daroussin extern Decl_List * build_dlist(Decl *decl);
222*0c8de5b0SBaptiste Daroussin extern Expr * build_expr(Expr *left, enum Operator op, Expr *right);
223*0c8de5b0SBaptiste Daroussin extern Expr * var_expr(Scope *scope, char *id);
224*0c8de5b0SBaptiste Daroussin extern Code * build_expr_code(Expr *expr);
225*0c8de5b0SBaptiste Daroussin extern Code * build_if(Expr *cond_expr, Code *then_stmt, Code *else_stmt);
226*0c8de5b0SBaptiste Daroussin extern Code * code_append(Code *stmt_list, Code *stmt);
227