JavaScript Grammar

Thanks to JavaScript: The Good Parts by Douglas Crockford. Copyright 2008 Yahoo! Inc., 978–0–596–51774–8 for the railroad diagrams.

Whitespace

<whitespace> ::= 
              | <space>
              | <tab>
              | <line-end>
              | <comment>

<comment-> ::= // <any-char-no-le> <line-end>
             | /* <block-comment>

<any-char-no-le> ::= 
                   | <any-char-except-line-end> <any-char-no-le-seq>

<block-comment> ::= <any-character-except-*-and-/> <block-comment>
                | <more-/>

<more-/> ::= / <any-character-except-*-and-/> <block-comment>
             | / <more-/>

<more-*> ::= * <any-character-except-*-and-/> <block-comment>
             | * <more-*>
             | * /

Names

<name> ::= <letter> <rest-of-name>

<rest-of-name> ::= <letter> <rest-of-name>
                 | <digit> <rest-of-name>
                 | _ <rest-of-name>

Numbers

<number-literal> ::= <integer> <fraction-opt> <exponent-opt>

<fraction-opt> ::= 
                 | <fraction>

<exponent-opt> ::=
                 | <exponent>

<integer> ::= 0
            | <no-zero> <dig-seq>

<no-zero> ::= 1 
            | 2 
            | 3 
            | 4 
            | 5 
            | 6 
            | 7 
            | 8 
            | 9 

<digit> ::= 0 
          | <no-zero>

<dig-seq> ::= 
            | <digit> <dig-seq>

<fraction> ::= . <dig-seq>

<exponent> ::= <e-option> <sign-option> <digit> <dig-seq>

<es> ::= e | E

<sign-options> ::= 
                 | + 
                 | -

Strings

<string-literal> ::= ""
                   | ''
                   | <double-quote-choice>
                   | <single-quote-choice>

<double-quote-choice> ::= <except-"-\-control-char> "
                        | <except-"-\-control-char> <double-quote-choice>
                        | <escaped-character> <double-quote-choice>

<single-quote-choice> ::= <except-'-\-control-char>
                        | <except-"-\-control-char> <single-quote-choice>
                        | <escaped-character> <single-quote-choice>

<escaped-character> ::= \ <escaped-char-options>

<escaped-char-options> ::= "" 
                         | ' 
                         | \ 
                         | / 
                         | b 
                         | f 
                         | n 
                         | r 
                         | t 
                         | <hex>

<hex> ::= u <four-dex-digits>

Statements

<var-statements> ::=
                   | <var-statements> <var-statement>

<var-statement> ::= var <vardec-list> ;

<vardec-list> ::= <vardec>
                | <vardec-list> , <var-dec>

<vardec> ::= <name> = <expression>
           | <name>

<statements> ::=
               | <expression-statement> <statements>
               | <disruptive-statement> <statements>
               | <try-statement> <statements>
               | <if-statement> <statements>
               | <name> : <switch-statement> <statements>
               | <name> : <while-statement> <statements>
               | <name> : <for-statement> <statements>
               | <name> : <do-statement> <statements>

<disruptive-statement> ::= <break-statement>
                         | <return-statement>
                         | <throw-statement>

<block> ::= { }
          | { <statements> }

<if-statement> ::= if ( <expression> ) <block>
                 | if ( <expression> ) <block> else <block>
                 | if ( <expression> ) <block> else <if-statement>

<switch-statement> ::= switch ( <expression> ) { <switch-body> }

<switch-body> ::= <case-clause>
                | <case-disruptive-list> <case-clause>
                | <case-disruptive-list> <default-clause>

<case-disruptive> ::= <case-disruptive-list> <disruptive-statement>

<case-disruptive-list> ::= <case-disruptive>
                         | <case-disruptive> <case-disruptive-list>

<default-clause> ::= default : <statements>

<case-clause> ::= <case-exp-list> <statements>

<case-exp-list> ::= case <expression> :
                  | case <expression> : <case-exp-list> 

<while-statement> ::= while ( <expression ) <block>

<for-statement> ::= for ( <name> in <expression> ) <block>

<for-statement> ::= for ( <expression-statement-opt> ;
                          <expression-opt> ;
                          <expression-statement-opt> )
                      <block>

<expression-statement-opt> ::=
                             | <expression-statement>

<expression-opt> ::=
                   | <expression>

<do-statement> ::= do <block> while ( <expression> ) ;

<try-statement> ::= try <block> catch ( <name> ) <block>

<throw-statement> ::= throw <expression> ;

<return-statement> ::= return ;
                     | return <expression> ;

<break-statement> ::= break ;
                    | break <name> ;

<expression-statement> ::= delete <expression> <refinement>
                         | <expression-statement-loop>


<expression-statement-loop> ::= name <name-follow>

<name-follow> ::= <assign-vals>
                | <increment/decrement>
                | <invocation-loop>
                | <refinement-loop>

<assign-vals> ::= = <expression>
                | = <expression-statement-loop>

<increment/decrement> ::= += <expression>
                        | -= <expression>

<refinement-loop> ::= <refinement> <name-follow>

<invocation-loop> ::= <invocation-nelist>
                    | <invocation-nelist> <refinement-loop>

<invocation-nelist> ::= <invocation>
                     | <invocation> <invocation-nelist>

Expressions

<expression> ::= <literal>
               | <name>
               | ( <expression )
               | <prefix-operator> <expression>
               | <expression> <infix-operator> <expression>
               | <expression> ? <expression> : <expression>
               | <expression> <invocation>
               | <expression> <refinement>
               | new <expression> <invocation?
               | delete <expression> <refinement>

<prefix-operator> ::= typeof
                    | +
                    | -
                    | !

<infix-operator> ::= *
                   | /
                   | %
                   | +
                   | -
                   | >=
                   | <=
                   | >
                   | <
                   | ===
                   | !==
                   | ||
                   | &&

<invocation> ::= ()
                | ( <expression-nelist> )

<expression-nelist> ::= <expression>
                      | <expression> , <expression-nelist>

<refinement> ::= . <name>
               | [ <expression> ]

Literals

<literal> ::= <number-literal>
            | <string-literal>
            | <object-literal>
            | <array-literal>
            | <function>
            | <regexp-literal>

<object-literal> ::= {}
                   | { <fields> }

<field> ::= <name> : <expression
          | <string> : <expression>

<fields> ::= <field>
           | <field> , <fields>

<array-literal> ::= []
                  | [ <expression-nelist> ]

<regexp-literal> ::= / <regexp-choice> / <opt-g> <opt-i> <opt-m>

<opt-g> ::=
          | g

<opt-g> ::=
          | i

<opt-g> ::=
          | m

<funcion-literal> ::= function <parameters> <function-body>
                    | function <name> <parameters> <function-body>

<parameters> ::= ()
               | ( <name-nelist> )

<name-nelist> ::= <name>
                | <name> ,  <name-nelist>

<function-body> ::= { <var-statements> <statements> }