nl_tokens: Reads statements
pl_tokens: function ( ) { switch ( this . token ) { case "{" : return this . read_code_block ( false ) ; case this . tok . T_IF : return this . read_if ( ) ; case this . tok . T_SWITCH : return this . read_switch ( ) ; case this . tok . T_FOR : return this . read_for ( ) ; case this . tok . T_FOREACH : return this . read_foreach ( ) ; case this . tok . T_WHILE : return this . read_while ( ) ; case this . tok . T_DO : return this . read_do ( ) ; case this . tok . T_COMMENT : return this . read_comment ( ) ; case this . tok . T_DOC_COMMENT : return this . read_doc_comment ( ) ; case this . tok . T_RETURN : { const result = this . node ( "return" ) ; let expr = null ; if ( ! this . <mask> ( ) . is ( "EOS" ) ) { expr = this . read_expr ( ) ; } this . expectEndOfStatement ( ) ; return result ( expr ) ; } // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L429 case this . tok . T_BREAK : case this . tok . T_CONTINUE : { const result = this . node ( this . token === this . tok . T_CONTINUE ? "continue" : "break" ) ; let level = null ; this . next ( ) ; // look ahead if ( this . token !== ";" ) { level = this . read_expr ( ) ; } this . expectEndOfStatement ( ) ; return result ( level ) ; } case this . tok . T_GLOBAL : { const result = this . node ( "global" ) ; const items = this . next ( ) . read_list ( this . read_simple_variable , "," ) ; this . expectEndOfStatement ( ) ; return result ( items ) ; } case this . tok . T_STATIC : { const current = [ this . token , this . lexer . getState ( ) ] ; const result = this . node ( ) ; if ( this . next ( ) . token === this . tok . T_DOUBLE_COLON ) { // static keyword for a class this . lexer . tokens . push ( current ) ; const expr = this . next ( ) . read_expr ( ) ; this . expectEndOfStatement ( expr ) ; return result ( "expressionstatement" , expr ) ; } if ( this . token === this . tok . T_FUNCTION ) { return this . read_function ( true , [ 0 , 1 , 0 ] ) ; } const items = this . read_variable_declarations ( ) ; this . expectEndOfStatement ( ) ; return result ( "static" , items ) ; } case this . tok . T_ECHO : { const result = this . node ( "echo" ) ; const text = this . text ( ) ; const shortForm = text === "<?=" || text === "<%=" ; const expressions = this . next ( ) . read_list ( this . read_expr , "," ) ; this . expectEndOfStatement ( ) ; return result ( expressions , shortForm ) ; } case this . tok . T_INLINE_HTML : { const value = this . text ( ) ; let prevChar = this . lexer . yylloc . first_offset > 0 ? this . lexer . _input [ this . lexer . yylloc . first_offset - 1 ] : null ; const fixFirstLine = prevChar === "\r" || prevChar === "\n" ; // revert back the first stripped line if ( fixFirstLine ) { if ( prevChar === "\n" && this . lexer . yylloc . first_offset > 1 && this . lexer . _input [ this . lexer . yylloc . first_offset - 2 ] === "\r" ) { prevChar = "\r\n" ; } } const result = this . node ( "inline" ) ; this . next ( ) ; return result ( value , fixFirstLine ? prevChar + value : value ) ; } case this . tok . T_UNSET : { const result = this . node ( "unset" ) ; this . next ( ) . expect ( "(" ) && this . next ( ) ; const variables = this . read_list ( this . read_variable , "," ) ; this . expect ( ")" ) && this . next ( ) ; this . expect ( ";" ) && this . next ( ) ; return result ( variables ) ; } case this . tok . T_DECLARE : { const result = this . node ( "declare" ) ; const body = [ ] ; let mode ; this . next ( ) . expect ( "(" ) && this . next ( ) ; const directives = this . read_declare_list ( ) ; this . expect ( ")" ) && this . next ( ) ; if ( this . token === ":" ) { this . next ( ) ; while ( this . token != this . EOF && this . token !== this . tok . T_ENDDECLARE ) { // @todo : check declare_statement from php / not valid body . push ( this . read_top_statement ( ) ) ; } this . expect ( this . tok . T_ENDDECLARE ) && this . next ( ) ; this . expectEndOfStatement ( ) ; mode = this . ast . declare . MODE_SHORT ; } else if ( this . token === "{" ) { this . next ( ) ; while ( this . token != this . EOF && this . token !== "}" ) { // @todo : check declare_statement from php / not valid body . push ( this . read_top_statement ( ) ) ; } this . expect ( "}" ) && this . next ( ) ; mode = this . ast . declare . MODE_BLOCK ; } else { this . expect ( ";" ) && this . next ( ) ; mode = this . ast . declare . MODE_NONE ; } return result ( directives , body , mode ) ; } case this . tok . T_TRY : return this . read_try ( ) ; case this . tok . T_THROW : { const result = this . node ( "throw" ) ; const expr = this . next ( ) . read_expr ( ) ; this . expectEndOfStatement ( ) ; return result ( expr ) ; } // ignore this (extra ponctuation) case ";" : { this . next ( ) ; return null ; } case this . tok . T_STRING : { const result = this . node ( ) ; const current = [ this . token , this . lexer . getState ( ) ] ; const label = this . text ( ) ; // AST : https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L457 if ( this . next ( ) . token === ":" ) { this . next ( ) ; return result ( "label" , label ) ; } // default fallback expr / T_STRING '::' (etc...) result . destroy ( ) ; this . lexer . tokens . push ( current ) ; const statement = this . node ( "expressionstatement" ) ; const expr = this . next ( ) . read_expr ( ) ; this . expectEndOfStatement ( expr ) ; return statement ( expr ) ; } case this . tok . T_GOTO : { const result = this . node ( "goto" ) ; let label = null ; if ( this . next ( ) . expect ( this . tok . T_STRING ) ) { label = this . text ( ) ; this . next ( ) . expectEndOfStatement ( ) ; } return result ( label ) ; } default : { // default fallback expr const statement = this . node ( "expressionstatement" ) ; const expr = this . read_expr ( ) ; this . expectEndOfStatement ( expr ) ; return statement ( expr ) ; } } }