%{	/* ecma.y -- written by Alexis WILKE for Made to Order Software Corp. (c) 2004-2007 */
	/* grammar parser for Action Scripts */

/*

Copyright (c) 2004-2007 Made to Order Software Corp.

Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and
associated documentation files (the "Software"), to
deal in the Software without restriction, including
without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the
following conditions:

The above copyright notice and this permission notice
shall be included in all copies or substantial
portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

*/


#include	"sswf.h"

#define	YYPARSE_PARAM		result
static	void			yyerror(const char *msg);



%}



%union
{
	struct node_t		*node;
	int			unused;
};


/* terminals */

%token	<node>		ASSIGNMENT_OPERATOR
%token	<node>		BREAK
%token	<node>		CASE
%token	<node>		CATCH
%token	<node>		CONTINUE
%token	<node>		DECREMENT
%token	<node>		DEFAULT
%token	<node>		DELETE
%token	<node>		DO
%token	<node>		ELSE
%token	<node>		EQUAL
%token	<node>		EXACTLY_EQUAL
%token	<node>		EXACTLY_NOT_EQUAL
%token	<node>		FALSE
%token	<node>		FINALLY
%token	<node>		FOR
%token	<node>		FUNCTION
%token	<node>		GREATER_EQUAL
%token	<node>		IDENTIFIER
%token	<node>		IF
%token	<node>		IN
%token	<node>		INCREMENT
%token	<node>		INSTANCEOF
%token	<node>		LESS_EQUAL
%token	<node>		LOGICAL_AND
%token	<node>		LOGICAL_OR
%token	<node>		NEW
%token	<node>		NOT_EQUAL
%token	<node>		NULL_LITERAL
%token	<node>		NUMERIC
%token	<node>		RETURN
%token	<node>		SHIFT_LEFT
%token	<node>		SHIFT_RIGHT
%token	<node>		SHIFT_RIGHT_UNSIGNED
%token	<node>		STRING
%token	<node>		SWITCH
%token	<node>		THIS
%token	<node>		THROW
%token	<node>		TRY
%token	<node>		TRUE
%token	<node>		TYPEOF
%token	<node>		VAR
%token	<node>		VOID
%token	<node>		WITH
%token	<node>		WHILE


/*
%token	<node> STRING VALUE BOOLEAN IDENTIFIER UNDEFINED _NULL _ROOT
%token	<node> _QUALITY _PARENT _GLOBAL _LEVEL THIS SUPER
%token	<unused> FOR IF ELSE DEFAULT CASE GOTO FINALLY CATCH
%token	<unused> TRY THROW RETURN CONTINUE BREAK SWITCH WITH IN DO WHILE
%token	<unused> DELETE NEW DECREMENT INCREMENT GET SET VAR FUNCTION
%token	<unused> STATIC PUBLIC PRIVATE IMPLEMENT EXTENDS INTRINSIC DYNAMIC
%token	<unused> CLASS INTERFACE IMPORT
*/

/* all these yacc expressions are nodes */
/*
%type	<node> start expr
%type	<node> module
%type	<node> definition statement labelled_expr
*/

%type	<node>		variable_statement


/* expressions are like in C/C++ */
/*
%left	','
%left	ASSIGN
%left	'?' ':'
%left	LOGICAL_OR
%left	LOGICAL_XOR
%left	LOGICAL_AND
%left	'|'
%left	'^'
%left	'&'
%left	EQUAL EXACTLY_EQUAL NOT_EQUAL EXACTLY_NOT_EQUAL
%left	'<' LESS_EQUAL '>' GREATER_EQUAL INSTANCE_OF IN
%left	MAX MIN
%right	SHIFT_LEFT SHIFT_RIGHT SHIFT_RIGHT_UNSIGNED ROTATE_LEFT ROTATE_RIGHT
%left	'+' '-'
%left	'*' '/' '%'
%right	POWER
%right	POS NEG '!' '~' PRE_INCREMENT POST_INCREMENT PRE_DECREMENT POST_DECREMENT
%left	'['
%right	'.'
%left	LIST_SEPARATOR
*/


%%

/**** START ****/
start:
	  program
	  {
	  }
	;

program:
	  source_element_list
	  {
	  }
	;

source_element_list:
	  source_element
	  {
	  }
	| source_element_list source_element
	  {
	  }
	;

source_element:
	  statement
	  {
	  }
	| function_declaration
	  {
	  }
	;


function_declaration:
	  FUNCTION IDENTIFIER '(' formal_parameter_list ')' '{' function_body '}'
	  {
	  }
	| FUNCTION IDENTIFIER '(' ')' '{' function_body '}'
	  {
	  }
	;

