java parser generator
home
features
documentation
grammars
downloads
site originally designed by ninth ave
/*
 *  C grammar based on the ISO/IEC 9899:1999 standard 
 *  Copyright (C) 2003 Roger Keays
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Author: Roger Keays 
 * Date: 12 May 2003
 * Revision: 1.0
 * 
 * Known Bugs:
 *  o Does not compile with SableCC-3.0.beta.2
 *  o Does not include any pre-processor stuff from the standard (we let the
 *    preprocessor worry about that!)
 *  o Line comments are allowed
 *
 * Change history:
 *  21 Aug 2003 : Updated to compile with SableCC-3.beta.1
 *  14 Aug 2003 : Added braces around production transforms
 *  29 May 2003 : Removed danging else problem
 */

Package org.sablecc.isoc;

/* regular expressions */
Helpers

	/* sensible stuff */
	all = [0 .. 127];
    cr = 13;
    lf = 10;
    tab = 9;
	eol = cr | lf | cr lf;
	not_eol = [all - [cr + lf]];
	not_star = [all - '*'];
	not_star_slash = [not_star - '/'];

	/* 6.4.2.1 digit, nondigit */
	digit = ['0' .. '9'];
	nondigit = ['_' + [['a' .. 'z'] + ['A' .. 'Z']]];

	/* 6.4.4.1 (various constants) */
	nonzero_digit = [digit - '0'];
	decimal_constant = nonzero_digit digit*;

	octal_digit = ['0' .. '7'];
	octal_constant = '0' octal_digit*;

	hex_prefix = '0x' | '0X';
	hex_digit = [digit + [['a' .. 'f'] + ['A' .. 'F']]];
	hex_constant = hex_prefix hex_digit*;

	unsigned_suffix = 'u' | 'U';
	long_suffix = 'l' | 'L';
	long_long_suffix = 'll' | 'LL';
	integer_suffix = 
		unsigned_suffix long_suffix? |
		unsigned_suffix long_long_suffix |
        long_suffix unsigned_suffix? |
		long_long_suffix unsigned_suffix?;

	/* 6.4.3 universal-character-name, hex-quad */
	hex_quad = hex_digit hex_digit hex_digit hex_digit;
	universal_char_name = '\u' hex_quad;

	/* 6.4.2.1 identifier-nondigit */
	identifier_nondigit = nondigit | universal_char_name;

	/* 6.4.2.2 (various constants) */
	sign = '+' | '-';
	digit_sequence = digit+;
	hex_digit_sequence = hex_digit+;
	exponent_part = ('e' | 'E') sign? digit_sequence;
	binary_exponent_part = ('p' | 'P') sign? digit_sequence;
	floating_suffix = ('f' | 'l' | 'F' | 'L');

	fractional_constant =
		digit_sequence? '.' digit_sequence |
		digit_sequence '.';

	decimal_floating_constant =
		fractional_constant exponent_part? floating_suffix? |
		digit_sequence exponent_part floating_suffix?;

	hex_fractional_constant = 
		hex_digit_sequence? '.' hex_digit_sequence |
		hex_digit_sequence '.';

	hex_floating_constant =
		hex_prefix (hex_fractional_constant | hex_digit_sequence)
			binary_exponent_part floating_suffix?;

	/* 6.4.4.1 (various constants) */
	integer_constant = 
		decimal_constant integer_suffix? |
		octal_constant integer_suffix? |
		hex_constant integer_suffix?;

	/* 6.4.4.2 (various constants) */
	floating_constant = 
		decimal_floating_constant |
		hex_floating_constant;

	/* 6.4.4.4 (various sequences) */
	simple_escape_seq = 
		'\' ''' | '\"' | '\?' | '\\' | '\a' | '\b' | '\f' | '\n' |
		'\r' | '\t' | '\v';

	octal_escape_seq = '\' octal_digit octal_digit? octal_digit?;
	hex_escape_seq = '\x' hex_digit+;

	escape_seq =
		simple_escape_seq |
		octal_escape_seq |
		hex_escape_seq |
		universal_char_name;	

	c_char = [all - [''' + ['\' + [cr + lf]]]] | escape_seq;
	c_char_seq = c_char+;
	character_constant = 'L'? ''' c_char_seq ''';

	/* 6.4.5 string sequences */
	s_char = [all - ['"' + ['\' + [cr + lf]]]] | escape_seq;
	s_char_seq = s_char+;
	
/*
 * Tokens and keywords. The ISO standard has very few tokens: just keywords,
 * identifiers, constants, string-literals and punctuators. All the other
 * lexical elements are best expressed as Helpers as they are never referenced
 * in the Productions section.
 */
Tokens
	
	/* sensible stuff */
	blank = (eol | tab | ' ')+;
	comment = 
		('//' not_eol* eol) |
		('/*' not_star* '*'+ (not_star_slash not_star* '*'+)* '/');
	
	/* 6.4 tokens */
	/* 6.4.1 keywords */
	kw_auto = 'auto';
	kw_break = 'break';
	kw_case = 'case';
	kw_char = 'char';
	kw_const = 'const';
	kw_continue = 'continue';
	kw_default = 'default';
	kw_do = 'do';
	kw_double = 'double';
	kw_else = 'else';
	kw_enum = 'enum';
	kw_extern = 'extern';
	kw_float = 'float';
	kw_for = 'for';
	kw_goto = 'goto';
	kw_if = 'if';
	kw_inline = 'inline';
	kw_int = 'int';
	kw_long = 'long';
	kw_register = 'register';
	kw_restrict = 'restrict';
	kw_return = 'return';
	kw_short = 'short';
	kw_signed = 'signed';
	kw_sizeof = 'sizeof';
	kw_static = 'static';
	kw_struct = 'struct';
	kw_switch = 'switch';
	kw_typedef = 'typedef';
	kw_union = 'union';
	kw_unsigned = 'unsigned';
	kw_void = 'void';
	kw_volatile = 'volatile';
	kw_while = 'while';
	kw_bool = '_Bool';             /* ?! hey it's in the standard! */
	kw_complex = '_Complex';       /* ?! hey it's in the standard! */ 
	kw_imaginary = '_Imaginary';   /* ?! hey it's in the standard! */

	/* 6.4.6 punctuators */
	tok_lbracket = '[';
	tok_rbracket = ']';
	tok_lpar = '(';
	tok_rpar = ')';
	tok_lbrace = '{';
	tok_rbrace = '}';
	tok_dot = '.';
	tok_arrow = '->';
	tok_plus_plus = '++';
	tok_minus_minus = '--';
	tok_amp = '&';
	tok_star = '*';
	tok_plus = '+';
	tok_minus = '-';
	tok_tilde = '~';
	tok_exclamation = '!';
	tok_slash = '/';
	tok_percent = '%';
	tok_lshift = '<<';
	tok_rshift = '>>';
	tok_lt = '<';
	tok_gt = '>';
	tok_lt_eq = '<=';
	tok_gt_eq = '>=';
	tok_eq_eq = '==';
	tok_not_eq = '!=';
	tok_caret = '^';
	tok_bar = '|';
	tok_amp_amp = '&&';
	tok_bar_bar = '||';	
	tok_question = '?';
	tok_colon = ':';
	tok_semicolon = ';';
	tok_elipsis = '...';
	tok_eq = '=';
	tok_star_eq = '*=';
	tok_slash_eq = '/=';
	tok_percent_eq = '%=';
	tok_plus_eq = '+=';
	tok_minus_eq = '-=';
	tok_lshift_eq = '<<=';
	tok_rshift_eq = '>>=';
	tok_amp_eq = '&=';
	tok_caret_eq = '^=';
	tok_bar_eq = '|=';
	tok_comma = ',';

	/* ?! hey, it's in the standard! */
	tok_hash = '#';
	tok_hash_hash = '##';
	tok_lt_colon = '<:';
	tok_colon_gt = '>:';
	tok_lt_percent = '<%';
	tok_percent_gt = '%>';
	tok_percent_colon = '%:';
	tok_percent_colon_percent_colon = '%:%:';

	/*
	 * 6.4.2.1 Identifiers 
	 * Custom lexer distinguishes between identifiers, typedef_identifier and
	 * enumeration_constants
	 */
	identifier = identifier_nondigit (digit | identifier_nondigit)*;
	typedef_identifier = identifier_nondigit (digit | identifier_nondigit)*;

	/*
	 * 6.4.4.3 enumeration-constant 
	 * These are automatically converted to integer_constants by the custom
	 * parser and lexer.
	 *
	 * enumeration_constant = ...
	 */

	/* 6.4.4 constants */
	constant =
		integer_constant |
		floating_constant |
		character_constant;


	/* 6.4.5 string-literal */
	string_literal = 'L'? '"' s_char_seq? '"';

Ignored Tokens
	comment,
	blank;

/* Concrete Syntax Tree */
Productions

	/* 6.9 translation-unit */
	translation_unit = external_declaration+ 
		{ -> New translation_unit([external_declaration]) } ;
		
	/* 6.9 external-declaration */
	external_declaration =
		{normal} declaration 
			{ -> New external_declaration.normal(declaration) } |
		{function} function_definition 
			{ -> New external_declaration.function(function_definition) } ;

	/* 6.9.1 function-definition */
	function_definition =
		declaration_specifiers declarator declaration_list? compound_statement
		{ -> New function_definition
			([declaration_specifiers.declaration_specifier],
			declarator, [declaration_list.declaration], 
			compound_statement.statement) } ;

	/* 6.9.1 declaration-list */
	declaration_list { -> declaration* } = declaration+ { -> [declaration] } ;
	
	/* 6.4.4 constant 
	constant = 
		{int} integer_constant 
			{ -> New constant.int(integer_constant) } |
		{float} floating_constant
			{ -> New constant.float(floating_constant) } |
		/* these are converted to integer_constants by the custom parser 
		{enum} enumeration_constant 
			{ -> New constant.enum(enumeration_constant) } | 
		{char} character_constant
			{ -> New constant.char(character_constant) } ;
	*/

	/* 6.5.1 primary-expression */
	primary_expression { -> expression } =
		{identifier} identifier { -> New expression.identifier(identifier) } |
		{constant} constant { -> New expression.constant(constant) } |
		{string} string_literal { -> New expression.string(string_literal) } |
		{expression} tok_lpar expression tok_rpar 
			{ -> expression.single_list } ;

	/* 6.5.2 postfix-expression */
	postfix_expression { -> expression } =
		{primary} primary_expression { -> primary_expression.expression } |
		{array} postfix_expression tok_lbracket expression tok_rbracket 
			{ -> New expression.array(postfix_expression.expression, 
				expression.single_list) } |
		{function} postfix_expression tok_lpar argument_expression_list? 
				tok_rpar 
			{ -> New expression.function(postfix_expression.expression, 
				[argument_expression_list.expression]) } |
		{struct} postfix_expression tok_dot identifier 
			{ -> New expression.struct(postfix_expression.expression,
				identifier) } |
		{lookup} postfix_expression tok_arrow identifier 
			{ -> New expression.lookup(postfix_expression.expression, 
				identifier) } |
		{increment} postfix_expression tok_plus_plus 
			{ -> New expression.increment(postfix_expression.expression) } |
		{decrement} postfix_expression tok_minus_minus 
			{ -> New expression.decrement(postfix_expression.expression) } |
		{initialize1} tok_lpar type_name tok_rpar tok_lbrace initializer_list
				tok_rbrace { -> New expression.initialize(type_name,
				[initializer_list.initializer]) } |
		{initialize2} tok_lpar type_name tok_rpar tok_lbrace initializer_list
				tok_comma tok_rbrace { -> New expression.initialize(type_name,
				[initializer_list.initializer]) } ;
	
	/* 6.5.2 argument-expression-list */
	argument_expression_list { -> expression* } =
		{single} assignment_expression 
			{ -> [assignment_expression.expression] } |
		{list} argument_expression_list tok_comma assignment_expression 
			{ -> [argument_expression_list.expression
				assignment_expression.expression] } ;

	/* 6.5.3 unary-expression */
	unary_expression { -> expression } = 
		{postfix} postfix_expression { -> postfix_expression.expression } |
		{increment} tok_plus_plus unary_expression 
			{ -> New expression.increment(unary_expression.expression) } |
		{decrement} tok_minus_minus unary_expression 
			{ -> New expression.decrement(unary_expression.expression) } |
		{unary} unary_operator cast_expression 
			{ -> New expression.unary(unary_operator,
				cast_expression.expression) } |
		{sizeof} kw_sizeof unary_expression 
			{ -> New expression.sizeof(unary_expression.expression) } |
		{sizeof_type} kw_sizeof tok_lpar type_name tok_rpar
			{ -> New expression.sizeof_type(type_name) } ;

	/* 6.5.3 unary-operator */
	unary_operator =
		{address} tok_amp { -> New unary_operator.address() } |
		{dereference} tok_star { -> New unary_operator.dereference() } |
		{positive} tok_plus { -> New unary_operator.positive() } |
		{negative} tok_minus { -> New unary_operator.negative() } |
		{inverse} tok_tilde { -> New unary_operator.inverse() } |
		{not} tok_exclamation { -> New unary_operator.not() } ;


	/* 6.5.4 cast-expression */
	cast_expression { -> expression } =
		{no} unary_expression { -> unary_expression.expression } |
		{cast} tok_lpar type_name tok_rpar cast_expression
			{ -> New expression.cast(type_name,
				cast_expression.expression) } ;

	/* 6.5.5 multiplicative-expression */
	multiplicative_expression { -> expression } = 
		{no} cast_expression { -> cast_expression.expression } |
		{mult} multiplicative_expression tok_star cast_expression 
			{ -> New expression.multiply(multiplicative_expression.expression,
				cast_expression.expression) } |
		{divide} multiplicative_expression tok_slash cast_expression 
			{ -> New expression.divide(multiplicative_expression.expression, 
				cast_expression.expression) } |
		{mod} multiplicative_expression tok_percent cast_expression
			{ -> New expression.mod(multiplicative_expression.expression,
				cast_expression.expression) } ;

	/* 6.5.6 additive-expression */
	additive_expression { -> expression } =
		{no} multiplicative_expression 
			{ -> multiplicative_expression.expression } |
		{plus} additive_expression tok_plus multiplicative_expression 
			{ -> New expression.plus(additive_expression.expression,
				multiplicative_expression.expression) } |
		{minus} additive_expression tok_minus multiplicative_expression
			{ -> New expression.minus(additive_expression.expression,
				multiplicative_expression.expression) } ;

	/* 6.5.7 shift-expression */
	shift_expression { -> expression } =
		{no} additive_expression { -> additive_expression.expression } |
		{lshift} shift_expression tok_lshift additive_expression 
			{ -> New expression.lshift(shift_expression.expression,
				additive_expression.expression) } |
		{rshift} shift_expression tok_rshift additive_expression
			{ -> New expression.rshift(shift_expression.expression,
				additive_expression.expression) } ;
 
	/* 6.5.8 relational-expression */
	relational_expression { -> expression } =
		{no} shift_expression { -> shift_expression.expression } |
		{lt} relational_expression tok_lt shift_expression 
			{ -> New expression.lt(relational_expression.expression,
				shift_expression.expression) } |
		{gt} relational_expression tok_gt shift_expression 
			{ -> New expression.gt(relational_expression.expression,
				shift_expression.expression) } |
		{lt_eq} relational_expression tok_lt_eq shift_expression 
			{ -> New expression.lt_eq(relational_expression.expression,
				shift_expression.expression) } |
		{gt_eq} relational_expression tok_gt_eq shift_expression
			{ -> New expression.gt_eq(relational_expression.expression,
				shift_expression.expression) } ;

	/* 6.5.9 equality-expression */
	equality_expression { -> expression } =
		{no} relational_expression { -> relational_expression.expression } |
		{eq_eq} equality_expression tok_eq_eq relational_expression 
			{ -> New expression.eq_eq(equality_expression.expression,
				relational_expression.expression) } |
		{not_eq} equality_expression tok_not_eq relational_expression
			{ -> New expression.not_eq(equality_expression.expression,
				relational_expression.expression) } ;

	/* 6.5.10 AND-expression */
	and_expression { -> expression } = 
		{no} equality_expression { -> equality_expression.expression } |
		{and} and_expression tok_amp equality_expression
			{ -> New expression.bitwise_and(and_expression.expression,
				equality_expression.expression) } ;

	/* 6.5.11 exclusive-OR-expression */
	exclusive_or_expression { -> expression } = 
		{no} and_expression { -> and_expression.expression } |
		{xor} exclusive_or_expression tok_caret and_expression
			{ -> New expression.bitwise_xor(exclusive_or_expression.expression,
				and_expression.expression) } ;

	/* 6.5.12 inclusive-OR-expression */
	inclusive_or_expression { -> expression } =
		{no} exclusive_or_expression { -> exclusive_or_expression.expression } |
		{or} inclusive_or_expression tok_bar exclusive_or_expression
			{ -> New expression.bitwise_or(inclusive_or_expression.expression,
				exclusive_or_expression.expression) } ;

	/* 6.5.13 logical-AND-expression */
	logical_and_expression { -> expression } =
		{no} inclusive_or_expression { -> inclusive_or_expression.expression } |
		{and} logical_and_expression tok_amp_amp inclusive_or_expression
			{ -> New expression.logical_and(logical_and_expression.expression,
				inclusive_or_expression.expression) } ;

	/* 6.5.14 logical-OR-expression */
	logical_or_expression { -> expression } =
		{no} logical_and_expression { -> logical_and_expression.expression } |
		{or} logical_or_expression tok_bar_bar logical_and_expression
			{ -> New expression.logical_or(logical_or_expression.expression,
				logical_and_expression.expression) } ;

	/* 6.5.15 conditional-expression */
	conditional_expression { -> expression } =
		{no} logical_or_expression { -> logical_or_expression.expression } |
		{cond} logical_or_expression tok_question expression tok_colon
				conditional_expression 
				{ -> New expression.conditional
					(logical_or_expression.expression,
					expression.single_list, 
					conditional_expression.expression) } ;

	/* 6.5.16 assignment-expression */
	assignment_expression { -> expression } =
		{no} conditional_expression { -> conditional_expression.expression } |
		{assign} unary_expression assignment_operator assignment_expression
			{ -> New expression.assignment(unary_expression.expression,
				assignment_operator, assignment_expression.expression) } ;

	/* 6.5.16 assignment-operator */
	assignment_operator =
		{eq} tok_eq { -> New assignment_operator.eq() } |
		{multiply_eq} tok_star_eq { -> New assignment_operator.multiply_eq() } |
		{divide_eq} tok_slash_eq { -> New assignment_operator.divide_eq() } |
		{mod_eq} tok_percent_eq { -> New assignment_operator.mod_eq() } |
		{plus_eq} tok_plus_eq { -> New assignment_operator.plus_eq() } |
		{minus_eq} tok_minus_eq { -> New assignment_operator.minus_eq() } |
		{lshift_eq} tok_lshift_eq { -> New assignment_operator.lshift_eq() } |
		{rshift_eq} tok_rshift_eq { -> New assignment_operator.rshift_eq() } |
		{and_eq} tok_amp_eq { -> New assignment_operator.and_eq() } |
		{xor_eq} tok_caret_eq { -> New assignment_operator.xor_eq() } |
		{or_eq} tok_bar_eq { -> New assignment_operator.or_eq() } ;
	
	/* 6.5.17 expression 
	 *
	 * this node is transformed into a list of expressions and also a single
 	 * expression of type list, so either can be used for convenience
	 */
	expression { -> [long_list]:expression* [single_list]:expression } =
		{no} assignment_expression 
			{ -> [assignment_expression.expression] 
			New expression.list([assignment_expression.expression]) } |
		{list} expression tok_comma assignment_expression
			{ -> [expression.long_list assignment_expression.expression] 
			New expression.list
			([assignment_expression.expression expression.long_list]) } ;

	/* 6.6 constant-expression */
	constant_expression { -> expression } = conditional_expression 
		{ -> conditional_expression.expression } ;

	/* 6.7 declaration */
	declaration = declaration_specifiers init_declarator_list? tok_semicolon 
		{ -> New declaration([declaration_specifiers.declaration_specifier],
			[init_declarator_list.init_declarator]) } ;

	/* 6.7 declaration-specifiers */
	declaration_specifiers { -> declaration_specifier* } =
		{storage} storage_class_specifier declaration_specifiers? 
			{ -> [New declaration_specifier.storage(storage_class_specifier)
				declaration_specifiers.declaration_specifier] } |
		{type_specifier} type_specifier declaration_specifiers? 
			{ -> [New declaration_specifier.type_specifier(type_specifier)
				declaration_specifiers.declaration_specifier] } |
		{type_qualifier} type_qualifier declaration_specifiers? 
			{ -> [New declaration_specifier.type_qualifier(type_qualifier)
				declaration_specifiers.declaration_specifier] } |
		{function} function_specifier declaration_specifiers? 
			{ -> [New declaration_specifier.function()
				declaration_specifiers.declaration_specifier] } ;

	/* 6.7 init-declarator-list */
	init_declarator_list { -> init_declarator* } =
		{single} init_declarator { -> [init_declarator] } |
		{list} init_declarator_list tok_comma init_declarator 
			{ -> [init_declarator_list.init_declarator init_declarator] } ;

	/* 6.7 init-declarator */
	init_declarator =
		{plain} declarator { -> New init_declarator(declarator, Null) } |
		{assign} declarator tok_eq initializer 
			{ -> New init_declarator(declarator, initializer) } ;

	/* 6.7.1 storage-class-specifier */
	storage_class_specifier =
		{typedef} kw_typedef { -> New storage_class_specifier.typedef() } |
		{extern} kw_extern { -> New storage_class_specifier.extern() } |
		{static} kw_static { -> New storage_class_specifier.static() } |
		{auto} kw_auto { -> New storage_class_specifier.auto() } |
		{register} kw_register { -> New storage_class_specifier.register() } ;

	/* 6.7.2 type-specifier */
	type_specifier =
		{void} kw_void { -> New type_specifier.void() } |
		{char} kw_char { -> New type_specifier.char() } |
		{short} kw_short { -> New type_specifier.short() } |
		{int} kw_int { -> New type_specifier.int() } |
		{long} kw_long { -> New type_specifier.long() } |
		{float} kw_float { -> New type_specifier.float() } |
		{double} kw_double { -> New type_specifier.double() } |
		{signed} kw_signed { -> New type_specifier.signed() } |
		{unsigned} kw_unsigned { -> New type_specifier.unsigned() } |
		{bool} kw_bool { -> New type_specifier.bool() } |
		{complex} kw_complex { -> New type_specifier.complex() } |
		{imaginary} kw_imaginary { -> New type_specifier.imaginary() } |
		{struct_or_union} struct_or_union_specifier 
			{ -> struct_or_union_specifier.type_specifier } |
		{enum} enum_specifier { -> enum_specifier.type_specifier } |
		{typedef} typedef_name { -> typedef_name.type_specifier } ;

	/* 6.7.2.1 struct-or-union-specifier */
	struct_or_union_specifier { -> type_specifier } =
		{struct1} kw_struct identifier? tok_lbrace struct_declaration_list
				 tok_rbrace 
				{ -> New type_specifier.struct(identifier,
					[struct_declaration_list.declaration]) } |
		{struct2} kw_struct identifier
				{ -> New type_specifier.struct(identifier, []) } |
		{union1} kw_union identifier? tok_lbrace struct_declaration_list
				tok_rbrace 
				{ -> New type_specifier.union(identifier,
					[struct_declaration_list.declaration]) } |
		{union2} kw_union identifier
				{ -> New type_specifier.union(identifier, []) } ;

	/*
	 * 6.7.2.1 struct-or-union  (not used in this grammar. I have instead made
 	 * separate alternatives for structs and unions above)
	 *
	 * struct_or_union =
	 *	{struct} kw_struct } |
	 *	{union} kw_union } ;
 	 */

	/* 6.7.2.1 struct-declaration-list */
	struct_declaration_list { -> declaration* } = struct_declaration+ 
		{ -> [struct_declaration.declaration] } ;

	/* 6.7.2.1 struct-declaration */
	struct_declaration { -> declaration } = 
		specifier_qualifier_list struct_declarator_list tok_semicolon
			{ ->  New declaration
				([specifier_qualifier_list.declaration_specifier],
				[struct_declarator_list.init_declarator]) } ;
		
	/* 6.7.2.1 specifier-qualifier-list */
	specifier_qualifier_list { -> declaration_specifier* } =
		{spec_first} type_specifier specifier_qualifier_list? 
			{ -> [New declaration_specifier.type_specifier(type_specifier)
				specifier_qualifier_list.declaration_specifier] } |
		{qual_first} type_qualifier specifier_qualifier_list? 
			{ -> [New declaration_specifier.type_qualifier(type_qualifier)
				specifier_qualifier_list.declaration_specifier] } ;

	/* 6.7.2.1 struct-declarator-list */
	struct_declarator_list { -> init_declarator* } =
		{single} struct_declarator { -> [struct_declarator.init_declarator] } |
		{list} struct_declarator_list tok_comma struct_declarator 
			{ -> [struct_declarator_list.init_declarator
				struct_declarator.init_declarator] } ;

	/* 6.7.2.1 struct-declarator */
	struct_declarator { -> init_declarator } =
		{plain} declarator { -> New init_declarator(declarator, Null) } |
		{with_const} declarator? tok_colon constant_expression
			{ -> New init_declarator(declarator, New
				initializer.expression(constant_expression.expression)) } ;

	/* 6.7.2.2 enum-specifier */
	enum_specifier { -> type_specifier } =
		{values1} kw_enum identifier? tok_lbrace enumerator_list tok_rbrace 
			{ -> New type_specifier.enum(identifier, 
				[enumerator_list.enumerator]) } |
		{values2} kw_enum identifier? tok_lbrace enumerator_list tok_comma 
				tok_rbrace 
			{ -> New type_specifier.enum(identifier, 
				[enumerator_list.enumerator]) } |
		{novalues} kw_enum identifier
			{ -> New type_specifier.enum(identifier, []) } ;

	/* 6.7.2.2 enumerator-list */
	enumerator_list { -> enumerator* } =
		{single} enumerator { -> [enumerator] } |
		{list} enumerator_list tok_comma enumerator 
			{ -> [enumerator_list.enumerator enumerator] } ;

	/* 6.7.2.2 enumerator */
	enumerator =
		{plain} identifier 
			{ -> New enumerator(identifier, Null) } |
		{assign} identifier tok_eq constant_expression
			{ -> New enumerator(identifier, 
				constant_expression.expression) } ;

	/* 6.7.3 type-qualifier */
	type_qualifier =
		{const} kw_const { -> New type_qualifier.const() } |
		{restrict} kw_restrict { -> New type_qualifier.restrict() } |
		{volatile} kw_volatile { -> New type_qualifier.volatile() } ;

	/* 6.7.4 function-specifier */
	function_specifier { -> declaration_specifier } = kw_inline
		{ -> New declaration_specifier.function() } ;

	/* 6.7.5 declarator */
	declarator = pointer? direct_declarator
		{ -> New declarator([pointer.pointer],
			direct_declarator.direct_declarator) } ;

	/* 6.7.5 direct-declarator */
	direct_declarator =
		{ident} identifier 
			{ -> New direct_declarator.identifier(identifier) } |
		{nested} tok_lpar declarator tok_rpar 
			{ -> New direct_declarator.nested(declarator) } |
		{array1} direct_declarator tok_lbracket type_qualifier_list?	
				assignment_expression? tok_rbracket 
			{ -> New direct_declarator.array(direct_declarator,
				[type_qualifier_list.type_qualifier],
				assignment_expression.expression, Null, Null) } |
		{array2} direct_declarator tok_lbracket kw_static type_qualifier_list?	
				assignment_expression tok_rbracket 
			{ -> New direct_declarator.array(direct_declarator,
				[type_qualifier_list.type_qualifier],
				assignment_expression.expression, kw_static, Null) } |
		{array3} direct_declarator tok_lbracket type_qualifier_list kw_static
				assignment_expression tok_rbracket 
			{ -> New direct_declarator.array(direct_declarator,
				[type_qualifier_list.type_qualifier],
				assignment_expression.expression, kw_static, Null) } |
		{array4} direct_declarator tok_lbracket type_qualifier_list? tok_star
				tok_rbracket 
			{ -> New direct_declarator.array(direct_declarator,
				[type_qualifier_list.type_qualifier],
				Null, Null, tok_star) } |
		{parameters1} direct_declarator tok_lpar parameter_type_list tok_rpar 
			{ -> New direct_declarator.declared_parameters(direct_declarator,
				[parameter_type_list.declaration]) } |
		{parameters2} direct_declarator tok_lpar identifier_list? tok_rpar
			{ -> New direct_declarator.identified_parameters(direct_declarator,
				[identifier_list.identifier]) } ;

	/* 6.7.5 pointer */
	pointer { -> pointer* } =
		{single} tok_star type_qualifier_list? 
			{ -> [New pointer([type_qualifier_list.type_qualifier])] } |
		{recursive} tok_star type_qualifier_list? pointer
			{ -> [New pointer([type_qualifier_list.type_qualifier]) 
				pointer.pointer] } ;

	/* 6.7.5 type-qualifier-list */
	type_qualifier_list { -> type_qualifier* } = 
		type_qualifier+ { -> [type_qualifier] } ;

	/* 6.7.5 parameter-type-list */
	parameter_type_list { -> declaration* } =
		{plain} parameter_list { -> [parameter_list.declaration] } |
		{elipsis} parameter_list tok_comma tok_elipsis
			{ -> [parameter_list.declaration New declaration.elipsis()] } ;

	/* 6.7.5 parameter-list */
	parameter_list { -> declaration* } = 
		{single} parameter_declaration 
			{ -> [parameter_declaration.declaration] } |
		{list} parameter_list tok_comma parameter_declaration
			{ -> [parameter_list.declaration 
				parameter_declaration.declaration] } ;

	/* 6.7.5 parameter-declaration */
	parameter_declaration { -> declaration } =
		{plain} declaration_specifiers declarator 
			{ -> New declaration([declaration_specifiers.declaration_specifier],
				[New init_declarator(declarator, Null)]) } |
		{abstract} declaration_specifiers abstract_declarator?
			{ -> New declaration([declaration_specifiers.declaration_specifier],
				[New init_declarator(abstract_declarator.declarator, Null)]) } ;

	/* 6.7.5 identifier-list */
	identifier_list { -> identifier* } =
		{single} identifier { -> [identifier] } |
		{list} identifier_list tok_comma identifier
			{ -> [identifier_list.identifier identifier] } ;

	/* 6.7.6 type-name */
	type_name = specifier_qualifier_list abstract_declarator?
		{ -> New type_name([specifier_qualifier_list.declaration_specifier],
			abstract_declarator.declarator) } ;
		
	/* 6.7.6 abstract-declarator */
	abstract_declarator { -> declarator } =
		{pointer} pointer { -> New declarator([pointer.pointer], Null) } |
		{direct} pointer? direct_abstract_declarator
			{ -> New declarator([pointer.pointer],
				direct_abstract_declarator.direct_declarator) } ;

	/* 6.7.6 direct-abstract-declarator */
	direct_abstract_declarator { -> direct_declarator } =
		{par} tok_lpar abstract_declarator tok_rpar 
			{ -> New direct_declarator.abstract_nested
				(abstract_declarator.declarator) } |
		{array1} direct_abstract_declarator? tok_lbracket
				assignment_expression? tok_rbracket 
			{ -> New direct_declarator.abstract_array
				(direct_abstract_declarator.direct_declarator,
				assignment_expression.expression, Null) } |
		{array2} direct_abstract_declarator? tok_lbracket tok_star
				tok_rbracket 
			{ -> New direct_declarator.abstract_array
				(direct_abstract_declarator.direct_declarator,
				Null, tok_star) } |
		{parameters} direct_abstract_declarator? tok_lpar parameter_type_list?
				tok_rpar
			{ -> New direct_declarator.abstract_parameters
				(direct_abstract_declarator.direct_declarator,
				parameter_type_list.declaration) } ;

	/* 6.7.7 typedef-name */
	typedef_name { -> type_specifier } = typedef_identifier 
		{ -> New type_specifier.typedef(typedef_identifier) } ;

	/* 6.7.8 initializer */
	initializer { -> initializer } =
		{expression} assignment_expression 
			{ -> New initializer.expression
				(assignment_expression.expression) } |
		{block1} tok_lbrace initializer_list tok_rbrace 
			{ -> New initializer.block([initializer_list.initializer]) } |
		{block2} tok_lbrace initializer_list tok_comma tok_rbrace
			{ -> New initializer.block([initializer_list.initializer]) } ;

	/* 6.7.8 initializer-list */
	initializer_list { -> initializer* } =
		{single} designation? initializer 
			{ -> [New initializer.part([designation.designator],
				initializer.initializer)] } |
		{list} initializer_list tok_comma designation? initializer
			{ -> [initializer_list.initializer
				New initializer.part([designation.designator],
				initializer.initializer)] } ;

	/* 6.7.8 designation */
	designation { -> designator* } = designator_list tok_eq
		{ -> [designator_list.designator] } ;

	/* 6.7.8 designator-list */
	designator_list { -> designator* } = designator+ { -> [designator] } ;

	/* 6.7.8 designator */
	designator =
		{brackets} tok_lbracket constant_expression tok_rbracket 
			{ -> New designator.array(constant_expression.expression) } |
		{dot} tok_dot identifier
			{ -> New designator.struct(identifier) } ;
	/*
	 * 6.8 statement 
	 * non-standard... this is separated into two to remove the dangling else
 	 * problem 
	 */
	statement =
		{no_dangling} no_dangling_statement 
			{ -> no_dangling_statement.statement } |
		{dangling} dangling_statement 
			{ -> dangling_statement.statement } ;

	/* productions NOT ending in 'statement' */
	no_dangling_statement { -> statement } =
		{comp} compound_statement { -> compound_statement.statement } |
		{exp} expression_statement { -> expression_statement.statement } |
		{jmp} jump_statement { -> jump_statement.statement } |
		{ifelse} kw_if tok_lpar expression tok_rpar no_dangling_statement 
			kw_else [other]:no_dangling_statement 
			{ -> New statement.ifelse(expression.single_list, 
				no_dangling_statement.statement, other.statement) } ;
 
	/* productions ending in 'statement' */
	dangling_statement { -> statement } =
		{label} labeled_statement { -> labeled_statement.statement } |
		{select} selection_statement { -> selection_statement.statement } |
		{iter} iteration_statement { -> iteration_statement.statement } ;

	/* 6.8.1 labeled-statement */
	labeled_statement { -> statement } = 
		{plain} identifier tok_colon statement 
			{ -> New statement.labeled(identifier, statement) } |
		{case} kw_case constant_expression tok_colon statement 
			{ -> New statement.case(constant_expression.expression, 
				statement) } |
		{default} kw_default tok_colon statement 
			{ -> New statement.default(statement) } ;
		
	/* 6.8.2 compound-statement */
	compound_statement { -> statement } = tok_lbrace block_item_list? tok_rbrace
		{ -> New statement.compound([block_item_list.statement]) } ;

	/* 6.8.2 block-item-list */
	block_item_list { -> statement* } = block_item+ 
		{ -> [block_item.statement] } ;

	/* 6.8.2 block-item */
	block_item { -> statement } =
		{decl} declaration { -> New statement.declaration(declaration) } |
		{statement} statement { -> statement } ;

	/* 6.8.3 expression-statement */
	expression_statement { -> statement } = expression? tok_semicolon
		{ -> New statement.expression([expression.long_list]) } ;

	/* 6.8.4 selection-statment */
	selection_statement { -> statement } =
		{if} kw_if tok_lpar expression tok_rpar statement 
			{ -> New statement.if(expression.single_list, statement) } |
		{ifelse} kw_if tok_lpar expression tok_rpar no_dangling_statement 
			kw_else [other]:dangling_statement 
			{ -> New statement.ifelse(expression.single_list,
				no_dangling_statement.statement, other.statement) } |
		{switch} kw_switch tok_lpar expression tok_rpar statement
			{ -> New statement.switch(expression.single_list, statement) } ;
		
	/* 6.8.5 iteration-statement */
	iteration_statement { -> statement } =
		{while} kw_while tok_lpar expression tok_rpar statement 
			{ -> New statement.while(expression.single_list, statement) } |
		{do} kw_do statement kw_while tok_lpar expression tok_rpar 
			tok_semicolon 
			{ -> New statement.do(statement, expression.single_list) } |
		{for} kw_for tok_lpar [declaration]:expression? [a]:tok_semicolon 
			[condition]:expression?  [b]:tok_semicolon [iteration]:expression? 
			tok_rpar statement 
			{ -> New statement.for(declaration.single_list, 
				condition.single_list, iteration.single_list, statement) } |
		{for_decl} kw_for tok_lpar declaration [condition]:expression? 
			tok_semicolon [iteration]:expression? tok_rpar statement 
			{ -> New statement.for_decl(declaration, condition.single_list,
				iteration.single_list, statement) } ;

	/* 6.8.6 jump-statement */
	jump_statement { -> statement } =
		{goto} kw_goto identifier tok_semicolon 
			{ -> New statement.goto(identifier) } |
		{continue} kw_continue tok_semicolon 
			{ -> New statement.continue() } |
		{break} kw_break tok_semicolon 
			{ -> New statement.break() } |
		{return} kw_return expression? tok_semicolon
			{ -> New statement.return(expression.single_list) } ;

/* Abstract Syntax Tree */
Abstract Syntax Tree 

	translation_unit = external_declaration* ;

	external_declaration = 
		{normal} declaration |
		{function} function_definition ;

	/*
	 * declaration_specifier is void/char/static... etc, but does not have
 	 * pointer or array information. That is in the declarator.
	 */
	function_definition = declaration_specifier* declarator 
		[param_definitions]:declaration* statement ;

	/*
	 * it is possible to have multiple init-declarators. e.g. in 
	 * statements like int x = 3, y = 5; 
	 * 
	 * the elipsis alternative is a special case used to represent the ...
	 * parameter.
	 */
	declaration = 
		declaration_specifier* init_declarator* |
		{elipsis} ;
	/*
	 * an init_declarator is usually just name/expression, but may also have
	 * pointer/array information (in the declarator) and complex initializer
	 * (e.g. values in an array or struct).
	 */
	init_declarator = declarator initializer ;
	
	/*
	 * a declaration_specifier describes the type (except pointer/array
	 * information.
	 */
	declaration_specifier = 
		{storage} storage_class_specifier |
		{type_specifier} type_specifier |
		{type_qualifier} type_qualifier |
		{function} ; /* (inline) */

	/* this is the same as the CST */
	storage_class_specifier = {typedef} | {extern} | {static} | {auto} |
		{register} ;

	/* same as CST, except unions and struct are given separate nodes */
	type_specifier = {void} | {char} | {short} | {int} | {long} |
		{float} | {double} | {signed} | {unsigned} | {bool} | {complex} |
		{imaginary} |
		{struct} [name]:identifier [members]:declaration* | 
		{union} [name]:identifier [members]:declaration* | 
		{enum} [name]:identifier enumerator* |
		{typedef} typedef_identifier ; 

	enumerator = identifier expression ;

	/* same as CST */
	type_qualifier = {const} | {restrict} | {volatile} ;

	/*
	 * a declarator may be a pointer and a pointer to a pointer etc... hence the
	 * [pointer] list. Likewise, a list is used for array declarators (enabling
	 * multidimension arrays).  The ISO grammar (6.7.5) allows a declarator to
	 * be a child of a direct_declarator... presumably this is for stuff like
	 * pointers to functions. This is why you see 'declarator*' here.
	 */
	declarator = pointer* direct_declarator ;

	direct_declarator =
		{identifier} identifier |
		{nested} declarator |
		{abstract_nested} declarator |
		{array} direct_declarator type_qualifier* expression kw_static 
			tok_star |
		{abstract_array} direct_declarator expression tok_star |
		{declared_parameters} direct_declarator [parameters]:declaration* |
		{identified_parameters} direct_declarator [parameters]:identifier* |
		{abstract_parameters} direct_declarator [parameters]:declaration* ;

	pointer = type_qualifier* ;

	/* type_name is used for casts */
	type_name = declaration_specifier* declarator ;

	/*
	 * initializer can be a simple expression, or if used to initialize an
	 * array, struct or union a designator may be required. Initializers may
	 * also be nested inside other initializers in the case of defining
	 * multi-demensional arrays / structs / unions.
	 */
	initializer = 
		{part} designator* initializer |
		{expression} [value]:expression |
		{block} [values]:initializer* ;

	/* two designations: one for arrays and another for structs/unions */
	designator = 
		{array} [index]:expression |
		{struct} [member]:identifier ;

	statement =
		{declaration} declaration |
		{expression} expression* |
		{labeled} identifier statement |
		{compound} statement* |

		/* if blocks */
		{if} [condition]:expression statement |
		{ifelse} [condition]:expression statement [else]:statement |

		/* for switch blocks */
		{switch} [condition]:expression statement |
		{case} [case]:expression statement |
		{default} statement |
		
		/* iteration blocks */
		{while} [condition]:expression statement |
		{do} statement [condition]:expression |
		{for} [declaration]:expression [condition]:expression
			 [iteration]:expression statement |
		{for_decl} declaration [condition]:expression
			 [iteration]:expression statement |

		/* control statements */
		{goto} [destination]:identifier |
		{continue} |
		{break} |
		{return} expression ;

	/* 
	 * expression nodes: all the precedence is done by the CST! The choice here
	 * was whether to have few nodes and use an 'operator' element, or
	 * distinguish between operators by using a separate node type for each
	 * operation. I have gone for (mostly) the latter except for assignment and
	 * unary expressions.
	 */
	expression = 
		{list} expression* |
		{assignment} [lhs]:expression assignment_operator [rhs]:expression |
		{conditional} [condition]:expression [true]:expression 
			[false]:expression |
		{logical_or} [lhs]:expression [rhs]:expression |
		{logical_and} [lhs]:expression [rhs]:expression |
		{bitwise_or} [lhs]:expression [rhs]:expression |
		{bitwise_and} [lhs]:expression [rhs]:expression |
		{bitwise_xor} [lhs]:expression [rhs]:expression |
		{not_eq} [lhs]:expression [rhs]:expression |
		{eq_eq} [lhs]:expression [rhs]:expression |
		{lt} [lhs]:expression [rhs]:expression |
		{gt} [lhs]:expression [rhs]:expression |
		{lt_eq} [lhs]:expression [rhs]:expression |
		{gt_eq} [lhs]:expression [rhs]:expression |
		{rshift} [lhs]:expression [rhs]:expression |
		{lshift} [lhs]:expression [rhs]:expression |
		{minus} [lhs]:expression [rhs]:expression |
		{plus} [lhs]:expression [rhs]:expression |
		{mod} [lhs]:expression [rhs]:expression |
		{divide} [lhs]:expression [rhs]:expression |
		{multiply} [lhs]:expression [rhs]:expression |
		{cast} type_name expression |
		{sizeof} expression |
		{sizeof_type} type_name |
		{unary} unary_operator expression |
		{array} [array]:expression [index]:expression | /* for referencing arrays */
		{function} [function]:expression [parameters]: expression* | /* for calling functions */
		{struct} [member]:expression identifier | /* for referencing struct/union members */
		{lookup} [member]:expression identifier | /* for dereferencing struct/union members */
		{increment} expression | /* pre or post (CST handles order) */
		{decrement} expression | /* pre or post (CST handles order) */
		{initialize} type_name initializer* | /* ??.. see 6.5.2 */
		{identifier} identifier |
		{constant} constant |
		{string} string_literal ;

	unary_operator = {address} | {dereference} | {positive} | {negative} |
		{inverse} | {not} ;

	assignment_operator = {eq} | {multiply_eq} | {divide_eq} | {mod_eq} |
		{plus_eq} | {minus_eq} | {lshift_eq} | {rshift_eq} | {and_eq} |
		{xor_eq} | {or_eq} ;

This site has been last updated by the web master on 2007/6/24.