/*!
* Copyright (C) 2017 Glayzzle (BSD3 License)
* @authors https://github.com/glayzzle/php-parser/graphs/contributors
* @url http://glayzzle.com
*/
module.exports = {
T_CONSTANT_ENCAPSED_STRING: function() {
var ch;
while(this.offset < this.size) {
ch = this.input();
if (ch == '\\') {
this.input();
} else if (ch == '\'') {
break;
}
}
return this.tok.T_CONSTANT_ENCAPSED_STRING;
},
// check if matching a HEREDOC state
is_HEREDOC: function() {
var revert = this.offset;
Eif (
this._input[this.offset - 1] === '<'
&& this._input[this.offset] === '<'
&& this._input[this.offset + 1] === '<'
) {
this.offset += 3;
// optional tabs / spaces
if (this.is_TABSPACE()) {
while(this.offset < this.size) {
this.offset ++;
if (!this.is_TABSPACE()) {
break;
}
}
}
// optional quotes
var tChar = this._input[this.offset - 1];
if (tChar === '\'' || tChar === '"') {
this.offset ++;
} else {
tChar = null;
}
// required label
Eif (this.is_LABEL_START()) {
var yyoffset = this.offset - 1;
while(this.offset < this.size) {
this.offset++;
if (!this.is_LABEL()) {
break;
}
}
var yylabel = this._input.substring(yyoffset, this.offset - 1);
Eif (!tChar || tChar === this._input[this.offset - 1]) { // required ending quote
if (tChar) this.offset ++;
// require newline
Eif (this._input[this.offset - 1] === '\r' || this._input[this.offset - 1] === '\n') {
// go go go
this.heredoc_label = yylabel;
yyoffset = this.offset - revert;
this.offset = revert;
this.consume(yyoffset);
if (tChar === '\'') {
this.begin('ST_NOWDOC');
} else {
this.begin('ST_HEREDOC');
}
return this.tok.T_START_HEREDOC;
}
}
}
}
this.offset = revert;
return false;
},
ST_DOUBLE_QUOTES: function() {
var ch;
while(this.offset < this.size) {
ch = this.input();
if (ch == '\\') {
this.input();
} else if (ch == '"') {
break;
} else if (ch == '$') {
ch = this.input();
if ( ch == '{' || this.is_LABEL_START()) {
this.unput(2);
break;
}
this.unput(1);
} else if (ch == '{') {
ch = this.input();
if (ch == '$') {
this.unput(2);
break;
}
this.unput(1);
}
}
if (ch == '"') {
return this.tok.T_CONSTANT_ENCAPSED_STRING;
} else {
var prefix = 1;
if (this.yytext[0] === 'b' || this.yytext[0] === 'B') {
prefix = 2;
}
if (this.yytext.length > 2) {
this.appendToken(
this.tok.T_ENCAPSED_AND_WHITESPACE,
this.yytext.length - prefix
);
}
this.unput(this.yytext.length - prefix);
this.begin("ST_DOUBLE_QUOTES");
return this.yytext;
}
},
// check if its a DOC end sequence
isDOC_MATCH: function() {
// @fixme : check if out of text limits
if (this._input.substring(this.offset - 1, this.offset - 1 + this.heredoc_label.length) === this.heredoc_label) {
var ch = this._input[this.offset - 1 + this.heredoc_label.length];
Eif (ch === '\n' || ch === '\r' || ch === ';') {
return true;
}
}
return false;
},
matchST_NOWDOC: function() {
/** edge case : empty now doc **/
Iif (this.isDOC_MATCH()) {
// @fixme : never reached (may be caused by quotes)
this.consume(this.heredoc_label.length);
this.popState();
return this.tok.T_END_HEREDOC;
}
/** SCANNING CONTENTS **/
var ch = this._input[this.offset - 1];
while(this.offset < this.size) {
if (ch === '\n' || ch === '\r') {
ch = this.input();
if (this.isDOC_MATCH()) {
this.unput(1).popState();
this.appendToken(
this.tok.T_END_HEREDOC, this.heredoc_label.length
);
return this.tok.T_ENCAPSED_AND_WHITESPACE;
}
} else {
ch = this.input();
}
}
// too bad ! reached end of document (will get a parse error)
return this.tok.T_ENCAPSED_AND_WHITESPACE;
},
matchST_HEREDOC: function() {
/** edge case : empty here doc **/
var ch = this.input();
if (this.isDOC_MATCH()) {
this.consume(this.heredoc_label.length - 1);
this.popState();
return this.tok.T_END_HEREDOC;
}
/** SCANNING CONTENTS **/
while(this.offset < this.size) {
if (ch === '\\') {
ch = this.input(); // ignore next
Eif (ch !== '\n' && ch !== '\r') {
ch = this.input();
}
}
if (ch === '\n' || ch === '\r') {
ch = this.input();
if (this.isDOC_MATCH()) {
this.unput(1).popState();
this.appendToken(
this.tok.T_END_HEREDOC, this.heredoc_label.length
);
return this.tok.T_ENCAPSED_AND_WHITESPACE;
}
} else if (ch === '$') {
ch = this.input();
if (ch === '{') {
// start of ${
this.begin('ST_LOOKING_FOR_VARNAME');
Eif (this.yytext.length > 2) {
this.appendToken(this.tok.T_DOLLAR_OPEN_CURLY_BRACES, 2);
this.unput(2);
return this.tok.T_ENCAPSED_AND_WHITESPACE;
}else {
return this.tok.T_DOLLAR_OPEN_CURLY_BRACES;
}
} else Eif (this.is_LABEL_START()) {
// start of $var...
var yyoffset = this.offset;
var next = this.consume_VARIABLE();
Eif (this.yytext.length > this.offset - yyoffset + 2) {
this.appendToken(next, this.offset - yyoffset + 2);
this.unput(this.offset - yyoffset + 2);
return this.tok.T_ENCAPSED_AND_WHITESPACE;
} else {
return next;
}
//console.log(this.yytext);
}
} else if (ch === '{') {
ch = this.input();
Eif (ch === '$') {
// start of {$...
this.begin('ST_IN_SCRIPTING');
Iif (this.yytext.length > 2) {
this.appendToken(this.tok.T_CURLY_OPEN, 1);
this.unput(2);
return this.tok.T_ENCAPSED_AND_WHITESPACE;
} else {
this.unput(1);
return this.tok.T_CURLY_OPEN;
}
}
} else {
ch = this.input();
}
}
// too bad ! reached end of document (will get a parse error)
return this.tok.T_ENCAPSED_AND_WHITESPACE;
},
consume_VARIABLE: function() {
this.consume_LABEL();
ch = this.input();
if (ch == '[') {
this.unput(1);
this.begin('ST_VAR_OFFSET');
return this.tok.T_VARIABLE;
} else if (ch === '-') {
if (this.input() === '>') {
this.input();
Eif (this.is_LABEL_START()) {
this.begin('ST_LOOKING_FOR_PROPERTY');
}
this.unput(3);
return this.tok.T_VARIABLE;
} else {
this.unput(2);
}
} else {
this.unput(1);
}
return this.tok.T_VARIABLE;
},
// HANDLES BACKQUOTES
matchST_BACKQUOTE: function() {
var ch = this.input();
if (ch === '$') {
ch = this.input();
if (ch === '{') {
this.begin('ST_LOOKING_FOR_VARNAME');
return this.tok.T_DOLLAR_OPEN_CURLY_BRACES;
} else if (this.is_LABEL_START()) {
var tok = this.consume_VARIABLE();
return tok;
}
} else if (ch === '{') {
if (this._input[this.offset] === '$') {
this.begin('ST_IN_SCRIPTING');
return this.tok.T_CURLY_OPEN;
}
} else if (ch === '`') {
this.popState();
return '`';
}
// any char
while(this.offset < this.size) {
if (ch === '\\') {
this.input();
} else if (ch === '`') {
this.unput(1);
this.popState();
this.appendToken('`', 1);
break;
} else if (ch === '$') {
ch = this.input();
if (ch === '{') {
this.begin('ST_LOOKING_FOR_VARNAME');
Eif (this.yytext.length > 2) {
this.appendToken(this.tok.T_DOLLAR_OPEN_CURLY_BRACES, 2);
this.unput(2);
return this.tok.T_ENCAPSED_AND_WHITESPACE;
}else {
return this.tok.T_DOLLAR_OPEN_CURLY_BRACES;
}
} else if (this.is_LABEL_START()) {
// start of $var...
var yyoffset = this.offset;
var next = this.consume_VARIABLE();
Eif (this.yytext.length > this.offset - yyoffset + 2) {
this.appendToken(next, this.offset - yyoffset + 2);
this.unput(this.offset - yyoffset + 2);
return this.tok.T_ENCAPSED_AND_WHITESPACE;
} else {
return next;
}
}
this.unput(1);
} else if (ch === '{') {
ch = this.input();
if (ch === '$') {
// start of {$...
this.begin('ST_IN_SCRIPTING');
Eif (this.yytext.length > 2) {
this.appendToken(this.tok.T_CURLY_OPEN, 1);
this.unput(2);
return this.tok.T_ENCAPSED_AND_WHITESPACE;
} else {
this.unput(1);
return this.tok.T_CURLY_OPEN;
}
}
this.unput(1);
}
ch = this.input();
}
return this.tok.T_ENCAPSED_AND_WHITESPACE;
},
matchST_DOUBLE_QUOTES: function() {
var ch = this.input();
if (ch === '$') {
ch = this.input();
if (ch === '{') {
this.begin('ST_LOOKING_FOR_VARNAME');
return this.tok.T_DOLLAR_OPEN_CURLY_BRACES;
} else Eif (this.is_LABEL_START()) {
var tok = this.consume_VARIABLE();
return tok;
}
} else if (ch === '{') {
Eif (this._input[this.offset] === '$') {
this.begin('ST_IN_SCRIPTING');
return this.tok.T_CURLY_OPEN;
}
} else if (ch === '"') {
this.popState();
return '"';
}
// any char
while(this.offset < this.size) {
if (ch === '\\') {
this.input();
} else if (ch === '"') {
this.unput(1);
this.popState();
this.appendToken('"', 1);
break;
} else if (ch === '$') {
ch = this.input();
if (ch === '{') {
this.begin('ST_LOOKING_FOR_VARNAME');
Eif (this.yytext.length > 2) {
this.appendToken(this.tok.T_DOLLAR_OPEN_CURLY_BRACES, 2);
this.unput(2);
return this.tok.T_ENCAPSED_AND_WHITESPACE;
}else {
return this.tok.T_DOLLAR_OPEN_CURLY_BRACES;
}
} else Eif (this.is_LABEL_START()) {
// start of $var...
var yyoffset = this.offset;
var next = this.consume_VARIABLE();
Eif (this.yytext.length > this.offset - yyoffset + 2) {
this.appendToken(next, this.offset - yyoffset + 2);
this.unput(this.offset - yyoffset + 2);
return this.tok.T_ENCAPSED_AND_WHITESPACE;
} else {
return next;
}
}
this.unput(1);
} else if (ch === '{') {
ch = this.input();
if (ch === '$') {
// start of {$...
this.begin('ST_IN_SCRIPTING');
Eif (this.yytext.length > 2) {
this.appendToken(this.tok.T_CURLY_OPEN, 1);
this.unput(2);
return this.tok.T_ENCAPSED_AND_WHITESPACE;
} else {
// @fixme : yytext = '"{$' (this.yytext.length > 3)
this.unput(1);
return this.tok.T_CURLY_OPEN;
}
}
Eif (ch) this.unput(1);
}
ch = this.input();
}
return this.tok.T_ENCAPSED_AND_WHITESPACE;
}
};
|