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