btyacc_demo.y revision 264790
123462Sjmg/*
250476Speter * demonstrate enhancements derived from btyacc:
323462Sjmg * backtracking to resolve conflicts
45909Sjmz * semantic disambiguation via []-actions invoking YYVALID & YYERROR
572762Sru * %locations
679538Sru * @$ & @N to refer to lhs & rhs symbol location
75909Sjmz * %destructor
85909Sjmz * syntactic suger for inherited attributes
95909Sjmz * extension to %type to define inherited attribute type
105909Sjmz */
11166599Sbrueffer
12166599Sbrueffer%LOCATIONS
13166599Sbrueffer
14166599Sbrueffer%{
15166599Sbrueffer/* dummy types just for compile check */
16166599Sbrueffertypedef int Code;
1768246Ssheldonhtypedef int Decl_List;
18166599Sbrueffertypedef int Expr;
19166599Sbrueffertypedef int Expr_List;
20166599Sbrueffertypedef int Scope;
21166599Sbrueffertypedef int Type;
22166667Sbruefferenum Operator { ADD, SUB, MUL, MOD, DIV, DEREF };
23166599Sbrueffer
2468246Ssheldonhtypedef unsigned char bool;
2584877Syokotatypedef struct Decl {
2699871Sru    Scope *scope;
2784877Syokota    Type  *type;
2884877Syokota    bool (*istype)(void);
29152313Sjylefort} Decl;
30152313Sjylefort
3184877Syokota#include "btyacc_demo.tab.h"
3293229Sru#include <stdlib.h>
335909Sjmz#include <stdio.h>
345909Sjmz%}
355909Sjmz
365909Sjmz%union {
375909Sjmz    Scope	*scope;
385909Sjmz    Expr	*expr;
3946582Sbillf    Expr_List	*elist;
4057731Ssheldonh    Type	*type;
4157731Ssheldonh    Decl	*decl;
426644Sjmz    Decl_List	*dlist;
436644Sjmz    Code	*code;
446644Sjmz    char	*id;
456644Sjmz    };
466644Sjmz
476644Sjmz%left '+' '-'
486644Sjmz%left '*' '/' '%'
496644Sjmz%nonassoc PREFIX
506644Sjmz%nonassoc POSTFIX '(' '[' '.'
516644Sjmz
525909Sjmz%token <id>	ID
5368575Sru%token <expr>	CONSTANT
545909Sjmz%token		EXTERN REGISTER STATIC CONST VOLATILE IF THEN ELSE CLCL
555909Sjmz
5668575Sru%type <expr>	expr(<scope>)
575909Sjmz%type		decl(<scope>) declarator_list(<scope>, <type>)
5857731Ssheldonh		decl_list(<scope>)
5957731Ssheldonh%type <code>	statement(<scope>) statement_list(<scope>)
605909Sjmz		block_statement(<scope>)
6179727Sschweikh%type <decl>	declarator(<scope>, <type>) formal_arg(<scope>)
6212695Sjmz%type <type>	decl_specs(<scope>) decl_spec(<scope>) typename(<scope>)
635909Sjmz		cv_quals cv_qual
6457731Ssheldonh%type <scope>	opt_scope(<scope>)
6557731Ssheldonh%type <dlist>	formal_arg_list(<scope>) nonempty_formal_arg_list(<scope>)
665909Sjmz
675909Sjmz%destructor	{ // 'msg' is a 'char *' indicating the context of destructor invocation
6879727Sschweikh		  printf("%s accessed by symbol \"decl\" (case s.b. 273) @ position[%d,%d..%d,%d]\n",
6912695Sjmz			 msg,
705909Sjmz			 @$.first_line, @$.first_column,
7179727Sschweikh			 @$.last_line, @$.last_column);
725909Sjmz		  free($<decl>$->scope); free($<decl>$->type); } decl
73131530Sru%destructor	{ printf("%s accessed by symbol with type <decl> (case s.b. 279 & 280) @ position[%d,%d..%d,%d]\n",
7479727Sschweikh			 msg,
755909Sjmz			 @$.first_line, @$.first_column,
76131530Sru			 @$.last_line, @$.last_column);
7779727Sschweikh		  free($$); } <decl>
785909Sjmz%destructor	{ printf("%s accessed by symbol of any type other than <decl>  @ position[%d,%d..%d,%d]\n",
79131530Sru			 msg,
8079727Sschweikh			 @$.first_line, @$.first_column,
815909Sjmz			 @$.last_line, @$.last_column);
82131530Sru		  free($$); } <*>
8379727Sschweikh%destructor	{ printf("%s accessed by symbol with no type @ position[%d,%d..%d,%d]\n",
8470466Sru			 msg,
8510822Sjmz			 @$.first_line, @$.first_column,
8610822Sjmz			 @$.last_line, @$.last_column);
8771263Sru		  /* in this example, we don't know what to do here */ } <>
8810822Sjmz
8910822Sjmz%start input
9010822Sjmz
9110822Sjmz%%
9210822Sjmz
9310822Sjmzopt_scope($e):		[ $$ = $e; ]
9410822Sjmz  | CLCL		[ $$ = global_scope; ]
9510822Sjmz  | opt_scope ID CLCL	[ Decl *d = lookup($1, $2);
9610822Sjmz			  if (!d || !d->scope) YYERROR;
9710822Sjmz			  $$ = d->scope; ]
9810822Sjmz  ;
9910822Sjmz
10010822Sjmztypename($e): opt_scope ID
10110822Sjmz      [ Decl *d = lookup($1, $2);
10210822Sjmz	if (d == NULL || d->istype() == 0) YYERROR;
10371263Sru	$$ = d->type; ]
10410822Sjmz  ;
10510822Sjmz
106165215Smppinput: decl_list(global_scope = new_scope(0)) ;
10710822Sjmzdecl_list($e): | decl_list decl($e) ;
1085909Sjmzdecl($e):
1095909Sjmz    decl_specs declarator_list($e,$1) ';' [YYVALID;]
1105909Sjmz  | decl_specs declarator($e,$1) block_statement(start_fn_def($e, $2))
1115909Sjmz      { /* demonstrate use of @$ & @N, although this is just the
11270466Sru	   default computation and so is not necessary */
1135909Sjmz	@$.first_line   = @1.first_line;
114166599Sbrueffer	@$.first_column = @1.first_column;
115166599Sbrueffer	@$.last_line    = @3.last_line;
116166599Sbrueffer	@$.last_column  = @3.last_column;
11717762Smpp	finish_fn_def($2, $3); }
118140561Sru  ;
119267938Sbapt
120decl_specs($e):
121    decl_spec			[ $$ = $1; ]
122  | decl_specs decl_spec($e)	[ $$ = type_combine($1, $2); ]
123  ;
124
125cv_quals:			[ $$ = 0; ]
126  | cv_quals cv_qual		[ $$ = type_combine($1, $2); ]
127  ;
128
129decl_spec($e):
130    cv_qual		[ $$ = $1; ]
131  | typename		[ $$ = $1; ]
132  | EXTERN		[ $$ = bare_extern(); ]
133  | REGISTER		[ $$ = bare_register(); ]
134  | STATIC		[ $$ = bare_static(); ]
135  ;
136
137cv_qual:
138    CONST		[ $$ = bare_const(); ]
139  | VOLATILE		[ $$ = bare_volatile(); ]
140  ;
141
142declarator_list($e, $t):
143    declarator_list ',' declarator($e, $t)
144  | declarator
145  ;
146
147declarator($e, $t):
148    /* empty */			[ if (!$t) YYERROR; ]
149				{ $$ = declare($e, 0, $t); }
150  | ID				{ $$ = declare($e, $1, $t); }
151  | '(' declarator($e, $t) ')'	{ $$ = $2; }
152  | '*' cv_quals declarator($e, $t) %prec PREFIX
153	  { $$ = make_pointer($3, $2); }
154  | declarator '[' expr($e) ']'
155	  { $$ = make_array($1->type, $3); }
156  | declarator '(' formal_arg_list($e) ')' cv_quals
157	  { $$ = build_function($1, $3, $5); }
158  ;
159
160formal_arg_list($e):		{ $$ = 0; }
161  | nonempty_formal_arg_list	{ $$ = $1; }
162  ;
163nonempty_formal_arg_list($e):
164    nonempty_formal_arg_list ',' formal_arg($e)	{ $$ = append_dlist($1, $3); }
165  | formal_arg					{ $$ = build_dlist($1); }
166  ;
167formal_arg($e):
168    decl_specs declarator($e,$1)	{ $$ = $2; }
169  ;
170
171expr($e):
172    expr '+' expr($e)		{ $$ = build_expr($1, ADD, $3); }
173  | expr '-' expr($e)		{ $$ = build_expr($1, SUB, $3); }
174  | expr '*' expr($e)		{ $$ = build_expr($1, MUL, $3); }
175  | expr '%' expr($e)		{ $$ = build_expr($1, MOD, $3); }
176  | expr '/' expr($e)		{ $$ = build_expr($1, DIV, $3); }
177  | '*' expr($e) %prec PREFIX	{ $$ = build_expr(0, DEREF, $2); }
178  | ID				{ $$ = var_expr($e, $1); }
179  | CONSTANT			{ $$ = $1; }
180  ;
181
182statement($e):
183    decl			{ $$ = 0; }
184  | expr($e) ';' [YYVALID;]	{ $$ = build_expr_code($1); }
185  | IF '(' expr($e) ')' THEN statement($e) ELSE statement($e) [YYVALID;]
186    { $$ = build_if($3, $6, $8); }
187  | IF '(' expr($e) ')' THEN statement($e) [YYVALID;]
188    { $$ = build_if($3, $6, 0); }
189  | block_statement(new_scope($e)) [YYVALID;]{ $$ = $1; }
190  ;
191
192statement_list($e):			{ $$ = 0; }
193  | statement_list statement($e)	{ $$ = code_append($1, $2); }
194  ;
195
196block_statement($e):
197    '{' statement_list($e) '}' { $$ = $2; }
198  ;
199%%
200
201extern int YYLEX_DECL();
202extern void YYERROR_DECL();
203
204extern Scope *global_scope;
205
206extern Decl * lookup(Scope *scope, char *id);
207extern Scope * new_scope(Scope *outer_scope);
208extern Scope * start_fn_def(Scope *scope, Decl *fn_decl);
209extern void finish_fn_def(Decl *fn_decl, Code *block);
210extern Type * type_combine(Type *specs, Type *spec);
211extern Type * bare_extern(void);
212extern Type * bare_register(void);
213extern Type * bare_static(void);
214extern Type * bare_const(void);
215extern Type * bare_volatile(void);
216extern Decl * declare(Scope *scope, char *id, Type *type);
217extern Decl * make_pointer(Decl *decl, Type *type);
218extern Decl * make_array(Type *type, Expr *expr);
219extern Decl * build_function(Decl *decl, Decl_List *dlist, Type *type);
220extern Decl_List * append_dlist(Decl_List *dlist, Decl *decl);
221extern Decl_List * build_dlist(Decl *decl);
222extern Expr * build_expr(Expr *left, enum Operator op, Expr *right);
223extern Expr * var_expr(Scope *scope, char *id);
224extern Code * build_expr_code(Expr *expr);
225extern Code * build_if(Expr *cond_expr, Code *then_stmt, Code *else_stmt);
226extern Code * code_append(Code *stmt_list, Code *stmt);
227