function_expression:
	  function_declaration
	  {
	  }
	| FUNCTION '(' formal_parameter_list ')' '{' function_body '}'
	  {
	  }
	| FUNCTION '(' ')' '{' function_body '}'
	  {
	  }
	;

formal_parameter_list:
	  IDENTIFIER
	  {
	  }
	| formal_parameter_list ',' IDENTIFIER
	  {
	  }
	;

function_body:
	  source_element_list
	  {
	  }
	;






statement:
	  block
	  {
	  }
	| variable_statement
	  {
	  }
	| empty_statement
	  {
	  }
	| expression_statement
	  {
	  }
	| if_statement
	  {
	  }
	| iteration_statement
	  {
	  }
	| continue_statement
	  {
	  }
	| break_statement
	  {
	  }
	| return_statement
	  {
	  }
	| with_statement
	  {
	  }
	| labelled_statement
	  {
	  }
	| switch_statement
	  {
	  }
	| throw_statement
	  {
	  }
	| try_statement
	  {
	  }
	;


block:
	  '{' '}'
	  {
	  }
	| '{' statement_list '}'
	  {
	  }
	;


statement_list:
	  statement
	  {
	  }
	| statement_list statement
	  {
	  }
	;


variable_statement:
	  // TODO: see whether the ';' is mandatory for 'var'
	  VAR variable_declaration_list ';'
	;


variable_declaration_list:
	  variable_declaration
	  {
	  }
	| variable_declaration_list ',' variable_declaration
	  {
	  }
	;


variable_declaration_list_no_in:
	  variable_declaration_no_in
	  {
	  }
	| variable_declaration_list_no_in ',' variable_declaration_no_in
	  {
	  }
	;


variable_declaration:
	  IDENTIFIER
	  {
	  }
	| IDENTIFIER initializer
	  {
	  }
	;


variable_declaration_no_in:
	  IDENTIFIER
	  {
	  }
	| IDENTIFIER initializer_no_in
	  {
	  }
	;


initializer:
	  '=' assignment_expression
	  {
	  }
	;


initializer_no_in:
	  '=' assignment_expression_no_in
	  {
	  }
	;



empty_statement:
	  ';'
	;



expression_statement:
	  // BUT NOT '{' or FUNCTION
	  expression ';'
	  {
	  }
	;


if_statement:
	  IF '(' expression ')' statement ELSE statement
	  {
	  }
	| IF '(' expression ')' statement
	  {
	  }
	;


iteration_statement:
	  DO statement WHILE '(' expression ')' ';'
	  {
	  }
	| WHILE '(' expression ')' statement
	  {
	  }
	| FOR '(' expression_no_in_opt ';' expression_no_in_opt ';' expression_no_in_opt ')' statement
	  {
	  }
	| FOR '(' VAR variable_declaration_list_no_in ';' expression_no_in_opt ';' expression_no_in_opt ')' statement
	  {
	  }
	| FOR '(' left_hand_side_expression IN expression ')' statement
	  {
	  }
	| FOR '(' VAR variable_declaration_list_no_in IN expression ')' statement
	  {
	  }
	;



continue_statement:
	  CONTINUE
	  {
	  }
	| CONTINUE /*no line terminator*/ IDENTIFIER
	  {
	  }
	;


break_statement:
	  BREAK
	  {
	  }
	| BREAK /*no line terminator*/ IDENTIFIER
	  {
	  }
	;


return_statement:
	  RETURN
	  {
	  }
	| RETURN /*no line terminator*/ expression
	  {
	  }
	;





with_statement:
	  WITH '(' expression ')' statement
	  {
	  }
	;


switch_statement:
	  SWITCH '(' expression ')' case_block
	  {
	  }
	;


case_block:
	  '{' '}'
	  {
	  }
	| '{' case_clause_list '}'
	  {
	  }
	;


case_clause_list:
	  case_clause
	  {
	  }
	| case_clause_list case_clause
	  {
	  }
	;



case_clause:
	  CASE expression ':'
	  {
	  }
	| CASE expression ':' statement_list
	  {
	  }
	| DEFAULT ':'
	  {
	  }
	| DEFAULT ':' statement_list
	  {
	  }
	;



labelled_statement:
	  IDENTIFIER ':' statement
	  {
	  }
	;



throw_statement:
	  THROW /*no line terminator*/ expression
	  {
	  }
	;


try_statement:
	  TRY block catch
	  {
	  }
	| TRY block finally
	  {
	  }
	| TRY block catch finally
	  {
	  }
	;


