%{	/* action-script.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> 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



/* 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:
	  module
	  {
	  }
	| program
	  {
	  }
	;

module:
	  MODULE module_names '{' program '}' ';'
	  {
	  }
	;

program:
	  import
	  {
	  }
	| defs
	  {
	  }
	| program defs
	  {
	  }
	;

defs:
	  class_def
	  {
	  }
	| function_def
	  {
	  }
	;

import:
	  IMPORT import_names ';'
	  {
	  }
	| USING import_names ';'
	  {
	  }
	;

import_names:
	  module_names
	  {
	  }
	| import_names ',' module_names
	  {
	  }
	;

module_names:
	  IDENTIFIER
	  {
	  }
	| IDENTIFIER '.' '*'
	  {
	  }
	| IDENTIFIER '.' module_names
	  {
	  }
	;

class_def:
	  qualified_class IDENTIFIER extends_opt implements_opt '{' definition_list_opt '}'
	  {
	  }
	| INTERFACE IDENTIFIER extends_opt '{' definition_list_opt '}'
	  {
	  }
	;

qualified_class:
	  CLASS
	  {
	  }
	| DYNAMIC CLASS
	  {
	  }
	| INTRINSIC CLASS
	  {
	  }
	;

extends_opt:
	  /* EMPTY */
	  {
	  }
	| EXTENDS IDENTIFIER
	  {
	  }
	;

implements_opt:
	  /* EMPTY */
	  {
	  }
	| IMPLEMENT identifier_list
	  {
	  }
	;

definition_list_opt:
	  /* EMPTY */
	  {
	  }
	| definition_list
	  {
	  }
	;

definition_list:
	  definition
	  {
	  }
	| definition_list definition
	  {
	  }
	;

definition:
	  qualified_def var_def
	  {
	  }
	| qualified_def function_def
	  {
	  }
	;

qualified_def:
	  PRIVATE
	  {
	  }
	| PUBLIC
	  {
	  }
	| STATIC
	  {
	  }
	;

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

function_def:
	  FUNCTION IDENTIFIER '(' var_list_def ')' type_opt statement_block
	  {
	  }
	| FUNCTION GET IDENTIFIER '(' var_list_def ')' type_opt statement_block
	  {
	  }
	| FUNCTION SET IDENTIFIER '(' var_list_def ')' type_opt statement_block
	  {
	  }
	;

var_list_def:
	  var_def
	  {
	  }
	| var_list_def var_def
	  {
	  }
	;

var_def:
	  VAR var_list ';'
	  {
	  }
	| var_list ';'
	  {
	  }
	;

var_list:
	  variable
	  {
	  }
	| var_list ',' variable		%prec LIST_SEPARATOR
	  {
	  }
	;

variable:
	  IDENTIFIER type_opt init_opt ';'
	  {
	  }
	;

init_opt:
	  /* EMPTY */
	  {
	  }
	| '=' init_expr
	  {
	  }
	;


expr:
	/* support for SSWF variables (viewed as constants) */
	  '$' '(' IDENTIFIER ')'
	  {
	  }
	| expr '[' expr ']'
	  {
	  }
	| '(' expr ')'
	  {
	  }
	| '+' expr		%prec POS
	  {
	  }
	| '-' expr		%prec NEG
	  {
	  }
	| '!' expr		%prec '!'
	  {
	  }
	| '~' expr		%prec '~'
	  {
	  }
	| INCREMENT expr	%prec PRE_INCREMENT
	  {
	  }
	| expr INCREMENT	%prec POST_INCREMENT
	  {
	  }
	| DECREMENT expr	%prec PRE_DECREMENT
	  {
	  }
	| expr DECREMENT	%prec POST_DECREMENT
	  {
	  }
	| expr '(' ')'
	  {
	  }
	| expr '(' expr ')'
	  {
	  }
	| NEW IDENTIFIER '(' expr ')'
	  {
	  }
	| DELETE expr
	  {
	  }
	| TYPEOF expr
	  {
	  }
	| expr '.' expr
	  {
	  }
	| expr POWER expr
	  {
	  }
	| expr '*' expr
	  {
	  }
	| expr '/' expr
	  {
	  }
	| expr '%' expr
	  {
	  }
	| expr '+' expr
	  {
	  }
	| expr '-' expr
	  {
	  }
	| expr SHIFT_LEFT expr
	  {
	  }
	| expr SHIFT_RIGHT expr
	  {
	  }
	| expr SHIFT_RIGHT_UNSIGNED expr
	  {
	  }
	| expr ROTATE_LEFT expr
	  {
	  }
	| expr ROTATE_RIGHT expr
	  {
	  }
	| expr MAX expr
	  {
	  }
	| expr MIN expr
	  {
	  }
	| expr EQUAL expr
	  {
	  }
	| expr EXACTLY_EQUAL expr
	  {
	  }
	| expr NOT_EQUAL expr
	  {
	  }
	| expr EXACTLY_NOT_EQUAL expr
	  {
	  }
	| expr '<' expr
	  {
	  }
	| expr LESS_EQUAL expr
	  {
	  }
	| expr '>' expr
	  {
	  }
	| expr GREATER_EQUAL expr
	  {
	  }
	| expr '&' expr
	  {
	  }
	| expr '^' expr
	  {
	  }
	| expr '|' expr
	  {
	  }
	| expr LOGICAL_AND expr
	  {
	  }
	| expr LOGICAL_XOR expr
	  {
	  }
	| expr LOGICAL_OR expr
	  {
	  }
	| expr INSTANCE_OF expr
	  {
	  }
	| expr '?' expr ':' expr
	  {
	  }
	| expr ASSIGN expr
	  {
	  	/* ASSIGN includes
		 *	=, :=
		 *	**=
		 *	*=, /=, %=
		 *	+=, -=
		 *	<?=, >?=
		 *	<<=, >>=, >>>=, !<=, !>=
		 *	|=, ^=, &=
		 *	||=, ^^=, &&=
		 */
	  }
	| expr ',' expr
	  {
	  }
	| IDENTIFIER
	  {
	  }
	/* VALUE includes NaN, Infinity */
	| VALUE
	  {
	  }
	| BOOLEAN
	  {
	  }
	/* STRING includes newline (== "\n") */
	| STRING
	  {
	  }
	| _LEVEL
	  {
	  }
	| _GLOBAL
	  {
	  }
	| THIS
	  {
	  }
	| SUPER
	  {
	  }
	| _PARENT
	  {
	  }
	| _QUALITY
	  {
	  }
	| _ROOT
	  {
	  }
	| _NULL
	  {
	  }
	| UNDEFINED
	  {
	  }
	;

expr_opt:
	  /* EMPTY */
	  {
	  }
	| expr
	  {
	  }
	;


init_expr:
	  expr
	  {
	  }
	| '{' labelled_expr '}'
	  {
	  }
	| '[' init_expr ']'
	  {
	  }
	;

labelled_expr:
	  init_expr
	  {
	  }
	| IDENTIFIER ':' expr
	  {
	  }
	| labelled_expr ';' labelled_expr		//%prec LIST_SEPARATOR
	  {
	  }
	;

statement_block:
	  '{' statement_list '}'
	  {
	  }
	| '{' '}'
	  {
	  }
	;

statement_list:
	| statement
	  {
	  }
	| statement_list statement
	  {
	  }
	;

statement:
	  VAR var_list ';'
	  {	/* defines local variables */
	  }
	| IF '(' expr ')' statement else_opt
	  {
	  }
	| WHILE '(' expr ')' statement
	  {
	  }
	| DO statement WHILE '(' expr ')' ';'
	  {
	  }
	| FOR '(' expr_opt ';' expr_opt ';' expr_opt ')' statement
	  {
	  }
	| FOR '(' VAR IDENTIFIER IN expr ')' statement
	  {
	  }
	| WITH '(' IDENTIFIER ')' statement
	  {
	  }
	| SWITCH '(' expr ')' '{' case_list '}'
	  {
	  }
	| BREAK ';'
	  {
	  }
	| CONTINUE ';'
	  {
	  }
	| RETURN expr_opt ';'
	  {
	  }
	| THROW expr ';'
	  {
	  }
	| TRY statement
	  {
	  }
	| CATCH '(' IDENTIFIER type_opt ')' statement
	  {
	  }
	| FINALLY statement
	  {
	  }
	/* if we can relatively easilly emulate this instruction
	 * we certain should have it too */
	| GOTO IDENTIFIER ';'
	  {
	  }
	/* we could also use the labels for break/continue
	 * instructions so we can break/continue any level */
	| IDENTIFIER ':'
	  {
	  }
	| statement_block
	  {
	  }
	| expr ';'
	  {
	  }
	| ';'
	  {
	  }
	;

else_opt:
	  /* EMPTY */
	  {
	  }
	| ELSE statement
	  {
	  }
	;

case_list:
	  case_entry
	  {
	  }
	| case_list case_entry
	  {
	  }
	;

case_entry:
	  CASE expr ':' statement_list
	  {
	  }
	| DEFAULT ':' statement_list
	  {
	  }
	;

type_opt:
	  /* EMPTY */
	  {
	  }
	| ':' IDENTIFIER
	  {
	  }
	;



%%


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




