;;; javascript-jv.wy -- LALR grammar for Javascript

;; Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
;;   Free Software Foundation, Inc.
;; Copyright (C) 1998-2011 Ecma International.

;; Author: Joakim Verona

;; This file is part of GNU Emacs.

;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; GNU Emacs 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 General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.

;;; Commentary:

;; The grammar itself is transcribed from the ECMAScript Language
;; Specification published at
;;
;; http://www.ecma-international.org/publications/standards/Ecma-262.htm
;;
;; and redistributed under the following license:

;; Redistribution and use in source and binary forms, with or without
;; modification, are permitted provided that the following conditions
;; are met:

;; 1. Redistributions of source code must retain the above copyright
;; notice, this list of conditions and the following disclaimer.

;; 2. Redistributions in binary form must reproduce the above
;; copyright notice, this list of conditions and the following
;; disclaimer in the documentation and/or other materials provided
;; with the distribution.

;; 3. Neither the name of the authors nor Ecma International may be
;; used to endorse or promote products derived from this software
;; without specific prior written permission.  THIS SOFTWARE IS
;; PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR
;; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
;; ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR
;; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
;; OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
;; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
;; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
;; USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
;; DAMAGE.

%package wisent-javascript-jv-wy
;; JAVE I prefere ecmascript-mode
%languagemode ecmascript-mode javascript-mode

;; The default goal
%start Program
;; Other Goals
%start FormalParameterList

;; with the terminals stuff, I used the javacript.y names,
;; but the wisent-java-tags.wy types
;; when possible
;; ------------------
;; Operator terminals
;; ------------------

;;define-lex-string-type-analyzer gets called with the "syntax" comment
%type <punctuation> ;;syntax "\\(\\s.\\|\\s$\\|\\s'\\)+" matchdatatype string

%token <punctuation> ASSIGN_SYMBOL            "="
%token <punctuation> BITWISE_AND              "&"
%token <punctuation> BITWISE_AND_EQUALS       "&="
%token <punctuation> BITWISE_EXCLUSIVE_OR     "^"
%token <punctuation> BITWISE_EXCLUSIVE_OR_EQUALS "^="
%token <punctuation> BITWISE_OR               "|"
%token <punctuation> BITWISE_OR_EQUALS        "|="
%token <punctuation> BITWISE_SHIFT_LEFT       "<<"
%token <punctuation> BITWISE_SHIFT_LEFT_EQUALS "<<="
%token <punctuation> BITWISE_SHIFT_RIGHT      ">>"
%token <punctuation> BITWISE_SHIFT_RIGHT_EQUALS ">>="
%token <punctuation> BITWISE_SHIFT_RIGHT_ZERO_FILL ">>>"
%token <punctuation> BITWISE_SHIFT_RIGHT_ZERO_FILL_EQUALS ">>>="
%token <punctuation> NOT_EQUAL "!="
%token <punctuation> DIV_EQUALS "/="
%token <punctuation> EQUALS "=="
%token <punctuation> GREATER_THAN ">"
%token <punctuation> GT_EQUAL ">="
%token <punctuation> LOGICAL_AND "&&"
%token <punctuation> LOGICAL_OR "||"
%token <punctuation> LOGICAL_NOT "!!"
%token <punctuation> LS_EQUAL "<="
%token <punctuation> MINUS "-"
%token <punctuation> MINUS_EQUALS "-="
%token <punctuation> MOD "%"
%token <punctuation> MOD_EQUALS "%="
%token <punctuation> MULTIPLY "*"
%token <punctuation> MULTIPLY_EQUALS "*="
%token <punctuation> PLUS "+"
%token <punctuation> PLUS_EQUALS "+="
%token <punctuation> INCREMENT "++"
%token <punctuation> DECREMENT "--"
%token <punctuation> DIV "/"
%token <punctuation> COLON ":"
%token <punctuation> COMMA ","
%token <punctuation> DOT "."
%token <punctuation> LESS_THAN "<"
%token <punctuation> LINE_TERMINATOR "\n"
%token <punctuation> SEMICOLON ";"
%token <punctuation> ONES_COMPLIMENT "~"


;; -----------------------------
;; Block & Parenthesis terminals
;; -----------------------------
%type  <block>       ;;syntax "\\s(\\|\\s)" matchdatatype block
%token <block>       PAREN_BLOCK "(OPEN_PARENTHESIS CLOSE_PARENTHESIS)"
%token <block>       BRACE_BLOCK "(START_BLOCK END_BLOCK)"
%token <block>       BRACK_BLOCK "(OPEN_SQ_BRACKETS CLOSE_SQ_BRACKETS)"