catch:
	  CATCH '(' IDENTIFIER '}' block
	  {
	  }
	;


finally:
	  FINALLY block
	  {
	  }
	;




primary_expression:
	  THIS
	  {
	  }
	| IDENTIFIER
	  {
	  }
	| literal
	  {
	  }
	| array_literal
	  {
	  }
	| object_literal
	  {
	  }
	| '(' expression ')'
	  {
	  }
	;



literal:
	  NULL_LITERAL
	  {
	  }
	| TRUE
	  {
	  }
	| FALSE
	  {
	  }
	| NUMERIC
	  {
	  }
	| STRING
	  {
	  }
	;



array_literal:
	  '[' ']'
	  {
	  }
	| '[' elision ']'
	  {
	  }
	| '[' element_list ']'
	  {
	  }
	| '[' element_list elision ']'
	  {
	  }
	;


element_list:
	  assignment_expression
	  {
	  }
	| elision assignment_expression
	  {
	  }
	| element_list elision assignment_expression
	  {
	  }
	;


elision:
	  ','
	  {
	  }
	| elision ','
	  {
	  }
	;


object_literal:
	  '{' '}'
	  {
	  }
	| '{' property_name_and_value_list '}'
	  {
	  }
	;


property_name_and_value_list:
	  property
	  {
	  }
	| property_name_and_value_list ',' property
	  {
	  }
	;

property:
	  property_name ':' assignment_expression
	  {
	  }
	;


property_name:
	  IDENTIFIER
	  {
	  }
	| STRING
	  {
	  }
	| NUMERIC
	  {
	  }
	;



member_expression:
	  primary_expression
	  {
	  }
	| function_expression
	  {
	  }
	| member_expression '[' expression ']'
	  {
	  }
	| member_expression '.' IDENTIFIER
	  {
	  }
	| NEW member_expression arguments
	  {
	  }
	;


new_expression:
	  member_expression
	  {
	  }
	| NEW new_expression
	  {
	  }
	;


call_expression:
	  member_expression arguments
	  {
	  }
	| call_expression arguments
	  {
	  }
	| call_expression '[' expression ']'
	  {
	  }
	| call_expression '.' IDENTIFIER
	  {
	  }
	;


arguments:
	  '(' ')'
	  {
	  }
	| '(' argument_list ')'
	  {
	  }
	;



argument_list:
	  assignment_expression
	  {
	  }
	| argument_list ',' assignment_expression
	  {
	  }
	;



left_hand_side_expression:
	  new_expression
	  {
	  }
	| call_expression
	  {
	  }
	;


postfix_expression:
	  left_hand_side_expression
	  {
	  }
	| left_hand_side_expression INCREMENT
	  {
	  }
	| left_hand_side_expression DECREMENT
	  {
	  }
	;



unary_expression:
	  postfix_expression
	  {
	  }
	| DELETE unary_expression
	  {
	  }
	| VOID unary_expression
	  {
	  }
	| TYPEOF unary_expression
	  {
	  }
	| INCREMENT unary_expression
	  {
	  }
	| DECREMENT unary_expression
	  {
	  }
	| '+' unary_expression
	  {
	  }
	| '-' unary_expression
	  {
	  }
	| '~' unary_expression
	  {
	  }
	| '!' unary_expression
	  {
	  }
	;


multiplicative_expression:
	  unary_expression
	  {
	  }
	| multiplicative_expression '*' unary_expression
	  {
	  }
	| multiplicative_expression '/' unary_expression
	  {
	  }
	| multiplicative_expression '%' unary_expression
	  {
	  }
	;



additive_expression:
	  multiplicative_expression
	  {
	  }
	| additive_expression '+' multiplicative_expression
	  {
	  }
	| additive_expression '-' multiplicative_expression
	  {
	  }
	;



shift_expression:
	  additive_expression
	  {
	  }
	| shift_expression SHIFT_LEFT additive_expression
	  {
	  }
	| shift_expression SHIFT_RIGHT additive_expression
	  {
	  }
	| shift_expression SHIFT_RIGHT_UNSIGNED additive_expression
	  {
	  }
	;


relational_expression:
	  shift_expression
	  {
	  }
	| relational_expression '<' shift_expression
	  {
	  }
	| relational_expression '>' shift_expression
	  {
	  }
	| relational_expression LESS_EQUAL shift_expression
	  {
	  }
	| relational_expression GREATER_EQUAL shift_expression
	  {
	  }
	| relational_expression INSTANCEOF shift_expression
	  {
	  }
	| relational_expression IN shift_expression
	  {
	  }
	;



