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