%token <open-paren>  OPEN_PARENTHESIS  "("
%token <close-paren>  CLOSE_PARENTHESIS ")"

%token <open-paren>  START_BLOCK       "{"
%token <close-paren>  END_BLOCK         "}"

%token <open-paren>  OPEN_SQ_BRACKETS  "["
%token <close-paren>  CLOSE_SQ_BRACKETS "]"


;; -----------------
;; Keyword terminals
;; -----------------

;; Generate a keyword analyzer
%type  <keyword> ;;syntax "\\(\\sw\\|\\s_\\)+" matchdatatype keyword

%keyword IF           "if"
%put     IF summary
"if (<expr>) <stmt> [else <stmt>] (jv)"

%keyword BREAK        "break"
%put     BREAK summary
"break [<label>] ;"

%keyword CONTINUE     "continue"
%put     CONTINUE summary
"continue [<label>] ;"

%keyword ELSE         "else"
%put     ELSE summary
"if (<expr>) <stmt> else <stmt>"


%keyword FOR          "for"
%put     FOR summary
"for ([<init-expr>]; [<expr>]; [<update-expr>]) <stmt>"


%keyword FUNCTION  "function"
%put     FUNCTION summary
"function declaration blah blah"

%keyword THIS         "this"
%put THIS summary
"this"


%keyword RETURN       "return"
%put     RETURN summary
"return [<expr>] ;"

%keyword WHILE        "while"
%put     WHILE summary
"while (<expr>) <stmt> | do <stmt> while (<expr>);"

%keyword VOID_SYMBOL         "void"
%put     VOID_SYMBOL summary
"Method return type: void <name> ..."



%keyword NEW          "new"
%put NEW summary
"new <objecttype> - Creates a new object."

%keyword DELETE "delete"
%put DELETE summary
"delete(<objectreference>) - Deletes the object."

%keyword VAR "var"
%put VAR  summary
"var <variablename> [= value];"

%keyword WITH "with"
%put WITH summary
"with "

%keyword TYPEOF "typeof"
%put TYPEOF summary
"typeof "

%keyword IN "in"
%put IN  summary
"in something"


;; -----------------
;; Literal terminals
;; -----------------

;;the .y file uses VARIABLE as IDENTIFIER, which seems a bit evil
;; it think the normal .wy convention is better than this
%type  <symbol>      ;;syntax "\\(\\sw\\|\\s_\\)+"
%token <symbol>      VARIABLE

%type  <string>      ;;syntax "\\s\"" matchdatatype sexp
%token <string>      STRING

%type  <number>      ;;syntax semantic-lex-number-expression
%token <number>      NUMBER


%token FALSE
%token TRUE
%token QUERY


%token NULL_TOKEN

;;%token UNDEFINED_TOKEN
;;%token INFINITY

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; associativity and stuff
%left PLUS MINUS
%left MULTIPLY DIV MOD

%nonassoc FALSE
%nonassoc HIGHER_THAN_FALSE
%nonassoc ELSE
%nonassoc LOWER_THAN_CLOSE_PARENTHESIS
%nonassoc CLOSE_PARENTHESIS

%%

Program : SourceElement
        ;

SourceElement : Statement
              | FunctionDeclaration
              ;

Statement : Block
          | VariableStatement
          | EmptyStatement
          | ExpressionStatement
          | IfStatement
          | IterationExpression
          | ContinueStatement
          | BreakStatement
          | ReturnStatement
          | WithStatement
          ;   
      
FunctionDeclaration : FUNCTION VARIABLE FormalParameterListBlock Block
		      (FUNCTION-TAG $2 nil $3)
                    ;

FormalParameterListBlock : PAREN_BLOCK
			   (EXPANDFULL $1 FormalParameterList)
			;

FormalParameterList: OPEN_PARENTHESIS
		     ()
		   | VARIABLE
		     (VARIABLE-TAG $1 nil nil)
		   | CLOSE_PARENTHESIS
		     ()
		   | COMMA
		     ()
		   ;

StatementList : Statement
              | StatementList Statement
              ;

Block : BRACE_BLOCK
     ;; If you want to parse the body of the function
     ;; ( EXPANDFULL $1 BlockExpand )
      ;

