/*!
* Copyright (C) 2017 Glayzzle (BSD3 License)
* @authors https://github.com/glayzzle/php-parser/graphs/contributors
* @url http://glayzzle.com
*/
var lexer = require('./lexer');
var parser = require('./parser');
var tokens = require('./tokens');
var AST = require('./ast');
/**
* @private combine structures
*/
function combine(src, to) {
var keys = Object.keys(src);
var i = keys.length;
while (i--) {
var k = keys[i];
var val = src[k];
Iif (val === null) {
delete to[k];
} else Iif (typeof val === 'function') {
to[k] = val.bind(to);
} else Iif (Array.isArray(val)) {
to[k] = Array.isArray(to[k]) ? to[k].concat(val) : val;
} else if (typeof val === 'object') {
to[k] = typeof to[k] === 'object' ? combine(val, to[k]) : val;
} else {
to[k] = val;
}
}
return to;
}
/**
* Initialise a new parser instance with the specified options
*
* Usage :
* ```js
* var parser = require('php-parser');
* var instance = new parser({
* parser: {
* extractDoc: true,
* suppressErrors: true
* },
* ast: {
* withPositions: true
* },
* lexer: {
* short_tags: true,
* asp_tags: true
* }
* });
*
* var evalAST = instance.parseEval('some php code');
* var codeAST = instance.parseCode('<?php some php code', 'foo.php');
* var tokens = instance.tokenGetAll('<?php some php code');
* ```
*
* @constructor {Engine}
* @param {Object} options - List of options
*
* @property {Lexer} lexer
* @property {Parser} parser
* @property {AST} ast
* @property {Object} tokens
*/
var engine = function(options) {
Iif (typeof this === 'function') {
return new this(options);
}
this.tokens = tokens;
this.lexer = new lexer(this);
this.ast = new AST();
this.parser = new parser(this.lexer, this.ast);
if (options && typeof options === 'object') {
combine(options, this);
}
};
/**
* Creates a new instance (Helper)
* @param {Object} options
* @return {Engine}
* @private
*/
engine.create = function(options) {
return new engine(options);
};
/**
* Evaluate the buffer
* @private
*/
engine.parseEval = function(buffer, options) {
var self = new engine(options);
return self.parseEval(buffer);
};
/**
* Parse an evaluating mode string (no need to open php tags)
* @param {String} buffer
* @return {Program}
*/
engine.prototype.parseEval = function(buffer) {
this.lexer.mode_eval = true;
this.lexer.all_tokens = false;
return this.parser.parse(buffer, 'eval');
};
/**
* Static function that parse a php code with open/close tags
* @private
*/
engine.parseCode = function(buffer, filename, options) {
if (typeof filename === 'object') {
// retro-compatibility
options = filename;
filename = 'unknown';
}
var self = new engine(options);
return self.parseCode(buffer, filename);
};
/**
* Function that parse a php code with open/close tags
*
* Sample code :
* ```php
* <?php $x = 1;
* ```
*
* Usage :
* ```js
* var parser = require('php-parser');
* var phpParser = new parser({
* // some options
* });
* var ast = phpParser.parseCode('...php code...', 'foo.php');
* ```
* @param {String} buffer - The code to be parsed
* @param {String} filename - Filename
* @return {Program}
*/
engine.prototype.parseCode = function(buffer, filename) {
this.lexer.mode_eval = false;
this.lexer.all_tokens = false;
return this.parser.parse(buffer, filename);
};
/**
* Split the buffer into tokens
* @private
*/
engine.tokenGetAll = function(buffer, options) {
var self = new engine(options);
return self.tokenGetAll(buffer);
};
/**
* Extract tokens from the specified buffer.
* > Note that the output tokens are *STRICLY* similar to PHP function `token_get_all`
* @param {String} buffer
* @return {String[]} - Each item can be a string or an array with following informations [token_name, text, line_number]
*/
engine.prototype.tokenGetAll = function(buffer) {
this.lexer.mode_eval = false;
this.lexer.all_tokens = true;
var EOF = this.lexer.EOF;
var names = this.tokens.values;
this.lexer.setInput(buffer);
var token = this.lexer.lex() || EOF;
var result = [];
while(token != EOF) {
var entry = this.lexer.yytext;
if (names.hasOwnProperty(token)) {
entry = [names[token], entry, this.lexer.yylloc.first_line];
}
result.push(entry);
token = this.lexer.lex() || EOF;
}
return result;
};
// exports the function
module.exports = engine;
|