/*
 * Bernoulli Compiler
 * Copyright (c) Cornell University
 * Department of Computer Science
 * 
 * Kamen Yotov (kamen@yotov.org)
 * 
 * $Source: C:/CVS/kyotov/kyotov/Research/BC/C/CGrammar.cs,v $
 * $Revision: 1.16 $
 * $Date: 2002/12/12 05:22:49 $
 */

using System;

using BC.Core.Grammars;
using BC.Core.Grammars.Symbols;
using BC.Core.Grammars.Reductions;

namespace BC.C
{
	[Serializable]
	sealed class CGrammar: Grammar
	{
		Symbols s = new Symbols();

		public CGrammar (CParser p)
		{
			S = C.N_start;

			NonTerminal N_brace_scope_open = new NonTerminal("_brace_scope_open");
			NonTerminal N_brace_scope_close = new NonTerminal("_brace_scope_close");

			this[N_brace_scope_open]
				= C.T_leftbrace + new Reduction(p._scope_open);

			this[N_brace_scope_close]
				= C.T_rightbrace + new Reduction(p._scope_close);

			NonTerminal N_parenthesis_scope_open = new NonTerminal("_parenthesis_scope_open");
			NonTerminal N_parenthesis_scope_close = new NonTerminal("_parenthesis_scope_close");

			this[N_parenthesis_scope_open]
				= C.T_leftparenthesis + new Reduction(p._scope_open);

			this[N_parenthesis_scope_close]
				= C.T_rightparenthesis + new Reduction(p._scope_close);

			// A.2. Phrase Structure
			// A.2.1. Expressions

			this[C.N_primary_expression]
				= C.T_identifier + new Reduction(p._primary_expression_0)
				| C.T_constant + new Reduction(CParser._primary_expression_1)
				| C.T_leftparenthesis + C.N_expression + C.T_rightparenthesis + X(Common.RShortCut, 1);

			this[C.N_postfix_expression]
				= C.N_primary_expression + Common.RShortCut
				| C.N_postfix_expression + C.T_leftbracket + C.N_expression + C.T_rightbracket + new Reduction(CParser._postfix_expression_1)

				| C.N_postfix_expression + C.T_leftparenthesis + O(C.N_argument_expression_list) + C.T_rightparenthesis + new Reduction(CParser._postfix_expression_2)

				| C.N_postfix_expression + C.T_dot + C.T_identifier + new Reduction(CParser._postfix_expression_3)
				| C.N_postfix_expression + C.T_reference + C.T_identifier + new Reduction(CParser._postfix_expression_4)
				| C.N_postfix_expression + C.T_increment + new Reduction(CParser._postfix_expression)
				| C.N_postfix_expression + C.T_decrement + new Reduction(CParser._postfix_expression)
				| C.T_leftparenthesis + C.N_type_name + C.T_rightparenthesis + C.T_leftbrace + C.N_initializer_list + O(C.T_coma) + C.T_rightbrace + new Reduction(CParser._postfix_expression_7);

			this[C.N_argument_expression_list]
				= C.N_assignment_expression + Common.RCreateList
				| C.N_argument_expression_list + C.T_coma + C.N_assignment_expression + X(Common.RAddToList, 0, 2);

			this[C.N_unary_expression]
				= C.N_postfix_expression + Common.RShortCut
				| C.T_increment + C.N_unary_expression + new Reduction(CParser._unary_expression)
				| C.T_decrement + C.N_unary_expression + new Reduction(CParser._unary_expression)
				| C.N_unary_operator + C.N_cast_expression + new Reduction(CParser._unary_expression)
				| C.T_keyword_sizeof + C.N_unary_expression + new Reduction(CParser._sizeof_expression_0)
				| C.T_keyword_sizeof + C.T_leftparenthesis + C.N_type_name + C.T_rightparenthesis + new Reduction(CParser._sizeof_expression_1);

			this[C.N_unary_operator]
				= C.T_address + Common.RShortCut
				| C.T_pointer + Common.RShortCut
				| C.T_add + Common.RShortCut
				| C.T_subtract + Common.RShortCut
				| C.T_bitwise_not + Common.RShortCut
				| C.T_logical_not + Common.RShortCut;

			this[C.N_cast_expression]
				= C.N_unary_expression + Common.RShortCut
				| C.T_leftparenthesis + C.N_type_name + C.T_rightparenthesis + C.N_cast_expression + new Reduction(CParser._cast_expression);

			this[C.N_multiplicative_expression]
				= C.N_cast_expression + Common.RShortCut
				| C.N_multiplicative_expression + C.T_multiply + C.N_cast_expression + new Reduction(CParser._binary_expression)
				| C.N_multiplicative_expression + C.T_divide + C.N_cast_expression + new Reduction(CParser._binary_expression)
				| C.N_multiplicative_expression + C.T_modulo + C.N_cast_expression + new Reduction(CParser._binary_expression);

			this[C.N_additive_expression]
				= C.N_multiplicative_expression + Common.RShortCut
				| C.N_additive_expression + C.T_add + C.N_multiplicative_expression + new Reduction(CParser._binary_expression)
				| C.N_additive_expression + C.T_subtract + C.N_multiplicative_expression + new Reduction(CParser._binary_expression);

			this[C.N_shift_expression]
				= C.N_additive_expression + Common.RShortCut
				| C.N_shift_expression + C.T_shiftleft + C.N_additive_expression + new Reduction(CParser._binary_expression)
				| C.N_shift_expression + C.T_shiftright + C.N_additive_expression + new Reduction(CParser._binary_expression);

			this[C.N_relational_expression]
				= C.N_shift_expression + Common.RShortCut
				| C.N_relational_expression + C.T_less + C.N_shift_expression + new Reduction(CParser._binary_expression)
				| C.N_relational_expression + C.T_greater + C.N_shift_expression + new Reduction(CParser._binary_expression)
				| C.N_relational_expression + C.T_lessorequal + C.N_shift_expression + new Reduction(CParser._binary_expression)
				| C.N_relational_expression + C.T_greaterorequal + C.N_shift_expression + new Reduction(CParser._binary_expression);

			this[C.N_equality_expression]
				= C.N_relational_expression + Common.RShortCut
				| C.N_equality_expression + C.T_equal + C.N_relational_expression + new Reduction(CParser._binary_expression)
				| C.N_equality_expression + C.T_notequal + C.N_relational_expression + new Reduction(CParser._binary_expression);

			this[C.N_and_expression]
				= C.N_equality_expression + Common.RShortCut
				| C.N_and_expression + C.T_bitwise_and + C.N_equality_expression + new Reduction(CParser._binary_expression);

			this[C.N_exclusive_or_expression]
				= C.N_and_expression + Common.RShortCut
				| C.N_exclusive_or_expression + C.T_xor + C.N_and_expression + new Reduction(CParser._binary_expression);

			this[C.N_inclusive_or_expression]
				= C.N_exclusive_or_expression + Common.RShortCut
				| C.N_inclusive_or_expression + C.T_bitwise_or + C.N_exclusive_or_expression + new Reduction(CParser._binary_expression);

			this[C.N_logical_and_expression]
				= C.N_inclusive_or_expression + Common.RShortCut
				| C.N_logical_and_expression + C.T_logical_and + C.N_inclusive_or_expression + new Reduction(CParser._binary_expression);

			this[C.N_logical_or_expression]
				= C.N_logical_and_expression + Common.RShortCut
				| C.N_logical_or_expression + C.T_logical_or + C.N_logical_and_expression + new Reduction(CParser._binary_expression);

			this[C.N_conditional_expression]
				= C.N_logical_or_expression + Common.RShortCut
				| C.N_logical_or_expression + C.T_question + C.N_expression + C.T_colon + C.N_conditional_expression + new Reduction(CParser._trinary_expression);

			this[C.N_assignment_expression] // buggy rule in the standard!?
				= C.N_conditional_expression + Common.RShortCut
				| C.N_conditional_expression + C.T_assign + C.N_assignment_expression + new Reduction(CParser._binary_expression);

			this[C.N_expression]
				= C.N_assignment_expression + Common.RShortCut
				| C.N_expression + C.T_coma + C.N_assignment_expression + new Reduction(CParser._binary_expression);

			this[C.N_constant_expression]
				= C.N_conditional_expression + Common.RShortCut;

			// A.2.2. Declarations

			this[C.N_declaration]
				= C.N_declaration_specifiers + O(C.N_init_declarator_list) + C.T_semicolon + new Reduction(p._declaration);

			this[C.N_declaration_specifiers]
				= C.N_declaration_specifier + Common.RCreateList
				| C.N_declaration_specifiers + C.N_declaration_specifier + Common.RAddToList;

			this[C.N_declaration_specifier]
				= C.N_implementation_defined_specifier + Common.RShortCut
				| C.N_storage_class_specifier + Common.RShortCut
				| C.N_type_qualifier + Common.RShortCut
				| C.N_function_specifier + Common.RShortCut
				| C.N_type_specifier + Common.RShortCut;

			this[C.N_init_declarator_list]
				= C.N_init_declarator + Common.RCreateList
				| C.N_init_declarator_list + C.T_coma + C.N_init_declarator + X(Common.RAddToList, 0, 2);

			this[C.N_init_declarator]
				= C.N_declarator + new Reduction(CParser._init_declarator_0)
				| C.N_declarator + C.T_assign_plain + C.N_initializer + new Reduction(CParser._init_declarator_1);

			// Implementation Defined Specifiers
			// To be extended...
			// *****

			this[C.N_implementation_defined_specifier]
				= C.T_keyword_far + Common.RShortCut
				| C.T_keyword_near + Common.RShortCut
				| C.T_keyword__declspec + Common.RShortCut;

			this[C.N_storage_class_specifier]
				= C.T_keyword_typedef + Common.RShortCut
				| C.T_keyword_extern + Common.RShortCut
				| C.T_keyword_static + Common.RShortCut
				| C.T_keyword_auto + Common.RShortCut
				| C.T_keyword_register + Common.RShortCut;

			this[C.N_type_specifier]
				= C.T_keyword_void + Common.RShortCut
				| C.T_keyword_char + Common.RShortCut
				| C.T_keyword_short + Common.RShortCut
				| C.T_keyword_int + Common.RShortCut
				| C.T_keyword_long + Common.RShortCut
				| C.T_keyword_float + Common.RShortCut
				| C.T_keyword_double + Common.RShortCut
				| C.T_keyword_signed + Common.RShortCut
				| C.T_keyword_unsigned + Common.RShortCut
				| C.T_keyword_bool + Common.RShortCut
				| C.T_keyword_complex + Common.RShortCut
				| C.T_keyword_imaginary + Common.RShortCut
				| C.N_struct_or_union_specifier + Common.RShortCut
				| C.N_enum_specifier + Common.RShortCut
				| C.N_typedef_name + Common.RShortCut;

			this[C.N_struct_or_union_specifier]
				= C.N_struct_or_union + O(C.T_identifier) + N_brace_scope_open + C.N_struct_declaration_list + N_brace_scope_close + new Reduction(CParser._struct_or_union_specifier_0)
				| C.N_struct_or_union + C.T_identifier + new Reduction(CParser._struct_or_union_specifier_1);

			this[C.N_struct_or_union]
				= C.T_keyword_struct + Common.RShortCut
				| C.T_keyword_union + Common.RShortCut;

			this[C.N_struct_declaration_list]
				= C.N_struct_declaration + Common.RShortCut
				| C.N_struct_declaration_list + C.N_struct_declaration + Common.RMergeLists;

			this[C.N_struct_declaration]
				= C.N_specifier_qualifier_list + C.N_struct_declarator_list + C.T_semicolon + new Reduction(p._struct_declaration);

			this[C.N_specifier_qualifier_list]
				= C.N_type_specifier + Common.RCreateList
				| C.N_specifier_qualifier_list + C.N_type_specifier + Common.RAddToList
				| C.N_type_qualifier + Common.RCreateList
				| C.N_specifier_qualifier_list + C.N_type_qualifier + Common.RAddToList
				| C.N_implementation_defined_specifier + Common.RCreateList
				| C.N_specifier_qualifier_list + C.N_implementation_defined_specifier + Common.RAddToList;

			this[C.N_struct_declarator_list]
				= C.N_struct_declarator + Common.RCreateList
				| C.N_struct_declarator_list + C.T_coma + C.N_struct_declarator + X(Common.RAddToList, 0, 2);

			this[C.N_struct_declarator]
				= C.N_declarator + Common.RShortCut
				| O(C.N_declarator) + C.T_colon + C.N_constant_expression + new Reduction(CParser._struct_declarator);

			this[C.N_enum_specifier]
				= C.T_keyword_enum + O(C.T_identifier) + C.T_leftbrace + C.N_enumerator_list + O(C.T_coma) + C.T_rightbrace + new Reduction(CParser._enum_specifier_0)
				| C.T_keyword_enum + C.T_identifier + new Reduction(CParser._enum_specifier_1);

			this[C.N_enumerator_list]
				= C.N_enumerator + Common.RCreateList
				| C.N_enumerator_list + C.T_coma + C.N_enumerator + X(Common.RAddToList, 0, 2);

			this[C.N_enumerator]
				= C.T_enumeration + new Reduction(CParser._enumerator_0)
				| C.T_enumeration + C.T_assign_plain + C.N_constant_expression + new Reduction(CParser._enumerator_1);

			this[C.N_type_qualifier]
				= C.T_keyword_const + Common.RShortCut
				| C.T_keyword_restrict + Common.RShortCut
				| C.T_keyword_volatile + Common.RShortCut;

			this[C.N_function_specifier]
				= C.T_keyword_inline + Common.RShortCut;

			this[C.N_declarator]
				= O(C.N_pointer) + C.N_direct_declarator + new Reduction(CParser._declarator);

			this[C.N_direct_declarator]
				= C.T_identifier + new Reduction(p._direct_declarator_0)
				| C.T_leftparenthesis + C.N_declarator + C.T_rightparenthesis + X(Common.RShortCut, 1)
				| C.N_direct_declarator + C.T_leftbracket + O(C.T_keyword_static) + O(C.N_type_qualifier_list) + O(C.T_keyword_static) + O(C.N_assignment_expression) + C.T_rightbracket + new Reduction(CParser._direct_declarator_2)
				| C.N_direct_declarator + C.T_leftbracket + O(C.N_type_qualifier_list) + C.T_pointer + C.T_rightbracket + new Reduction(CParser._direct_declarator_5)
				| C.N_direct_declarator + N_parenthesis_scope_open + O(C.N_parameter_type_list) + N_parenthesis_scope_close + new Reduction(CParser._direct_declarator_6);

			this[C.N_pointer]
				= C.T_pointer + O(C.N_type_qualifier_list) + O(C.N_pointer) + new Reduction(CParser._pointer);

			this[C.N_type_qualifier_list]
				= C.N_type_qualifier + Common.RCreateList
				| C.N_type_qualifier_list + C.N_type_qualifier + Common.RAddToList;

			this[C.N_parameter_type_list]
				= C.N_parameter_list + Common.RShortCut
				| C.N_parameter_list + C.T_coma + C.T_ellipsis + new Reduction(CParser._parameter_type_list_1);

			this[C.N_parameter_list]
				= C.N_parameter_declaration + Common.RCreateList
				| C.N_parameter_list + C.T_coma + C.N_parameter_declaration + X(Common.RAddToList, 0, 2);

			this[C.N_parameter_declaration]
				= C.N_declaration_specifiers + C.N_declarator + new Reduction(CParser._declaration_1)
				| C.N_declaration_specifiers + O(C.N_abstract_declarator) + new Reduction(CParser._declaration_1);

			this[C.N_identifier_list]
				= C.T_identifier + Common.RCreateList
				| C.N_identifier_list + C.T_coma + C.T_identifier + X(Common.RAddToList, 0, 2);

			this[C.N_type_name]
				= C.N_specifier_qualifier_list + O(C.N_abstract_declarator) + new Reduction(CParser._type_name);

			this[C.N_abstract_declarator]
				= C.N_pointer + O(C.N_direct_abstract_declarator) + new Reduction(CParser._declarator)
				| C.N_direct_abstract_declarator + Common.RShortCut;

			this[C.N_direct_abstract_declarator]
				= C.T_leftparenthesis + C.N_abstract_declarator + C.T_rightparenthesis + X(Common.RShortCut, 1)
				| C.N_direct_abstract_declarator + C.T_leftbracket + O(C.N_assignment_expression) + C.T_rightbracket + X(new Reduction(CParser._direct_declarator_2), 0, 1, -1, 2, 3)
				| O(C.N_direct_abstract_declarator) + C.T_leftbracket + C.T_pointer + C.T_rightbracket + X(new Reduction(CParser._direct_declarator_5), 0, 1, -1, 2, 3)
				| O(C.N_direct_abstract_declarator) + C.T_leftparenthesis + O(C.N_parameter_type_list) + C.T_rightparenthesis + new Reduction(CParser._direct_declarator_6);

			this[C.N_typedef_name]
				= C.T_identifier + new Reduction(p._typedef_name);

			this[C.N_initializer]
				= C.N_assignment_expression + new Reduction(CParser._initializer_0)
				| C.T_leftbrace + C.N_initializer_list + O(C.T_coma) + C.T_rightbrace + new Reduction(CParser._initializer_1);

			NonTerminal N_designated_initializer = new NonTerminal("_designated_initializer");

			this[N_designated_initializer]
				= O(C.N_designation) + C.N_initializer + new Reduction(CParser._designated_initializer);

			this[C.N_initializer_list]
				= N_designated_initializer + Common.RCreateList
				| C.N_initializer_list + C.T_coma + N_designated_initializer + X(Common.RAddToList, 0, 2);
				
			this[C.N_designation]
				= C.N_designator_list + C.T_assign_plain + Common.RShortCut;

			this[C.N_designator_list]
				= C.N_designator + Common.RCreateList
				| C.N_designator_list + C.N_designator + X(Common.RAddToList, 0, 2);

			this[C.N_designator]
				= C.T_leftbracket + C.N_constant_expression + C.T_rightbracket + new Reduction(CParser._designator_0)
				| C.T_dot + C.T_identifier + new Reduction(CParser._designator_1);

			// A.2.3. Statements

			this[C.N_simple_statement]
				= C.N_expression_statement + Common.RShortCut
				| C.N_compound_statement + Common.RShortCut
				| C.N_jump_statement + Common.RShortCut
				| C.N_iteration_statement + Common.RShortCut
				| C.N_comment_statement + Common.RShortCut;

			this[C.N_parenthesized_expression]
				= C.T_leftparenthesis + C.N_expression + C.T_rightparenthesis + X(Common.RShortCut, 1);

			this[C.N_if_header]
				= C.T_keyword_if + C.N_parenthesized_expression + new Reduction(CParser._if_header);

			this[C.N_left_recursive_header]
				= C.T_keyword_for + N_parenthesis_scope_open + O(C.N_expression) + C.T_semicolon + O(C.N_expression) + C.T_semicolon + O(C.N_expression) + C.T_rightparenthesis + new Reduction(CParser._left_recursive_header_0)
				| C.T_keyword_for + N_parenthesis_scope_open + C.N_declaration + O(C.N_expression) + C.T_semicolon + O(C.N_expression) + C.T_rightparenthesis + X(new Reduction(CParser._left_recursive_header_0), 0, 1, 2, -1, 3, 4, 5, 6)
				| C.T_keyword_while + C.N_parenthesized_expression + new Reduction(CParser._left_recursive_header_1)
				// labels
				| C.T_identifier + C.T_colon + new Reduction(CParser._left_recursive_header_2)
				| C.T_keyword_case + C.N_constant_expression + C.T_colon + new Reduction(CParser._left_recursive_header_3)
				| C.T_keyword_default + C.T_colon + new Reduction(CParser._left_recursive_header_4)
				// switch
				| C.T_keyword_switch + C.N_parenthesized_expression + new Reduction(CParser._left_recursive_header_5);

			this[C.N_open_statement]
				= C.N_if_header + C.N_statement + X(new Reduction(p._conditional_statement), 0, 1, -1, -1)
				| C.N_if_header + C.N_closed_statement + C.T_keyword_else + C.N_open_statement + new Reduction(p._conditional_statement)
				| C.N_left_recursive_header + C.N_open_statement + X(new Reduction(p._conditional_statement), 0, 1, -1, -1);

			this[C.N_closed_statement]
				= C.N_simple_statement + Common.RShortCut
				| C.N_if_header + C.N_closed_statement + C.T_keyword_else + C.N_closed_statement + new Reduction(p._conditional_statement)
				| C.N_left_recursive_header + C.N_closed_statement + X(new Reduction(p._conditional_statement), 0, 1, -1, -1);
			
			this[C.N_statement]
				= C.N_open_statement + Common.RShortCut
				| C.N_closed_statement + Common.RShortCut;

			this[C.N_compound_statement]
				= N_brace_scope_open + O(C.N_block_item_list) + N_brace_scope_close + new Reduction(CParser._compound_statement);

			NonTerminal N_declaration_statements = new NonTerminal("_declaration_statements");

			this[N_declaration_statements]
				= C.N_declaration + new Reduction(CParser._declaration_statements);

			this[C.N_comment_statement]
				= C.T_comment + new Reduction(CParser._comment_statement);

			this[C.N_block_item_list]
				= N_declaration_statements + Common.RShortCut
				| C.N_statement + Common.RCreateList
				| C.N_block_item_list + N_declaration_statements + Common.RMergeLists
				| C.N_block_item_list + C.N_statement + Common.RAddToList;

			this[C.N_expression_statement]
				= O(C.N_expression) + C.T_semicolon + new Reduction(CParser._expression_statement);

			this[C.N_iteration_statement]
				= C.T_keyword_do + C.N_statement + C.T_keyword_while + C.N_parenthesized_expression + C.T_semicolon + new Reduction(CParser._iteration_statement);

			this[C.N_jump_statement]
				= C.T_keyword_goto + C.T_identifier + C.T_semicolon + new Reduction(CParser._jump_statement_0)
				| C.T_keyword_continue + C.T_semicolon + new Reduction(CParser._jump_statement_1)
				| C.T_keyword_break + C.T_semicolon + new Reduction(CParser._jump_statement_2)
				| C.T_keyword_return + O(C.N_expression) + C.T_semicolon + new Reduction(CParser._jump_statement_3);

			// A.2.4. External Definitions

			this[C.N_start]
				= C.N_translation_unit + new Reduction(CParser._start);

			this[C.N_translation_unit] 
				= C.N_external_declaration + Common.RShortCut
				| C.N_translation_unit + C.N_external_declaration + Common.RMergeLists;

			this[C.N_external_declaration]
				= C.N_function_definition + Common.RCreateList
				| C.N_declaration + Common.RShortCut
				| C.N_comment_element + Common.RCreateList;

			NonTerminal N_function_declarator = new NonTerminal("_function_declarator");

			this[N_function_declarator]
				= O(C.N_pointer) + C.T_identifier + N_parenthesis_scope_open + O(C.N_parameter_type_list) + N_parenthesis_scope_close + new Reduction(p._function_declarator_1)
				| O(C.N_pointer) + C.T_identifier + N_parenthesis_scope_open + C.N_identifier_list + N_parenthesis_scope_close + C.N_declaration_list + new Reduction(p._function_declarator_2);

			this[C.N_function_definition]
				= C.N_declaration_specifiers + N_function_declarator + C.N_compound_statement + new Reduction(p._function_definition);

			this[C.N_comment_element]
				= C.T_comment + new Reduction(CParser._comment_element);

			this[C.N_declaration_list]
				= C.N_declaration + Common.RShortCut
				| C.N_declaration_list + C.N_declaration + Common.RMergeLists;
		}
	}
}