BlockExpand: START_BLOCK StatementList END_BLOCK
	   | START_BLOCK END_BLOCK
	   ;

VariableStatement : VAR VariableDeclarationList SEMICOLON
		    (VARIABLE-TAG $2 nil nil)
                  ;

VariableDeclarationList : VariableDeclaration
			  (list $1)
                        | VariableDeclarationList COMMA VariableDeclaration
			  (append $1 (list $3))
                        ;

VariableDeclaration : VARIABLE
		      (append (list $1 nil) $region)
                    | VARIABLE Initializer
		      (append (cons $1 $2) $region)
                    ;

Initializer : ASSIGN_SYMBOL AssignmentExpression
	      (list $2)
            ;

EmptyStatement : SEMICOLON
               ;

ExpressionStatement : Expression SEMICOLON
                    ;

IfStatement : IF OPEN_PARENTHESIS Expression CLOSE_PARENTHESIS Statement  %prec HIGHER_THAN_FALSE
            | IF OPEN_PARENTHESIS Expression CLOSE_PARENTHESIS Statement ELSE Statement
            | IF OPEN_PARENTHESIS FALSE CLOSE_PARENTHESIS Statement
            | IF OPEN_PARENTHESIS LeftHandSideExpression AssignmentOperator AssignmentExpression CLOSE_PARENTHESIS Statement
            ;

IterationExpression : WHILE OPEN_PARENTHESIS Expression CLOSE_PARENTHESIS Statement %prec HIGHER_THAN_FALSE
                    | WHILE OPEN_PARENTHESIS FALSE CLOSE_PARENTHESIS Statement
                    | WHILE OPEN_PARENTHESIS LeftHandSideExpression AssignmentOperator AssignmentExpression CLOSE_PARENTHESIS Statement
                    | FOR OPEN_PARENTHESIS OptionalExpression SEMICOLON OptionalExpression SEMICOLON OptionalExpression CLOSE_PARENTHESIS Statement
                    | FOR OPEN_PARENTHESIS VAR VariableDeclarationList SEMICOLON OptionalExpression SEMICOLON OptionalExpression CLOSE_PARENTHESIS Statement
                    | FOR OPEN_PARENTHESIS LeftHandSideExpression IN Expression CLOSE_PARENTHESIS Statement
                    | FOR OPEN_PARENTHESIS VAR VARIABLE OptionalInitializer IN Expression CLOSE_PARENTHESIS Statement
                    ;

ContinueStatement : CONTINUE SEMICOLON
                  ;

;;JAVE break needs labels 
BreakStatement : BREAK SEMICOLON
              ;;               | BREAK identifier SEMICOLON
               ;

ReturnStatement : RETURN Expression SEMICOLON
                | RETURN SEMICOLON
                ;

WithStatement : WITH OPEN_PARENTHESIS Expression CLOSE_PARENTHESIS   Statement
              ;

OptionalInitializer : Initializer
                    |
                    ;

PrimaryExpression : THIS
                  | VARIABLE
                  | NUMBER
                  | STRING
                  | NULL_TOKEN
                  | TRUE
                  | FALSE
                  | OPEN_PARENTHESIS Expression CLOSE_PARENTHESIS
                  ;

MemberExpression : PrimaryExpression
                 | MemberExpression OPEN_SQ_BRACKETS Expression  CLOSE_SQ_BRACKETS
                 | MemberExpression DOT VARIABLE
                 | NEW MemberExpression Arguments
                 ;

NewExpression : MemberExpression
              | NEW NewExpression
              ;

CallExpression : MemberExpression Arguments
               | CallExpression Arguments
               | CallExpression OPEN_SQ_BRACKETS Expression  CLOSE_SQ_BRACKETS
               | CallExpression DOT VARIABLE
               ;

Arguments : OPEN_PARENTHESIS CLOSE_PARENTHESIS
          | OPEN_PARENTHESIS ArgumentList CLOSE_PARENTHESIS
          ;

ArgumentList : AssignmentExpression
             | ArgumentList COMMA AssignmentExpression
             ;

LeftHandSideExpression : NewExpression
                       | CallExpression
                       ;

PostfixExpression : LeftHandSideExpression
                  | LeftHandSideExpression INCREMENT
                  | LeftHandSideExpression DECREMENT
                  ;

