You should separate each implemented variant on a branch or file before moving on to the next level. Log time you spend on it so we can compare power to weight ratio. Feel free to propose new variants that could serve as good milestones for beginners.
Note that this is a work in progress file. The headings will be renamed. Some of the variants may be removed.
program: <stms> stmBody: { <stms> } stms: <stm> [; <stm>]* stm: if ( <expr> ) <stmBody> else <stmBody> | <expr> expr: <funExpr> | <term> [<op> <term>]? funExpr: ( function ( [<id> [, <id>]* ]? ) { <stms> ; return <expr> } ) ( [ <expr> [, <expr>]* ]? ) term: <int> | <id> op: + | - | '<' int = [0-9]+ id = [a-zA-Z_.]+
program: <statements> statements: <statement> <moreStatements> moreStatements: ';' <statements> | '' statement: 'while(v[i]){' <statements> '}' | [ console.log | document.write ] '(String.fromCharCode(v[i]))' | var ' ' [ v | i | j ] | <assignment> assignment: v [ '=new Array' | '[i]=' [ '(v[i]|0)' [ '+' | '-' ] 1 | 'form.text.value.charCodeAt(j)|0' ] ] | [ i | j ] [ '=0' | '++' | '--' ]
Not supported:
program: <stms> stmBody: { <stms> } stms: <stm> [; <stm>]* stm: while ( <expr> ) <stmBody> | <funExpr> | <id> <iStm> funExpr: function <id> ( ) <stmBody> iStm: '=' <expr> | ( [ <expr> ]? ) expr: <term> [<op> <term>]? term: <int> | <id> op: + | - | '<' int = [0-9]+ id = [a-zA-Z_.]+
program: <stms> stmBody: { <stms> } stms: <stm> [; <stm>]* stm: while ( <expr> ) <stmBody> | <funExpr> | <id> <iStm> funExpr: function <id> ( ) <stmBody> iStm: [ '[' <expr> ']' ]? = <expr> | ( [ <expr> ]? ) expr: <term> [<op> <term>]? term: <int> | new Array | <id> [ '[' <expr> ']' ]? op: + | - | '<' int = [0-9]+ id = [a-zA-Z_.]+
program: <stms> stmBody: { <stms> } stms: <stm> [; <stm>]* stm: while ( <expr> ) <stmBody> | <funExpr> | <id> <iStm> funExpr: function <id> ( ) <stmBody> iStm: <idx> <iRest> idx: [ '[' <expr> ']' | . <id> ]* iRest: = <expr> | ( [ <expr> ]? ) expr: <term> [<op> <term>]? term: <int> | new Array | new Object | <id> [ '[' <expr> ']' ]? op: + | - | '<' int = [0-9]+ id = [a-zA-Z_][a-zA-Z_0-9]*
program: <stms> stmBody: { <stms> } stms: <stm> [; <stm>]* stm: while ( <expr> ) <stmBody> | <funExpr> | <id> <iStm> funExpr: function <id> ( ) <stmBody> iStm: = <expr> | ( [ <expr> ]? ) expr: <term> [<op> <term>]? term: <int> | <string> | <id> op: + | - | & | '|' | '<' int = [0-9]+ string = '([^'])*' id = [a-zA-Z_.]+
program: <stms> stmBody: { <stms> } stms: <stm> [; <stm>]* stm: while ( <expr> ) <stmBody> | <funExpr> | <expr> funExpr: function <id> ( ) <stmBody> expr: <lExpr> | <id> <iExpr> lExpr: <lTerm> [<op> <term>]? iExpr: [<op> <term>]? | = <expr> | ( [ <expr> ]? ) term: <lTerm> | <id> lTerm: <int> | <string> op: + | - | & | '|' | '<' int = [0-9]+ string = '([^'])*' id = [a-zA-Z_.]+
program: <stms> stms: [ <stm> [; <stm>]* ]? stm: if ( <expr> ) <stmBody> [else <stmBody>]? | while ( <expr> ) <stmBody> | <expr> | var <id> stmBody: { <stms> } expr: funExpr | term [<op> <term>]? funExpr: function <id> ( <params> ) { <stms> [ ; return <expr> ]? } params: [ <id> [, <id>]* ]? term: <int> | <string> | ( <expr> ) | <id> = <expr> | <id> ( <args> ) | <id> op: + | - | & | '|' | '<' | == args: [ <expr> [, <expr>]* ]? int = [1-9][0-9]* string = '([^'\\]|\\.)*' id = ([a-zA-Z_][a-zA-Z_0-9]*\.)*[a-zA-Z_][a-zA-Z_0-9]*
program: <stms> stms: [ <stm> [; <stm>]* ]? stm: if ( <expr> ) <stmBody> [else <stmBody>]? | while ( <expr> ) <stmBody> | <expr> stmBody: { <stms> } | <stm> expr: <funExpr> | [ ! ]? term [<op> <term>]? funExpr: function <id> ( <params> ) <funBody> funBody: { <funStm> [; <funStm>]* [ ; return <expr> ]? } funStm: var <id> | <stm> params: [ <id> [, <id>]* ]? term: <int> | <string> | ( <expr> ) | <id> = <expr> | <id> ( <args> ) | <id> op: + | - | & | '|' | '<' | == args: [ <expr> [, <expr>]* ]? int = [1-9][0-9]* string = '([^'\\]|\\.)*' id = ([a-zA-Z_][a-zA-Z_0-9]*\.)*[a-zA-Z_][a-zA-Z_0-9]*
program: <arrId> '=' new Array ';' [ <tstm> ';' ]* <expr> tstm: function <funcId> '(' ')' <body> | <mstm> mstm: if '(' <expr> ')' <body> | while '(' <expr> ')' <body> | <cstm> body: '{' <mstm> [ ';' <mstm> ]* '}' cstm: <builtin> | <funcId> '(' ')' | <arrId> <idx> '=' <expr> | <intId> '=' <expr> expr: <term> [ <op> <term> ]? term: <int> | <intId> | '(' [ 'form.text.value.charCodeAt(' <expr> ')' | <arrId> <idx> | '(' <term> '/' <term> ')' ] '|' '0' ')' idx: '[' <expr> ']' op: '+' | '-' | '*' | '%' | '<' | '>' | '<=' | '>=' | '^' | '|' | '&' | '<<' | '>>' | '>>>' | '===' | '!==' builtin: 'console.log(String.fromCharCode(' <expr> '))' arrId = _ intId = [a-z] funcId = [a-zA-Z_]{2,8} int = [0-9]+
Notes:
program: [ '\'use strict\'' ; [ var [ <arrId> | <intId> ] ; ]* <arrId> '=' new Array ; [ <tstm> ; ]* ]? <expr> [;]? tstm: function <funcId> ( [ A [ , B [ , C [ , D [ , E [ , F [ , G [ , H [ , I [ , J [ , K [ , L [ , M [ , N [ , O [ , P [ , Q [ , R [ , S [ , T [ , U [ , V [ , W [ , X [ , Y [ , Z ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ) <fBody> | <mstm> mstm: if '(' <expr> ')' <mBody> [ else <mBody> ]? | while ( <expr> ) <mBody> | <expr> fstm: if '(' <expr> ')' <fBody> [ else <fBody> ]? | while ( <expr> ) <fBody> | return <expr> | <expr> mBody: { [ <mstm> [ ; <mstm> ]* ]? [;]? } fBody: { [ <fstm> [ ; <fstm> ]* ; ]? return <expr> [;]? } expr: <term> [ <op> <term> ]* | '(' <term> '/' <term> ')' '|' '0' term: <int> | <builtin> | <funcId> '(' [ <expr> [, <expr>]* ]? ')' | [ <intId> | <parId> ] [ <rhs> ]? | <arrId> <idx> <rhs> | '(' [ 'form.text.value.charCodeAt(' <expr> ')|0' | <arrId> <idx> '|0' | <expr> ] ')' rhs: '=' <expr> idx: '[' <expr> ']' op: '+' | '-' | '*' | '%' | '<' | '>' | '<=' | '>=' | '^' | '|' | '&' | '<<' | '>>' | '>>>' | '||' | '&&' | '===' | '!==' builtin: 'console.log(String.fromCharCode(' <expr> '))' arrId = _ intId = [a-z] parId = [A-Z] funcId = [a-zA-Z_][0-9a-zA-Z_]{1,9}[0-9]? int = [0-9]+
Notes:
program: [ '\'use strict\'' ; [ var [ <arrId> | <intId> ] ; ]* <arrId> '=' new Array ; [ <tstm> ; ]* ]? <expr> [;]? tstm: function <funcId> ( [ A [ , B [ , C [ , D [ , E [ , F [ , G [ , H [ , I [ , J [ , K [ , L [ , M [ , N [ , O [ , P [ , Q [ , R [ , S [ , T [ , U [ , V [ , W [ , X [ , Y [ , Z ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ) <fBody> | <mstm> mstm: if '(' <expr> ')' <mBody> [ else <mBody> ]? | while ( <expr> ) <mBody> | do <mBody> while ( <expr> ) | for ( [ <expr> ]? ; [ <expr> ]? ; [ <expr> ]? ) <mBody> | switch ( <expr> ) { [ case <expr>: <mBody> ]* [ default: <mBody> ]? } | <cstm> fstm: if '(' <expr> ')' <fBody> [ else <fBody> ]? | while ( <expr> ) <fBody> | do <fBody> while ( <expr> ) | for ( [ <expr> ]? ; [ <expr> ]? ; [ <expr> ]? ) <fBody> | switch ( <expr> ) { [ case <expr>: <fBody> ]* [ default: <fBody> ]? } | return <expr> | <cstm> cstm: break | continue | <expr> mBody: { [ <mstm> [ ; <mstm> ]* ]? [;]? } fBody: { [ <fstm> [ ; <fstm> ]* ; ]? return <expr> [;]? } expr: <qexpr> [ '?' <qexpr> ':' <qexpr> ]? qexpr: <uterm> [ [ <opRel> <uterm> ]* ]? | '(' <uterm> '/' <uterm> ')' '|' '0' uterm: [ '++' | '--' ] [ <intId> | <parId> | <arrId> <idx> ] | [ [ '!' | '~' | '-' ]? <term> ] term: <int> | <builtin> | <funcId> '(' [ <expr> [, <expr>]* ]? ')' | [ <intId> | <parId> ] [ <rhs> ]? | <arrId> <idx> <rhs> | <bracketed> bracketed: '(' [ 'form.text.value.charCodeAt(' <expr> ')|0' | <arrId> <idx> '|0' | <expr> [ ',' <expr> ]* ] ')' rhs: '++' | '--' | [ <op> ]? '=' <expr> idx: '[' <expr> ']' op: '+' | '-' | '*' | % | ^ | '|' | '&' | '<<' | '>>' | '>>>' | '||' | '&&' opRel: <op> | '<' | '>' | '<=' | '>=' | '===' | '!==' builtin: 'console.log(String.fromCharCode(' <expr> '))' arrId = _ intId = [a-z] parId = [A-Z] funcId = [a-zA-Z_][0-9a-zA-Z_]{1,9}[0-9]? int = [0-9]+
Notes:
program: [ '\'use strict\'' ; [ var [ <arrId> | <intId> | <constInit> ] ; ]* <arrId> '=' new Array ; [ <tstm> ; ]* ]? <expr> [;]? constInit: <constId> '=' <cexpr> | <strId> '=' <string> | <litArrId> '=' '[' [ <cexpr> [ ',' <cexpr> ]* ]? ']' tstm: function <funcId> ( [ A [ , B [ , C [ , D [ , E [ , F [ , G [ , H [ , I [ , J [ , K [ , L [ , M [ , N [ , O [ , P [ , Q [ , R [ , S [ , T [ , U [ , V [ , W [ , X [ , Y [ , Z ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ]? ) <fBody> | <mstm> mstm: if '(' <expr> ')' <mBody> [ else <mBody> ]? | while ( <expr> ) <mBody> | do <mBody> while ( <expr> ) | for ( [ <expr> ]? ; [ <expr> ]? ; [ <expr> ]? ) <mBody> | switch ( <expr> ) { [ case <expr>: <mBody> ]* [ default: <mBody> ]? } | <cstm> fstm: if '(' <expr> ')' <fBody> [ else <fBody> ]? | while ( <expr> ) <fBody> | do <fBody> while ( <expr> ) | for ( [ <expr> ]? ; [ <expr> ]? ; [ <expr> ]? ) <fBody> | switch ( <expr> ) { [ case <expr>: <fBody> ]* [ default: <fBody> ]? } | return <expr> | <cstm> cstm: break | continue | <expr> mBody: { [ <mstm> [ ; <mstm> ]* ]? [;]? } fBody: { [ <fstm> [ ; <fstm> ]* ; ]? return <expr> [;]? } expr: [ [ '!' | '~' | '-' ]? <term> ] [ '?' <expr> ':' <expr> | [ <opRel> <term> ]* ]? | '(' <term> '/' <term> ')' '|' '0' term: <int> | <builtin> | [ <strId> | <litArrId> ] '.length' | <funcId> '(' [ <expr> [, <expr>]* ]? ')' | <constId> | [ <intId> | <parId> ] [ <rhs> ]? | <arrId> <idx> <rhs> | <bracketed> bracketed: '(' [ [ 'form.text.value' | <strId> ] '.charCodeAt(' <expr> ')|0' | [ <arrId> | <litArrId> ] <idx> '|0' | <expr> [ ',' <expr> ]* ] ')' cexpr: [ [ '!' | '~' | '-' ]? <cterm> ] [ '?' <cexpr> ':' <cexpr> | [ <opRel> <cterm> ]* ]? | '(' <cterm> '/' <cterm> ')' '|' '0' cterm: <int> | [ <strId> | <litArrId> ] '.length' | <constId> | <cbracketed> cbracketed: '(' [ <strId> '.charCodeAt(' <cexpr> ')|0' | <litArrId> <idx> '|0' | <cexpr> ] ')' rhs: '++' | '--' | [ <op> ]? '=' <expr> idx: '[' <expr> ']' op: '+' | '-' | '*' | '%' | '^' | '|' | '&' | '<<' | '>>' | '>>>' | '||' | '&&' opRel: <op> | '<' | '>' | '<=' | '>=' | '===' | '!==' builtin: 'console.log(String.fromCharCode(' <expr> '))' arrId = _ intId = [a-z] parId = [A-Z] constId = [A-Z][0-9a-zA-Z_]{1,9}[0-9]? strId = _s[0-9a-zA-Z_]{1,10}[0-9]? litArrId = _a[0-9a-zA-Z_]{1,10}[0-9]? funcId = [a-z][0-9a-zA-Z_]{1,9}[0-9]? string = '[^'\\]*'|"[^"\\]*" int = [0-9]+
Notes:
program: <stms> stms: [ <stm> [; <stm>]* ]? stm: if ( <expr> ) <stmBody> [else <stmBody>]? | while ( <expr> ) <stmBody> | <expr> stmBody: { <stms> } | <stm> expr: <funExpr> | [ ! ]? term [<op> <term>]? funExpr: function <id> ( <params> ) <funBody> funBody: { <funStm> [; <funStm>]* [ ; return <expr> ]? } funStm: var <id> | <stm> params: [ <id> [, <id>]* ]? term: <int> | <string> | new <id> | ( <expr> ) | <id> <idx> [ <iTerm> ]? iTerm: = <expr> | ( <args> ) idx: [ '[' <expr> ']' | . <id> ]* op: + | - | & | '|' | '<' | == args: [ <expr> [, <expr>]* ]? int = [1-9][0-9]* string = '([^'\\]|\\.)*' id = [a-zA-Z_][a-zA-Z_0-9]*
program: <stms> [;]? stmBody: { <stms> [;]? } stms: [ <stm> [; <stm>]* ]? stm: if ( <expr> ) <stmBody> [ else <stmBody> ]? | while ( <expr> ) <stmBody> | try <stmBody> catch ( <id> ) <stmBody> | var <id> | function <function> | <expr> function: <id> ( [ <id> [, <id>]* ]? ) { <stms> [ ; return <expr> ]? [;]? } expr: <term> [ <op> <term> ]? term: undefined | null | <int> | <string> | new <id> | [ ! ]? <id> <idx> [ <iTerm> ]? iTerm: '=' <expr> | ( [ <expr> [, <expr>]* ]? ) idx: [ '[' <expr> ']' | . <id> ]* op: + | - | '|' | & | '>>' | '<' | === | == int = -?[1-9][0-9]* string = '[^'\\]*'|"[^"\\]*" id = [a-zA-Z_][a-zA-Z_0-9]*
program: <stms> [;]? stmBody: { <stms> [;]? } stms: [ <stm> [; <stm>]* ]? stm: while ( <expr> ) <stmBody> | function <function> | <expr> function: <id> ( ) <stmBody> expr: <iTerm> <eExpr> | <lTerm> <eExpr> eExpr: [ <op> <term> ]? term: <iTerm> | <lTerm> lTerm: <int> | <string> | ! <id> <sTerm> iTerm: new <id> | <id> <sTerm> sTerm: <idx> [ <rhs> ]? rhs: '=' <expr> | ( [ <expr> ]? ) idx: [ '[' <expr> ']' | . <id> ]? op: + | - | '<' int = [1-9][0-9]* string = '[^'\\]*'|"[^"\\]*" id = [a-zA-Z_][a-zA-Z_0-9]*
program: <stms> [;]? stmBody: { <stms> [;]? } stms: [ <stm> [; <stm>]* ]? stm: while ( <expr> ) <stmBody> | function <function> | return <expr> | <expr> function: <id> ( ) <stmBody> expr: <iTerm> <eExpr> | <lTerm> <eExpr> eExpr: [ <op> <term> ]? term: <iTerm> | <lTerm> lTerm: <int> | <string> | ! <id> <sTerm> iTerm: undefined | new <id> | <id> <sTerm> sTerm: <idx> [ <rhs> ]? rhs: '=' <expr> | ( [ <expr> ]? ) idx: [ '[' <expr> ']' | . <id> ]? op: + | - | '<' | '===' int = [1-9][0-9]* string = '[^'\\]*'|"[^"\\]*" id = [a-zA-Z_][a-zA-Z_0-9]*
program: <stms> [;]? stmBody: { <stms> [;]? } stms: [ <stm> [; <stm>]* ]? stm: while ( <expr> ) <stmBody> | function <id> ( [ <id> ]? ) <stmBody> | return <expr> | <expr> expr: <term> [ <op> <term> ]? op: + | - | '<' | '===' term: <int> | <string> | undefined | new <cls> | [ '!' ]? <id> <idx> <rhs> cls: Object idx: [ '[' <expr> ']' | . <id> ]? rhs: [ '=' <expr> | ( [ <expr> ]? ) ]? int = [1-9][0-9]* string = '[^'\\]*'|"[^"\\]*" id = [a-zA-Z_][a-zA-Z_0-9]*
program: <stms> [;]? stmBody: { <stms> [;]? } stms: [ <stm> [; <stm>]* ]? stm: while ( <expr> ) <stmBody> | var <id> | function <id> ( [ <id> ]? ) <stmBody> | return <expr> | try <stmBody> catch ( <id> ) <stmBody> | throw <expr> | <expr> expr: <term> [ <op> <term> ]? op: + | - | '<' | '===' term: <int> | <string> | undefined | new <cls> | [ '!' ]? <id> <idx> <rhs> cls: Object idx: [ '[' <expr> ']' | . <id> ]? rhs: [ '=' <expr> | ( [ <expr> ]? ) ]? int = [1-9][0-9]* string = '[^'\\]*'|"[^"\\]*" id = [a-zA-Z_][a-zA-Z_0-9]*
program: <stms> stmBody: { <stms> } stms: [ [ <stmu> ; | <stmb> [;]? ]* [ <stmu> | <stmb> ] [;]? ]* stmu: var <id> | return <expr> | throw <expr> | <expr> stmb: if ( <expr> ) <stmBody> [ else <stmBody> ]? | while ( <expr> ) <stmBody> | function <id> ( [ <id> ]? ) <stmBody> | try <stmBody> catch ( <id> ) <stmBody> expr: <term> [ <op> <term> ]? op: + | - | '|' | & | '>>' | '<' | === | == term: <int> | <string> | undefined | null | new <cls> | [ '!' ]? <id> <idx> <rhs> cls: Object | Array idx: [ '[' <expr> ']' | . <id> ]? rhs: [ '=' <expr> | ( [ <expr> ]? ) ]? int = -?[1-9][0-9]* string = '[^'\\]*'|"[^"\\]*" id = [a-zA-Z_][a-zA-Z_0-9]*
program: <stms> [;]? stmBody: { <stms> [;]? } stms: [ <stm> [; <stm>]* ]? stm: if ( <expr> ) <stmBody> [ else <stmBody> ]? | while ( <expr> ) <stmBody> | var <id> | function <function> | return <expr> | try <stmBody> catch ( <id> ) <stmBody> | throw <expr> | <expr> function: <id> ( [ <id> [, <id>]* ]? ) <stmBody> expr: <iTerm> <eExpr> | <lTerm> <eExpr> eExpr: [ <op> <term> ]? term: <iTerm> | <lTerm> lTerm: <int> | <string> | ! <id> <sTerm> iTerm: undefined | null | new <id> | <id> <sTerm> sTerm: <idx> [ <rhs> ]? rhs: '=' <expr> | ( [ <expr> [, <expr>]* ]? ) idx: [ '[' <expr> ']' | . <id> ]? op: + | - | '|' | & | '>>' | '<' | === | == int = -?[1-9][0-9]* string = '[^'\\]*'|"[^"\\]*" id = [a-zA-Z_][a-zA-Z_0-9]*
program: <stms> [;]? stmBody: <stmBrace> | <stm> stmBrace: { <stms> [;]? } stms: [ <stm> [; <stm>]* ]? stm: if ( <expr> ) <stmBody> [ else <stmBody> ]? | while ( <expr> ) <stmBody> | var <id> [ '=' <expr> ]? | function <id> <function> | return <expr> | try <stmBrace> catch ( <id> ) <stmBrace> | throw <expr> | <expr> expr: function <function> | <iTerm> <eExpr> | <lTerm> <eExpr> function: ( [ <id> [, <id>]* ]? ) <stmBrace> eExpr: [ <op> <term> ]? term: <iTerm> | <lTerm> lTerm: <int> | <string> | ! <term> | ~ <term> | '(' <expr> ')' iTerm: undefined | null | new Object | new Array | <id> <sTerm> sTerm: <idx> [ <rhs> ]? rhs: '=' <expr> | ( [ <expr> [, <expr>]* ]? ) idx: [ '[' <expr> ']' | . <id> ]? op: + | - | '*' | / | % | '<' | '>' | '<=' | '>=' | ^ | '|' | '&' | '<<' | '>>' | '||' | '&&' | === | !== int = -?[1-9][0-9]* string = '[^'\\]*'|"[^"\\]*" id = [a-zA-Z_][a-zA-Z_0-9]*
program: <stms> [;]? stmBody: <stmBrace> | <stm> stmBrace: { <stms> [;]? } stms: [ <stm> [; <stm>]* ]? stm: if ( <expr> ) <stmBody> [ else <stmBody> ]? | while ( <expr> ) <stmBody> | for ( <id> in <expr> ) <stmBody> | var <id> [ '=' <expr> ]? | function <id> <function> | return <expr> | try <stmBrace> catch ( <id> ) <stmBrace> | throw <expr> | <expr> expr: function <function> | <iTerm> <eExpr> | <lTerm> <eExpr> function: ( [ <id> [, <id>]* ]? ) <stmBrace> eExpr: [ <op> <term> ]* term: <iTerm> | <lTerm> lTerm: <int> | <string> | [ ! | ~ | - ] <term> | '(' <expr> ')' [ <args> ]? iTerm: undefined | null | NaN | new Object | new Array | new Date | typeof <expr> | <id> <sTerm> sTerm: <idx> [ <rhs> ]? rhs: '=' <expr> | <args> args: '(' [ <expr> [, <expr>]* ]? ')' idx: [ '[' <expr> ']' | . <id> ]* op: + | - | '*' | / | % | '<' | '>' | '<=' | '>=' | ^ | '|' | '&' | '<<' | '>>' | '>>>' | '||' | '&&' | === | !== int = -?[1-9][0-9]* string = '[^'\\]*'|"[^"\\]*" id = [a-zA-Z_][a-zA-Z_0-9]*
Notes:
program: <stms> stms: [ <stm> [; <stm>]* [;]? ]? stmBody: <stmBrace> | <stm> stmBrace: { <stms> } stm: if ( <expr> ) <stmBody> [ else <stmBody> ]? | while ( <expr> ) <stmBody> | do <stmBody> while ( <expr> ) | delete <id> <idx> | <goto> | <expr> goto: try <stmBrace> catch ( <id> ) <stmBrace> | throw <expr> | return <expr> | break | continue | switch ( <expr> ) { [ case <lit>: <stms> ]* [ default: <stms> ]? } expr: <funExpr> | <uTerm> [ '?' <expr> : <expr> | <op> <uTerm> ]? funExpr: function [ <id> ]? ( [ <id> [, <id>]* ]? ) { <funStm> [; <funStm>]* [;]? } funStm: var <varInit> [, <varInit> ]* | <stm> varInit: <id> [ '=' <expr> ]? uTerm: [ ! | ~ | - ]? <term> term: <lit> | new <id> [ <args> ]? | typeof <id> <idx> | ( <expr> ) [ <args> ]? | <id> <idx> [ <iTerm> ]? lit: undefined | null | <num> | <string> iTerm: '=' <expr> | <args> | instanceof <id> idx: [ '[' <expr> ']' | . <id> ]* op: + | - | '*' | / | % | '<' | '>' | '<=' | '>=' | ^ | '|' | '&' | '<<' | '>>' | '>>>' | '||' | '&&' | === | !== | == | != args: ( [ <expr> [, <expr>]* ]? ) num: <double> | <int> double = -?[1-9][0-9]*\.[0-9]+ | NaN int = (-?[1-9][0-9]*|0x[0-9a-fA-F]+) string = '([^'\\]|\\n|\\t|\\.)*'|"([^"\\]|\\n|\\t|\\.)*" id = [a-zA-Z_][a-zA-Z_0-9]*