relational_expression_no_in:
	  shift_expression
	  {
	  }
	| relational_expression_no_in '<' shift_expression
	  {
	  }
	| relational_expression_no_in '>' shift_expression
	  {
	  }
	| relational_expression_no_in LESS_EQUAL shift_expression
	  {
	  }
	| relational_expression_no_in GREATER_EQUAL shift_expression
	  {
	  }
	| relational_expression_no_in INSTANCEOF shift_expression
	  {
	  }
	;


equality_expression:
	  relational_expression
	  {
	  }
	| equality_expression EQUAL relational_expression
	  {
	  }
	| equality_expression NOT_EQUAL relational_expression
	  {
	  }
	| equality_expression EXACTLY_EQUAL relational_expression
	  {
	  }
	| equality_expression EXACTLY_NOT_EQUAL relational_expression
	  {
	  }
	;




equality_expression_no_in:
	  relational_expression_no_in
	  {
	  }
	| equality_expression_no_in EQUAL relational_expression_no_in
	  {
	  }
	| equality_expression_no_in NOT_EQUAL relational_expression_no_in
	  {
	  }
	| equality_expression_no_in EXACTLY_EQUAL relational_expression_no_in
	  {
	  }
	| equality_expression_no_in EXACTLY_NOT_EQUAL relational_expression_no_in
	  {
	  }
	;



bitwise_and_expression:
	  equality_expression
	  {
	  }
	| bitwise_and_expression '&' equality_expression
	  {
	  }
	;

bitwise_and_expression_no_in:
	  equality_expression_no_in
	  {
	  }
	| bitwise_and_expression_no_in '&' equality_expression_no_in
	  {
	  }
	;


bitwise_xor_expression:
	  bitwise_and_expression
	  {
	  }
	| bitwise_xor_expression '^' bitwise_and_expression
	  {
	  }
	;

bitwise_xor_expression_no_in:
	  bitwise_and_expression_no_in
	  {
	  }
	| bitwise_xor_expression_no_in '^' bitwise_and_expression_no_in
	  {
	  }
	;


bitwise_or_expression:
	  bitwise_xor_expression
	  {
	  }
	| bitwise_or_expression '|' bitwise_xor_expression
	  {
	  }
	;

bitwise_or_expression_no_in:
	  bitwise_xor_expression_no_in
	  {
	  }
	| bitwise_or_expression_no_in '|' bitwise_xor_expression_no_in
	  {
	  }
	;




logical_and_expression:
	  bitwise_or_expression
	  {
	  }
	| logical_and_expression LOGICAL_AND bitwise_or_expression
	  {
	  }
	;

logical_and_expression_no_in:
	  bitwise_or_expression_no_in
	  {
	  }
	| logical_and_expression_no_in LOGICAL_AND bitwise_or_expression_no_in
	  {
	  }
	;




logical_or_expression:
	  logical_and_expression
	  {
	  }
	| logical_or_expression LOGICAL_OR logical_and_expression
	  {
	  }
	;

logical_or_expression_no_in:
	  logical_and_expression_no_in
	  {
	  }
	| logical_or_expression_no_in LOGICAL_OR logical_and_expression_no_in
	  {
	  }
	;


conditional_expression:
	  logical_or_expression
	  {
	  }
	| logical_or_expression '?' assignment_expression ':' assignment_expression
	  {
	  }
	;


conditional_expression_no_in:
	  logical_or_expression_no_in
	  {
	  }
	| logical_or_expression_no_in '?' assignment_expression ':' assignment_expression_no_in
	  {
	  }
	;



assignment_expression:
	  conditional_expression
	  {
	  }
	| left_hand_side_expression ASSIGNMENT_OPERATOR assignment_expression
	  {
	  }
	;

assignment_expression_no_in:
	  conditional_expression_no_in
	  {
	  }
	| left_hand_side_expression ASSIGNMENT_OPERATOR assignment_expression_no_in
	  {
	  }
	;



expression:
	  assignment_expression
	  {
	  }
	| expression ',' assignment_expression
	  {
	  }
	;

expression_no_in:
	  assignment_expression_no_in
	  {
	  }
	| expression_no_in ',' assignment_expression_no_in
	  {
	  }
	;


expression_no_in_opt:
	  /* EMPTY */
	  {
	  }
	| expression_no_in
	  {
	  }
	;



%%


void yyerror(const char *msg)
{
	printf("YACC ERROR at line #%d in file \"%s\": %s.\n", yylloc.first_line, lex_filename, msg);
}




