(file) Return to cparser.mly CVS log (file) (dir) Up to [venge] / src / mkc / frontc

File: [venge] / src / mkc / frontc / cparser.mly (download)
Revision: 1.1, Sun Apr 28 04:13:15 2002 UTC (8 years, 4 months ago) by graydon
Branch: MAIN
CVS Tags: HEAD
2002-04-28  Graydon Hoare  <graydon@redhat.com>

	* frontc/*: Import from cdk.
	* fe.ml: False -> false, for camlp4 3.04 compat.
	* driver.ml: Use mkc-fe from mkcamlp4.
	* Makefile: Teach to build mkc-fe, frontc.

/* NOTE: in the symbol table, local definition must replace type definition
**		in order to correctly parse local variable in functions body.
**		This is the only way to correctly handle this kind of exception,
**		that is,
**
**		typedef ... ID;
**		int f(int *p) {int ID; return (ID) * *p;}
**		If ID isn't overload, last expression is parsed as a type cast,
**		if it isn't, this a multiplication.
**
** IMPLEMENT:
**		(1) Old-parameter passing style with an exception: the first old-style
**		parameter name can't be a type name.
**		(2) GNU __attribute__ modifier, GNU ({ }) statement in expression form.
**
** HISTORY
**	1.0	2.19.99	Hugues Cassé	First version.
**	2.0	3.22.99	Hugues Cassé	Large simplification about declarations.
**								"register" parameters added, function pointers,
**								GCC attributes, typedef full supported.
**	2.1	4.23.99	Hugues Cassé	GNU Statement embedded statements managed.
**		a	&x == y was analyzed as ADDROF(EQ(x, y)) corrected into the
**			right form EQ(ADDROF(x), y)
**		b	typedef struct ID ... ID; is now accepted.
**		c	{v1, v2, v3, } now accepted.
**		d	Spaced string components now accepted. Example: "Hel" "lo !".
**	3.0	6.1.99	Hugues Cassé	Solve fully the problem of local/field/parameter
**								with the same identifier to a typedef.
**	a							const and volatile accepted for basic types
**								for fields and only-types.
**	b	10.9.99	Hugues Cassé	Correct priorities of type algebra:
**								()() > * > []. Add typalg.c for testing it.	
*/
%{
open Cabs
let version = "Cparser V3.0b 10.9.99 Hugues Cassé"

let parse_error msg =
	Clexer.display_error "Syntax error" (Parsing.symbol_start ()) (Parsing.symbol_end ())


(*
** Type analysis
*)
exception BadModifier
exception BadType
type modifier =
	BASE_SIZE of size
	| BASE_SIGN of sign
	| BASE_STORAGE of storage
	| BASE_VOLATILE
	| BASE_CONST

let apply_mod (typ, sto) modi =
	let rec mod_root typ =
		match (typ, modi) with
		(NO_TYPE, BASE_SIGN sign) -> INT (NO_SIZE, sign)
		| (NO_TYPE, BASE_SIZE size) -> INT (size, NO_SIGN)
		| (CHAR NO_SIGN, BASE_SIGN sign) -> CHAR sign
		| (INT (NO_SIZE, sign), BASE_SIZE size) -> INT (size, sign)
		| (INT (LONG, sign), BASE_SIZE LONG) -> INT (LONG_LONG, sign)
		| (INT (size, NO_SIGN), BASE_SIGN sign) -> INT (size, sign)
		| (BITFIELD (NO_SIGN, exp), BASE_SIGN sign) -> BITFIELD (sign, exp)
		| (FLOAT false, BASE_SIZE LONG) -> FLOAT true
		| (DOUBLE false, BASE_SIZE LONG) -> DOUBLE true
		| (PTR typ, _) -> PTR (mod_root typ)
		| (CONST typ, _) -> CONST (mod_root typ)
		| (VOLATILE typ, _) -> VOLATILE (mod_root typ)
		| _ -> raise BadModifier in
	let check_access typ =
		match typ with
		PROTO _ | OLD_PROTO _ | CONST _ | VOLATILE _ -> false
		| _ -> true in
	match modi with
	BASE_SIGN _ -> (mod_root typ, sto)
	| BASE_SIZE _ -> (mod_root typ, sto)
	| BASE_CONST ->
		if (check_access typ) then (CONST typ, sto)
		else raise BadModifier
	| BASE_VOLATILE ->
		if (check_access typ) then (VOLATILE typ, sto)
		else raise BadModifier
	| BASE_STORAGE sto' ->
		if sto = NO_STORAGE then (typ, sto')
		else raise BadModifier

let apply_mods mods fty =
	List.fold_left apply_mod fty mods

let set_type tst tin =
	let rec set typ =
		match typ with
		NO_TYPE -> tst
		| PTR typ -> PTR (set typ)
		| ARRAY (typ, dim) -> ARRAY (set typ, dim)
		| PROTO (typ, pars, ell) -> PROTO (set typ, pars, ell)
		| OLD_PROTO (typ, pars, ell) -> OLD_PROTO (set typ, pars, ell)
		| CONST typ -> CONST (set typ)
		| VOLATILE typ -> VOLATILE (set typ)
		| BITFIELD (NO_SIGN, exp) ->
			(match tst with
				INT (_, sign) -> BITFIELD (sign, exp)
				| _ -> raise BadType)
		| _ -> raise BadType in
	set tin


(*
** Expression building 
*)
let smooth_expression lst =
	match lst with
		[] -> NOTHING
		| [expr] -> expr
		| _ -> COMMA (List.rev lst)
let list_expression expr =
	match expr with
		COMMA lst -> lst
		| NOTHING -> []
		| _ -> [expr]


(*** Named Building ***)
let set_name (typ : base_type) (id, typ', attr, exp) =
	(id, set_type typ typ', attr, exp)
	
let set_name_group (typ, sto) (lst : name list)
: name_group =
	(typ, sto, List.map (set_name typ) lst)
	
let set_single (typ, sto) name : single_name =
	(typ, sto, set_name typ name)

let set_data (id, typ, attr, _) ini = (id, typ, attr, ini)

let apply_qual ((t1, q1) : base_type * modifier list)
			   ((t2, q2) : base_type * modifier list)
			   : base_type * modifier list =
	((if t1 = NO_TYPE then t2 else
		if t2 = NO_TYPE then t1 else  raise BadModifier),
	List.append q1 q2)
%}

%token <string> IDENT
%token <string> CST_CHAR
%token <string> CST_INT
%token <string> CST_FLOAT
%token <string> CST_STRING
%token <string> NAMED_TYPE

%token EOF
%token CHAR INT DOUBLE FLOAT VOID
%token ENUM STRUCT TYPEDEF UNION
%token SIGNED UNSIGNED LONG SHORT
%token VOLATILE EXTERN STATIC CONST AUTO REGISTER

%token SIZEOF

%token EQ PLUS_EQ MINUS_EQ STAR_EQ SLASH_EQ PERCENT_EQ
%token AND_EQ PIPE_EQ CIRC_EQ INF_INF_EQ SUP_SUP_EQ
%token ARROW DOT

%token EQ_EQ EXCLAM_EQ INF SUP INF_EQ SUP_EQ
%token PLUS MINUS STAR SLASH PERCENT
%token TILDE AND PIPE CIRC
%token EXCLAM AND_AND PIPE_PIPE
%token INF_INF SUP_SUP
%token PLUS_PLUS MINUS_MINUS

%token RPAREN LPAREN RBRACE LBRACE LBRACKET RBRACKET
%token COLON SEMICOLON COMMA ELLIPSIS QUEST

%token BREAK CONTINUE GOTO RETURN
%token SWITCH CASE DEFAULT
%token WHILE DO FOR
%token IF ELSE

%token ATTRIBUTE

/* operator precedence */
%nonassoc 	IF
%nonassoc 	ELSE

%left	COMMA
%right	EQ PLUS_EQ MINUS_EQ STAR_EQ SLASH_EQ PERCENT_EQ
		AND_EQ PIPE_EQ CIRC_EQ INF_INF_EQ SUP_SUP_EQ
%right	QUEST COLON
%left	PIPE_PIPE
%left	AND_AND
%left	PIPE
%left 	CIRC
%left	AND
%left	EQ_EQ EXCLAM_EQ
%left	INF SUP INF_EQ SUP_EQ
%left	INF_INF SUP_SUP
%left	PLUS MINUS
%left	STAR SLASH PERCENT CONST VOLATILE
%right	EXCLAM TILDE PLUS_PLUS MINUS_MINUS CAST RPAREN ADDROF
%left 	LBRACKET
%left	DOT ARROW LPAREN LBRACE SIZEOF

/* Non-terminals informations */
%start interpret file
%type <Cabs.definition list> file interpret globals

%type <Cabs.definition> global
%type <Cabs.base_type * Cabs.storage> global_type
%type <Cabs.base_type * modifier list> global_qual
%type <modifier list> global_mod_list_opt global_mod_list
%type <modifier> global_mod
%type <Cabs.name list> global_defs
%type <Cabs.name> global_def
%type <string * Cabs.base_type> global_dec

%type <Cabs.definition> local
%type <Cabs.base_type * Cabs.storage> local_type
%type <Cabs.base_type * modifier list> local_qual
%type <modifier list> local_mod_list_opt local_mod_list
%type <modifier> local_mod
%type <Cabs.name list> local_defs
%type <Cabs.name> local_def
%type <string * Cabs.base_type> local_dec

%type <Cabs.attributes> gcc_attributes
%type <Cabs.definition list * Cabs.statement> body
%type <Cabs.statement> statement opt_stats stats
%type <Cabs.constant> constant
%type <Cabs.expression> expression init_expression opt_expression
%type <Cabs.expression list> comma_expression init_comma_expression
%type <Cabs.single_name list * bool> parameters
%type <string> string_list


%%

interpret:
		file EOF						{$1}
;
file:
		/* empty */						{[]}
|		globals							{List.rev $1}
;
globals:
		global							{[$1]}
|		globals global					{$2::$1}
;


/*** Global Definition ***/
global:
		global_type global_defs SEMICOLON
			{DECDEF (set_name_group $1 (List.rev $2))}
|		global_type global_proto body
			{FUNDEF (set_single $1 $2, $3)}
|		global_type old_proto old_pardefs body
			{OLDFUNDEF (set_single $1 $2, List.rev $3, $4)}
|		global_type SEMICOLON
			{ONLYTYPEDEF (set_name_group $1 [])}
|		TYPEDEF typedef_type typedef_defs SEMICOLON
			{let _ = List.iter (fun (id, _, _, _) -> Clexer.add_type id) $3 in
			TYPEDEF (set_name_group $2 $3)}
;
global_type:
		global_mod_list_opt global_qual
			{apply_mods (snd $2) (apply_mods $1 ((fst $2), NO_STORAGE))}
|		global_mod_list_opt comp_type global_mod_list_opt
			{apply_mods $3 (apply_mods $1 ($2, NO_STORAGE))}
|		global_mod_list_opt NAMED_TYPE global_mod_list_opt
			{apply_mods $3 (apply_mods $1 (NAMED_TYPE $2, NO_STORAGE))}
|		global_mod_list_opt
			{apply_mods $1 (NO_TYPE, NO_STORAGE)}
;
global_mod_list_opt:
		/* empty */						{[]}
|		global_mod_list					{List.rev $1}
;
global_mod_list:
		global_mod						{[$1]}
|		global_mod_list global_mod		{$2::$1}
;
global_mod:
		STATIC							{BASE_STORAGE STATIC}
|		CONST							{BASE_CONST}
|		VOLATILE						{BASE_VOLATILE}
|		EXTERN							{BASE_STORAGE EXTERN}
;
global_qual:
		qual_type						{$1}
|		global_qual qual_type			{apply_qual $1 $2}
|		global_qual global_mod			{(fst $1, $2::(snd $1))}
;
global_defs:
		global_def						{[$1]}
|		global_defs COMMA global_def	{$3::$1}
;
global_def:
		global_dec gcc_attributes
			{(fst $1, snd $1, $2, NOTHING)}
|		global_dec gcc_attributes EQ init_expression
			{(fst $1, snd $1, $2, $4)}
;
global_dec:
		IDENT 
			{($1, NO_TYPE)}	
|		LPAREN global_dec RPAREN
			{$2}
|		STAR global_dec
			{(fst $2, set_type (PTR NO_TYPE) (snd $2))}
|		STAR CONST global_dec
			{(fst $3, set_type (CONST (PTR NO_TYPE)) (snd $3))}
|		STAR VOLATILE global_dec
			{(fst $3, set_type (VOLATILE (PTR NO_TYPE)) (snd $3))}
|		global_dec LBRACKET comma_expression RBRACKET
			{(fst $1, set_type (ARRAY (NO_TYPE, smooth_expression $3)) (snd $1))}
|		global_dec LBRACKET RBRACKET
			{(fst $1, set_type (ARRAY (NO_TYPE, NOTHING)) (snd $1))}
|		global_dec LPAREN parameters RPAREN			
			{(fst $1, PROTO (snd $1, fst $3, snd $3))}
|		LPAREN global_dec RPAREN LPAREN parameters RPAREN
			{(fst $2, set_type (PROTO (NO_TYPE, fst $5, snd $5)) (snd $2))}
|		global_dec LPAREN old_parameters RPAREN
			{(fst $1, OLD_PROTO (snd $1, fst $3, snd $3))}
|		LPAREN global_dec RPAREN LPAREN old_parameters RPAREN
			{(fst $2, set_type (OLD_PROTO (NO_TYPE, fst $5, snd $5)) (snd $2))}
;
global_proto:
		global_dec gcc_attributes
			{match (snd $1) with
				PROTO _ -> (fst $1, snd $1, $2, NOTHING)
				| _ -> raise BadType}
;
old_proto:
		global_dec gcc_attributes
			{match (snd $1) with
				OLD_PROTO _ -> (fst $1, snd $1, $2, NOTHING)
				| _ -> raise BadType}
;


/*** Old Parameter Style ***/
old_parameters:
		old_pardecs						{(List.rev $1, false)}
|		old_pardecs ELLIPSIS			{(List.rev $1, true)}
;
old_pardecs:
		IDENT							{[$1]}
|		old_pardecs COMMA IDENT			{$3::$1}
|		old_pardecs COMMA NAMED_TYPE	{$3::$1}
;

old_pardefs:
		old_pardef						{[$1]}
|		old_pardefs old_pardef			{$2::$1}
;
old_pardef:
		old_type old_defs SEMICOLON
			{set_name_group $1 (List.rev $2)}	
;
old_type:
		old_mods_opt NAMED_TYPE old_mods_opt
			{apply_mods $3 (apply_mods $1 (NAMED_TYPE $2, NO_STORAGE))}
|		old_mods_opt comp_type old_mods_opt
			{apply_mods $3 (apply_mods $1 ($2, NO_STORAGE))}
|		old_mods_opt old_qual
			{apply_mods (snd $2) (apply_mods $1 ((fst $2), NO_STORAGE))}
;
old_mods_opt:
		/* empty */						{[]}
|		CONST							{[BASE_CONST]}
|		REGISTER						{[BASE_STORAGE REGISTER]}
;
old_qual:
		qual_type						{$1}
|		old_qual qual_type				{apply_qual $1 $2}
|		old_qual CONST					{(fst $1, BASE_CONST::(snd $1))}
|		old_qual REGISTER				{(fst $1, (BASE_STORAGE REGISTER)::(snd $1))}
;
old_defs:
		old_def							{[$1]}
|		old_defs COMMA old_def			{$3::$1}
;
old_def:
		old_dec
			{(fst $1, snd $1, [], NOTHING)}
;
old_dec:
		IDENT
			{($1, NO_TYPE)}
|		STAR old_dec
			{(fst $2, set_type (PTR NO_TYPE) (snd $2))}
|		STAR CONST old_dec
			{(fst $3, set_type (CONST (PTR NO_TYPE)) (snd $3))}
|		STAR VOLATILE old_dec
			{(fst $3, set_type (VOLATILE (PTR NO_TYPE)) (snd $3))}
|		old_dec LBRACKET comma_expression RBRACKET
			{(fst $1, set_type (ARRAY (NO_TYPE, smooth_expression $3)) (snd $1))}
|		old_dec LBRACKET RBRACKET
			{(fst $1, set_type (ARRAY (NO_TYPE, NOTHING)) (snd $1))}
|		old_dec LPAREN parameters RPAREN				
			{(fst $1, PROTO (snd $1, fst $3, snd $3))}
|		LPAREN old_dec RPAREN LPAREN parameters RPAREN
			{(fst $2, set_type (PROTO (NO_TYPE, fst $5, snd $5)) (snd $2))}
|		LPAREN old_dec RPAREN
			{$2}
;


/*** Local Definition ***/
local:
		local_type local_defs SEMICOLON
			{DECDEF (set_name_group $1 (List.rev $2))}
;
local_type:
		local_mod_list_opt local_qual
			{apply_mods (snd $2) (apply_mods $1 ((fst $2), NO_STORAGE))}
|		local_mod_list_opt comp_type local_mod_list_opt
			{apply_mods $3 (apply_mods $1 ($2, NO_STORAGE))}
|		local_mod_list_opt NAMED_TYPE local_mod_list_opt
			{apply_mods $3 (apply_mods $1 (NAMED_TYPE $2, NO_STORAGE))}
;
local_mod_list_opt:						
		/* empty */						{[]}
|		local_mod_list					{List.rev $1}
;
local_mod_list:
		local_mod						{[$1]}
|		local_mod_list local_mod		{$2::$1}
;
local_mod:
		STATIC							{BASE_STORAGE STATIC}
|		AUTO							{BASE_STORAGE AUTO}
|		CONST							{BASE_CONST}
|		VOLATILE						{BASE_VOLATILE}
|		REGISTER						{BASE_STORAGE REGISTER}
|		EXTERN							{BASE_STORAGE EXTERN}
;
local_qual:
		qual_type						{$1}
|		local_qual qual_type			{apply_qual $1 $2}
|		local_qual local_mod			{(fst $1, $2::(snd $1))}
;
local_defs:
		local_def						{[$1]}
|		local_defs COMMA local_def		{$3::$1}
;
local_def:
		local_dec gcc_attributes
			{(fst $1, snd $1, $2, NOTHING)}
|		local_dec gcc_attributes EQ init_expression
			{(fst $1, snd $1, $2, $4)}
;
local_dec:
		IDENT
			{($1, NO_TYPE)}
|		NAMED_TYPE
			{Clexer.add_identifier $1;($1, NO_TYPE)}
|		STAR local_dec
			{(fst $2, set_type (PTR NO_TYPE) (snd $2))}
|		STAR CONST local_dec
			{(fst $3, set_type (CONST (PTR NO_TYPE)) (snd $3))}			
|		STAR VOLATILE local_dec
			{(fst $3, set_type (VOLATILE (PTR NO_TYPE)) (snd $3))}
|		local_dec LBRACKET comma_expression RBRACKET
			{(fst $1, set_type (ARRAY (NO_TYPE, smooth_expression $3)) (snd $1))}
|		local_dec LBRACKET RBRACKET
			{(fst $1, set_type (ARRAY (NO_TYPE, NOTHING)) (snd $1))}
|		local_dec LPAREN parameters RPAREN
			{(fst $1, PROTO (snd $1, fst $3, snd $3))}
|		LPAREN local_dec RPAREN LPAREN parameters RPAREN
			{(fst $2, set_type (PROTO (NO_TYPE, fst $5, snd $5)) (snd $2))}
|		LPAREN local_dec RPAREN
			{$2}
;


/*** Typedef Definition ***/
typedef_type:
		typedef_sub
			{apply_mods (snd $1) ((fst $1), NO_STORAGE)}
|		CONST typedef_sub
			{apply_mods (BASE_CONST::(snd $2)) ((fst $2), NO_STORAGE)}
;
typedef_sub:
		NAMED_TYPE						{(NAMED_TYPE $1, [])}
|		NAMED_TYPE CONST				{(NAMED_TYPE $1, [BASE_CONST])}
|		comp_type						{($1, [])}		
|		comp_type CONST					{($1, [BASE_CONST])}
|		typedef_qual					{$1}
;
typedef_qual:
		qual_type						{$1}
|		typedef_qual qual_type			{apply_qual $1 $2}
|		typedef_qual CONST				{(fst $1, BASE_CONST::(snd $1))}
;
typedef_defs:
		typedef_def						{[$1]}
|		typedef_defs COMMA typedef_def	{$3::$1}
typedef_def:
		typedef_dec						{(fst $1, snd $1, [], NOTHING)}
typedef_dec:
		IDENT
			{($1, NO_TYPE)}
|		STAR typedef_dec
			{(fst $2, set_type (PTR NO_TYPE) (snd $2))}
|		STAR CONST typedef_dec
			{(fst $3, set_type (CONST (PTR NO_TYPE)) (snd $3))}
|		STAR VOLATILE typedef_dec
			{(fst $3, set_type (VOLATILE (PTR NO_TYPE)) (snd $3))}
|		typedef_dec LBRACKET comma_expression RBRACKET
			{(fst $1, set_type (ARRAY (NO_TYPE, smooth_expression $3)) (snd $1))}
|		typedef_dec LBRACKET RBRACKET
			{(fst $1, set_type (ARRAY (NO_TYPE, NOTHING)) (snd $1))}
|		typedef_dec LPAREN parameters RPAREN
			{(fst $1, PROTO (snd $1, fst $3, snd $3))}
|		LPAREN typedef_dec RPAREN LPAREN parameters RPAREN
			{(fst $2, set_type (PROTO (NO_TYPE, fst $5, snd $5)) (snd $2))}
|		LPAREN typedef_dec RPAREN
			{$2}
;


/*** Field Definition ***/
field_list:
		field_list field				{$2::$1}
|		field							{[$1]}
;
field:
		field_type field_defs SEMICOLON	{set_name_group $1 (List.rev $2)}
;
field_type:
		field_mod_list_opt field_qual 
			{apply_mods (snd $2) (apply_mods $1 ((fst $2), NO_STORAGE))}
|		field_mod_list_opt comp_type field_mod_list_opt
			{apply_mods $3 (apply_mods $1 ($2, NO_STORAGE))}
|	field_mod_list_opt	NAMED_TYPE field_mod_list_opt
			{apply_mods $3 (apply_mods $1 (NAMED_TYPE $2, NO_STORAGE))}
;
field_mod_list_opt:
		/* empty */						{[]}
|		field_mod_list					{List.rev $1}
;
field_mod_list:
		field_mod						{[$1]}
|		field_mod_list field_mod		{$2::$1}
;
field_mod:
		CONST							{BASE_CONST}
|		VOLATILE						{BASE_VOLATILE}
;
field_qual:	
		qual_type						{$1}
|		field_qual qual_type			{apply_qual $1 $2}
|		field_qual field_mod			{(fst $1, $2::(snd $1))}
;
field_defs:
		field_defs COMMA field_def		{$3::$1}	
|		field_def						{[$1]}
;
field_def:
		field_dec						{(fst $1, snd $1, [], NOTHING)}
;
field_dec:
		IDENT
			{($1, NO_TYPE)}
|		NAMED_TYPE
			{($1, NO_TYPE)}
|		STAR field_dec
			{(fst $2, set_type (PTR NO_TYPE) (snd $2))}
|		STAR CONST field_dec
			{(fst $3, set_type (CONST (PTR NO_TYPE)) (snd $3))}
|		STAR VOLATILE field_dec
			{(fst $3, set_type (VOLATILE (PTR NO_TYPE)) (snd $3))}
|		field_dec LBRACKET comma_expression RBRACKET
			{(fst $1, set_type (ARRAY (NO_TYPE, smooth_expression $3)) (snd $1))}
|		field_dec LBRACKET RBRACKET
			{(fst $1, set_type (ARRAY (NO_TYPE, NOTHING)) (snd $1))}
|		field_dec LPAREN parameters RPAREN
			{(fst $1, PROTO (snd $1, fst $3, snd $3))}
|		LPAREN field_dec RPAREN LPAREN parameters RPAREN
			{(fst $2, set_type (PROTO (NO_TYPE, fst $5, snd $5)) (snd $2))}
|		LPAREN field_dec RPAREN
			{$2}
|		IDENT COLON expression
			{($1, BITFIELD (NO_SIGN, $3))}
;


/*** Parameter Definition ***/
parameters:
		/* empty */						{([], false)}
|		param_list						{(List.rev $1, false)}
|		param_list COMMA ELLIPSIS		{(List.rev $1, true)}
;
param_list:
		param_list COMMA param			{$3::$1}
|		param							{[$1]}
;
param:
		param_type param_def
			{set_single $1 $2}
;
param_type:
		param_mods_opt NAMED_TYPE param_mods_opt
			{apply_mods $3 (apply_mods $1 (NAMED_TYPE $2, NO_STORAGE))}
|		param_mods_opt comp_type param_mods_opt
			{apply_mods $3 (apply_mods $1 ($2, NO_STORAGE))}
|		param_mods_opt param_qual
			{apply_mods (snd $2) (apply_mods $1 ((fst $2), NO_STORAGE))}
;
param_mods_opt:
		/* empty */						{[]}
|		param_mods						{List.rev $1}
;
param_mods:
		param_mod						{[$1]}
|		param_mods param_mod			{$2::$1}
;
param_mod:
		CONST							{BASE_CONST}
|		REGISTER						{BASE_STORAGE REGISTER}
|		VOLATILE						{BASE_VOLATILE}
;
param_qual:
		qual_type						{$1}
|		param_qual qual_type			{apply_qual $1 $2}
|		param_qual CONST				{(fst $1, BASE_CONST::(snd $1))}
|		param_qual REGISTER				{(fst $1, (BASE_STORAGE REGISTER)::(snd $1))}
|		param_qual VOLATILE				{(fst $1, BASE_VOLATILE::(snd $1))}
;
param_def:
		param_dec gcc_attributes
			{(fst $1, snd $1, $2, NOTHING)}
;
param_dec:
		/* empty */
			{("", NO_TYPE)}
|		IDENT
			{($1, NO_TYPE)}
|		NAMED_TYPE
			{($1, NO_TYPE)}
|		STAR param_dec
			{(fst $2, set_type (PTR NO_TYPE) (snd $2))}
|		STAR CONST param_dec
			{(fst $3, set_type (CONST (PTR NO_TYPE)) (snd $3))}			
|		STAR VOLATILE param_dec
			{(fst $3, set_type (VOLATILE (PTR NO_TYPE)) (snd $3))}
|		param_dec LBRACKET comma_expression RBRACKET
			{(fst $1, set_type (ARRAY (NO_TYPE, smooth_expression $3)) (snd $1))}
|		param_dec LBRACKET RBRACKET
			{(fst $1, set_type (ARRAY (NO_TYPE, NOTHING)) (snd $1))}
|		LPAREN param_dec RPAREN LPAREN parameters RPAREN
			{(fst $2, set_type (PROTO (NO_TYPE, fst $5, snd $5)) (snd $2))}
|		LPAREN param_dec RPAREN
			{$2}
;
		

/*** Only-type Definition ***/
only_type:
		only_type_type only_def
			{set_type (fst $1) $2}
;
only_type_type:
	only_mod_list_opt only_qual
		{apply_mods (snd $2) (apply_mods $1 ((fst $2), NO_STORAGE))}
|	only_mod_list_opt comp_type only_mod_list_opt
		{apply_mods $3 (apply_mods $1 ($2, NO_STORAGE))}
|		only_mod_list_opt NAMED_TYPE only_mod_list_opt
			{apply_mods $3 (apply_mods $1 (NAMED_TYPE $2, NO_STORAGE))}
;
only_mod_list_opt:
		/* empty */						{[]}
|		only_mod_list					{List.rev $1}
;
only_qual:	
		qual_type						{$1}
|		only_qual qual_type				{apply_qual $1 $2}
|		only_qual only_mod				{(fst $1, $2::(snd $1))}
;
only_mod_list:
		only_mod						{[$1]}
|		only_mod_list only_mod		{$2::$1}
;
only_mod:
		CONST							{BASE_CONST}
|		VOLATILE						{BASE_VOLATILE}
;
only_def:
		only_dec						{$1}
;
only_dec:
		/* empty */
			{NO_TYPE}
|		STAR only_dec
			{set_type (PTR NO_TYPE) $2}
|		STAR CONST only_dec
			{set_type (CONST (PTR NO_TYPE)) $3}			
|		STAR VOLATILE only_dec
			{set_type (VOLATILE (PTR NO_TYPE)) $3}
|		only_dec LBRACKET comma_expression RBRACKET
			{set_type (ARRAY (NO_TYPE, smooth_expression $3)) $1}
|		only_dec LBRACKET RBRACKET
			{set_type (ARRAY (NO_TYPE, NOTHING)) $1}
|		LPAREN only_dec RPAREN LPAREN parameters RPAREN
			{set_type (PROTO (NO_TYPE, fst $5, snd $5)) $2}
|		LPAREN only_dec RPAREN
			{$2}
;


/*** Base type ***/
qual_type:
		VOID							{(VOID, [])}
|		CHAR							{(CHAR NO_SIGN, [])}
|		INT								{(INT (NO_SIZE, NO_SIGN), [])}
|		FLOAT							{(FLOAT false, [])}
|		DOUBLE							{(DOUBLE false, [])}
|		LONG							{(NO_TYPE, [BASE_SIZE LONG])}
|		SHORT							{(NO_TYPE, [BASE_SIZE SHORT])}
|		SIGNED							{(NO_TYPE, [BASE_SIGN SIGNED])}
|		UNSIGNED						{(NO_TYPE, [BASE_SIGN UNSIGNED])}
;
comp_type:
		STRUCT type_name
			{STRUCT ($2, [])}				
|		STRUCT LBRACE field_list RBRACE
			{STRUCT ("", List.rev $3)}
|		STRUCT type_name LBRACE field_list RBRACE
			{STRUCT ($2, List.rev $4)}
|		UNION type_name
			{UNION ($2, [])}						
|		UNION LBRACE field_list RBRACE			
			{UNION ("", List.rev $3)}
|		UNION type_name LBRACE field_list RBRACE
			{UNION ($2, List.rev $4)}
|		ENUM type_name
			{ENUM ($2, [])}					
|		ENUM LBRACE enum_list RBRACE
			{ENUM ("", List.rev $3)}		
|		ENUM type_name LBRACE enum_list RBRACE
			{ENUM ($2, List.rev $4)}
;
type_name:
		IDENT							{$1}
|		NAMED_TYPE						{$1}
;
enum_list:	enum_name					{[$1]}
|			enum_list COMMA enum_name	{$3::$1}
;
enum_name:	IDENT						{($1, NOTHING)}
|			IDENT EQ expression			{($1, $3)}
;


/*** Expressions ****/
init_expression:
		LBRACE init_comma_expression RBRACE
			{CONSTANT (CONST_COMPOUND (List.rev $2))}
|		expression
			{$1}
;
init_comma_expression:
		init_expression
			{[$1]}
|		init_comma_expression COMMA init_expression
			{$3::$1}
|		init_comma_expression COMMA
			{$1}
;
opt_expression:
		/* empty */
			{NOTHING}
|		comma_expression
			{smooth_expression $1}
;
comma_expression:
		expression
			{[$1]}
|		comma_expression COMMA expression
			{$3::$1}
;
expression:
		constant
			{CONSTANT $1}		
|		IDENT
			{VARIABLE $1}
|		SIZEOF expression
			{EXPR_SIZEOF $2}
|	 	SIZEOF LPAREN only_type RPAREN
			{TYPE_SIZEOF $3}
|		PLUS expression
			{UNARY (PLUS, $2)}
|		MINUS expression
			{UNARY (MINUS, $2)}
|		STAR expression
			{UNARY (MEMOF, $2)}
|		AND expression				%prec ADDROF
			{UNARY (ADDROF, $2)}
|		EXCLAM expression
			{UNARY (NOT, $2)}
|		TILDE expression
			{UNARY (BNOT, $2)}
|		PLUS_PLUS expression %prec CAST
			{UNARY (PREINCR, $2)}
|		expression PLUS_PLUS
			{UNARY (POSINCR, $1)}
|		MINUS_MINUS expression %prec CAST
			{UNARY (PREDECR, $2)}
|		expression MINUS_MINUS
			{UNARY (POSDECR, $1)}
|		expression ARROW IDENT
			{MEMBEROFPTR ($1, $3)}
|		expression ARROW NAMED_TYPE
			{MEMBEROFPTR ($1, $3)}
|		expression DOT IDENT
			{MEMBEROF ($1, $3)}
|		expression DOT NAMED_TYPE
			{MEMBEROF ($1, $3)}
|		LPAREN body RPAREN
			{GNU_BODY $2}
|		LPAREN comma_expression RPAREN
			{(smooth_expression $2)}
|		LPAREN only_type RPAREN expression %prec CAST
			{CAST ($2, $4)}
|		expression LPAREN opt_expression RPAREN
			{CALL ($1, list_expression $3)}
|		expression LBRACKET comma_expression RBRACKET
			{INDEX ($1, smooth_expression $3)}
|		expression QUEST expression COLON expression
			{QUESTION ($1, $3, $5)}
|		expression PLUS expression
			{BINARY(ADD ,$1 , $3)}
|		expression MINUS expression
			{BINARY(SUB ,$1 , $3)}
|		expression STAR expression
			{BINARY(MUL ,$1 , $3)}
|		expression SLASH expression
			{BINARY(DIV ,$1 , $3)}
|		expression PERCENT expression
			{BINARY(MOD ,$1 , $3)}
|		expression AND_AND expression
			{BINARY(AND ,$1 , $3)}
|		expression PIPE_PIPE expression
			{BINARY(OR ,$1 , $3)}
|		expression AND expression
			{BINARY(BAND ,$1 , $3)}
|		expression PIPE expression
			{BINARY(BOR ,$1 , $3)}
|		expression CIRC expression
			{BINARY(XOR ,$1 , $3)}
|		expression EQ_EQ expression
			{BINARY(EQ ,$1 , $3)}
|		expression EXCLAM_EQ expression
			{BINARY(NE ,$1 , $3)}
|		expression INF expression
			{BINARY(LT ,$1 , $3)}	
|		expression SUP expression
			{BINARY(GT ,$1 , $3)}
|		expression INF_EQ expression
			{BINARY(LE ,$1 , $3)}
|		expression SUP_EQ expression
			{BINARY(GE ,$1 , $3)}
|		expression  INF_INF expression
			{BINARY(SHL ,$1 , $3)}
|		expression  SUP_SUP expression
			{BINARY(SHR ,$1 , $3)}		
|		expression EQ expression
			{BINARY(ASSIGN ,$1 , $3)}			
|		expression PLUS_EQ expression
			{BINARY(ADD_ASSIGN ,$1 , $3)}		
|		expression MINUS_EQ expression		
			{BINARY(SUB_ASSIGN ,$1 , $3)}
|		expression STAR_EQ expression		
			{BINARY(MUL_ASSIGN ,$1 , $3)}
|		expression SLASH_EQ expression		
			{BINARY(DIV_ASSIGN ,$1 , $3)}
|		expression PERCENT_EQ expression	
			{BINARY(MOD_ASSIGN ,$1 , $3)}
|		expression AND_EQ expression		
			{BINARY(BAND_ASSIGN ,$1 , $3)}
|		expression PIPE_EQ expression		
			{BINARY(BOR_ASSIGN ,$1 , $3)}
|		expression CIRC_EQ expression		
			{BINARY(XOR_ASSIGN ,$1 , $3)}
|		expression INF_INF_EQ expression	
			{BINARY(SHL_ASSIGN ,$1 , $3)}
|		expression SUP_SUP_EQ expression
			{BINARY(SHR_ASSIGN ,$1 , $3)}
;
constant:
		CST_INT							{CONST_INT $1}					
|		CST_FLOAT						{CONST_FLOAT $1}
|		CST_CHAR						{CONST_CHAR $1}
|		string_list						{CONST_STRING $1}
;
string_list:
		CST_STRING						{$1}
|		string_list CST_STRING			{$1 ^ $2}
;


/*** statements ***/
body_begin:
		LBRACE 							{Clexer.push_context ()}
;
body_middle:
		opt_locals opt_stats 			{($1, $2)}
;
body:
		body_begin body_middle RBRACE 	{Clexer.pop_context(); $2}
;
opt_locals:
		/* empty */						{[]}
|		locals							{List.rev $1}
;
locals:
		local							{[$1]}
|		locals local					{$2::$1}
;
opt_stats:
		/* empty */						{NOP}
|		stats							{$1}
;
stats:
    	statement						{$1}
|   	stats statement					{SEQUENCE($1, $2)}
;
statement:
		SEMICOLON
			{NOP}							
|		comma_expression SEMICOLON
			{COMPUTATION (smooth_expression $1)}			
|		body
			{BLOCK $1}					
|		IF LPAREN comma_expression RPAREN statement %prec IF
			{IF (smooth_expression $3, $5, NOP)}
|		IF LPAREN comma_expression RPAREN statement ELSE statement
			{IF (smooth_expression $3, $5, $7)}
|		SWITCH LPAREN comma_expression RPAREN statement
			{SWITCH (smooth_expression $3, $5)}
|		WHILE LPAREN comma_expression RPAREN statement
			{WHILE (smooth_expression $3, $5)}
|		DO statement WHILE LPAREN comma_expression RPAREN SEMICOLON
			{DOWHILE (smooth_expression $5, $2)}
|		FOR LPAREN opt_expression SEMICOLON opt_expression
		SEMICOLON opt_expression RPAREN statement
			{FOR ($3, $5, $7, $9)}
|		IDENT COLON statement
			{LABEL ($1, $3)}			
|		CASE expression COLON statement
			{CASE ($2, $4)}
|		DEFAULT COLON statement
			{DEFAULT $3}		
|		RETURN SEMICOLON
			{RETURN NOTHING}					
|		RETURN expression SEMICOLON
			{RETURN $2}		
|		BREAK SEMICOLON
			{BREAK}						
|		CONTINUE SEMICOLON
			{CONTINUE}				
|		GOTO IDENT SEMICOLON
			{GOTO $2}				
;


/*** GCC attributes ***/
gcc_attributes:
		/* empty */						{[]}	
|		attributes						{List.rev $1}
;

attributes:
		attribute						{[$1]}
|		attributes attribute			{$2::$1}
;

attribute:
		ATTRIBUTE LPAREN args RPAREN	{ATTR_LIST (List.rev $3)}
;
args:
		arg								{[$1]}
|		args arg						{$2::$1}
;
arg:
		IDENT							{ATTR_ID $1}
|		LPAREN args RPAREN				{ATTR_LIST (List.rev $2)}
;

%%




graydon hoare
Powered by
ViewCVS 0.9.2