UnaryExpression : PostfixExpression
                | DELETE UnaryExpression
                | VOID_SYMBOL UnaryExpression
                | TYPEOF UnaryExpression
                | INCREMENT UnaryExpression
                | DECREMENT UnaryExpression
                | PLUS UnaryExpression
                | MINUS UnaryExpression
                | ONES_COMPLIMENT UnaryExpression
                | LOGICAL_NOT UnaryExpression
                ;

MultiplicativeExpression : UnaryExpression
                         | MultiplicativeExpression MULTIPLY UnaryExpression
                         | MultiplicativeExpression DIV UnaryExpression
                         | MultiplicativeExpression MOD UnaryExpression
                         ;

AdditiveExpression : MultiplicativeExpression
                   | AdditiveExpression PLUS MultiplicativeExpression
                   | AdditiveExpression MINUS MultiplicativeExpression
                   ;

ShiftExpression : AdditiveExpression
                | ShiftExpression BITWISE_SHIFT_LEFT AdditiveExpression
                | ShiftExpression BITWISE_SHIFT_RIGHT AdditiveExpression
                | ShiftExpression BITWISE_SHIFT_RIGHT_ZERO_FILL  AdditiveExpression
                ;

RelationalExpression : ShiftExpression
                     | RelationalExpression LESS_THAN ShiftExpression
                     | RelationalExpression GREATER_THAN ShiftExpression
                     | RelationalExpression LS_EQUAL ShiftExpression
                     | RelationalExpression GT_EQUAL ShiftExpression
                     ;

EqualityExpression : RelationalExpression
                   | EqualityExpression EQUALS RelationalExpression
                   | EqualityExpression NOT_EQUAL RelationalExpression
                   ;

BitwiseANDExpression : EqualityExpression
                     | BitwiseANDExpression BITWISE_AND EqualityExpression
                     ;

BitwiseXORExpression : BitwiseANDExpression
                     | BitwiseXORExpression BITWISE_EXCLUSIVE_OR     BitwiseANDExpression
                     ;

BitwiseORExpression : BitwiseXORExpression
                    | BitwiseORExpression BITWISE_OR BitwiseXORExpression
                    ;

LogicalANDExpression : BitwiseORExpression
                     | LogicalANDExpression LOGICAL_AND BitwiseORExpression
                     ;

LogicalORExpression : LogicalANDExpression
                    | LogicalORExpression LOGICAL_OR LogicalANDExpression
                    ;

ConditionalExpression : LogicalORExpression
                      | LogicalORExpression QUERY AssignmentExpression COLON    AssignmentExpression
                      ;

AssignmentExpression : ConditionalExpression
                     | LeftHandSideExpression AssignmentOperator  AssignmentExpression %prec LOWER_THAN_CLOSE_PARENTHESIS
                     ;

AssignmentOperator : ASSIGN_SYMBOL
                   | MULTIPLY_EQUALS
                   | DIV_EQUALS
                   | MOD_EQUALS
                   | PLUS_EQUALS
                   | MINUS_EQUALS
                   | BITWISE_SHIFT_LEFT_EQUALS
                   | BITWISE_SHIFT_RIGHT_EQUALS
                   | BITWISE_SHIFT_RIGHT_ZERO_FILL_EQUALS
                   | BITWISE_AND_EQUALS
                   | BITWISE_EXCLUSIVE_OR_EQUALS
                   | BITWISE_OR_EQUALS
                   ;

Expression : AssignmentExpression
           | Expression COMMA AssignmentExpression
           ;

OptionalExpression : Expression
                   |
                   ;

%%

;;here something like:
;;(define-lex wisent-java-tags-lexer
;; should go
(define-lex javascript-lexer-jv
"javascript thingy"
;;std stuff
  semantic-lex-ignore-whitespace
  semantic-lex-ignore-newline
  semantic-lex-ignore-comments

  ;;stuff generated from the wy file(one for each "type" declaration)
  wisent-javascript-jv-wy--<number>-regexp-analyzer
  wisent-javascript-jv-wy--<string>-sexp-analyzer

  wisent-javascript-jv-wy--<keyword>-keyword-analyzer

  wisent-javascript-jv-wy--<symbol>-regexp-analyzer
  wisent-javascript-jv-wy--<punctuation>-string-analyzer
  wisent-javascript-jv-wy--<block>-block-analyzer


  ;;;;more std stuff
  semantic-lex-default-action
  )
