123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324 |
- /**
- * 注册命名空间:baidu.jsAnalytic
- */
- baidu.namespace.register("baidu.jsAnalytic");
- /**
- * Javascript代码词法分析
- * @author lichengyin (FCP:PHP代码)
- * @cover zhaoxianlie (FCPHelper:将PHP代码重写为Javascript代码)
- */
- baidu.jsAnalytic = function(){
-
- this.parsePos = 0;
-
- this.content = '';
-
- this.contentLength = 0;
-
- this._output = [];
-
- this._whitespace = /[\n\r\t\s]/g;
-
- this._wordchar = /[a-zA-Z0-9_\$]/g;
-
- this._digits = /[0-9]/g;
-
- this._punct = /\+|-|\*|\/|%|&|\+\+|\-\-|=|\+=|\-=|\*=|\/=|%=|==|===|!=|!==|>|<|>=|<=|>>|<<|>>>|>>>=|>>=|<<=|&&|&=|\||\|\||!|!!|,|:|\?|\^|\^=|_|\|=|::/g;
-
- /**
- * 主方法
- * @param {Object} $content
- */
- this.run = function($content){
-
- this.content = $content.trim().replace(/\r\n/g, "\n");
- this.contentLength = this.content.length;
- this.tokenAnalytic();
- return this._output;
- };
-
- /**
- * 此法分析器
- */
- this.tokenAnalytic = function(){
- while (true){
- $token = this.getNextToken();
- if ($token){
- if ($token[1] === baidu.FL.FL_EOF) break;
- this._output.push($token);
- }
- }
- };
-
- /**
- * 检测$char是否在$array中
- * @param {Object} $char
- * @param {Object} $array
- */
- this._is_match = function($char,$reg){
- return $reg.test($char);
- };
-
- /**
- * 单个此法分析
- */
- this.getNextToken = function(){
- if (this.parsePos >= this.contentLength){
- return ['', baidu.FL.FL_EOF];
- }
- var $char = this.content[this.parsePos];
- var $result,$tokenCount,$lastText,$lastType;
- this.parsePos++;
-
- while (this._is_match($char, this._whitespace)){
- if (this.parsePos >= this.contentLength){
- return ['', baidu.FL.FL_EOF];
- }
- if ($char === "\x0d") return '';
- if ($char === "\x0a"){
- return [$char, baidu.FL.FL_NEW_LINE];
- }
- $char = this.content[this.parsePos];
- this.parsePos++;
- }
-
- //处理正常的字符
- if (this._is_match($char, this._wordchar)){
- $result = this._getWordToken($char);
- if ($result) return $result;
- }
- switch (true){
- case $char === '(' || $char === '[' : return [$char, baidu.FL.JS_START_EXPR];
- case $char === ')' || $char === ']' : return [$char, baidu.FL.JS_END_EXPR];
- case $char === '{' : return [$char, baidu.FL.JS_START_BLOCK];
- case $char === '}' : return [$char, baidu.FL.JS_END_BLOCK];
- case $char === ';' : return [$char, baidu.FL.JS_SEMICOLON];
- }
- //注释或者正则
- if ($char === '/'){
- //注释
- $result = this._getCommentToken($char);
- if ($result) return $result;
-
- //正则
- $tokenCount = this._output.length;
- if ($tokenCount){
- var _tem = this._output[$tokenCount - 1];
- $lastText = _tem[0];
- $lastType = _tem[1];
- }else {
- $lastType = baidu.FL.JS_START_EXPR;
- }
- if (($lastType === baidu.FL.JS_WORD && ($lastText === 'return' || $lastText === 'to'))
- || ($lastType === baidu.FL.JS_START_EXPR
- || $lastType === baidu.FL.JS_START_BLOCK
- || $lastType === baidu.FL.JS_END_BLOCK
- || $lastType === baidu.FL.JS_OPERATOR
- || $lastType === baidu.FL.JS_EQUALS
- || $lastType === baidu.FL.JS_SEMICOLON
- || $lastType === baidu.FL.FL_EOF
- )){
-
- $result = this._getRegexpToken($char);
- if ($result) return $result;
- }
- }
- //引号
- if ($char === '"' || $char === "'"){
- $result = this._getQuoteToken($char);
- if ($result) return $result;
- }
- //sharp variables
- if ($char === '#'){
- $result = this._getSharpVariblesToken($char);
- if ($result) return $result;
- }
- //操作符
- if (this._is_match($char, this._punct)){
- $result = this._getPunctToken($char);
- if ($result) return $result;
- }
-
- return [$char, baidu.FL.FL_NORMAL];
- };
-
- /**
- * 正常的字符
- * @param {Object} $char
- */
- this._getWordToken = function($char){
- var $sign,$t;
-
- while (this._is_match(this.content[this.parsePos], this._wordchar)
- && this.parsePos < this.contentLength){
- $char += this.content[this.parsePos];
- this.parsePos++;
- }
- //处理带E的数字,如:20010E+10,0.10E-10
- if ((this.content[this.parsePos] === '+' || this.content[this.parsePos] === '-')
- && /^[0-9]+[Ee]$/.test()
- && this.parsePos < this.contentLength){
-
- $sign = this.content[this.parsePos];
- this.parsePos++;
- $t = this.getNextToken();
- $char += $sign . $t[0];
- return [$char, baidu.FL.JS_WORD];
- }
- //for in operator
- if ($char === 'in'){
- return [$char , baidu.FL.JS_OPERATOR];
- }
- return [$char, baidu.FL.JS_WORD];
- };
-
- /**
- * 注释
- * @param {Object} $char
- */
- this._getCommentToken = function($char){
- var $comment = '';
- var $lineComment = true;
- var $c = this.content[this.parsePos];
- var $cc,$lineComment;
- //单行或者多行注释
- if($c === '*'){
- this.parsePos++;
- while (!(this.content[this.parsePos] === '*'
- && this.content[this.parsePos + 1]
- && this.content[this.parsePos + 1] === '/')
- && this.parsePos < this.contentLength){
-
- $cc = this.content[this.parsePos];
- $comment += $cc;
- //\x0d为\r, \x0a为\n
- if ($cc === "\x0d" || $cc === "\x0a"){
- $lineComment = false;
- }
- this.parsePos++;
- }
-
- this.parsePos += 2;
- //ie下的条件编译
- if ($comment.indexOf('@cc_on') === 0){
- return ['/*' + $comment + '*/', baidu.FL.JS_IE_CC];
- }
- if ($lineComment){
- return ['/*' + $comment + '*/', baidu.FL.JS_INLINE_COMMENT];
- }else{
- return ['/*' + $comment + '*/', baidu.FL.JS_BLOCK_COMMENT];
- }
- }
- //单行注释
- if ($c === '/'){
- $comment = $char;
- //\x0d为\r, \x0a为\n
- while (this.content[this.parsePos] !== "\x0d"
- && this.content[this.parsePos] !== "\x0a"
- && this.parsePos < this.contentLength){
-
- $comment += this.content[this.parsePos];
- this.parsePos++;
- }
- this.parsePos++;
- return [$comment, baidu.FL.JS_COMMENT];
- }
- };
-
- /**
- * 引号
- * @param {Object} $char
- */
- this._getQuoteToken = function($char){
- var $sep = $char;
- var $escape = false;
- var $resultString = $char;
- while (this.content[this.parsePos] !== $sep || $escape){
- $resultString += this.content[this.parsePos];
- $escape = !$escape ? (this.content[this.parsePos] === "\\") : false;
- this.parsePos++;
- if (this.parsePos >= this.contentLength){
- return [$resultString, baidu.FL.JS_STRING];
- }
- }
- this.parsePos++;
- $resultString += $sep;
- return [$resultString, baidu.FL.JS_STRING];
- };
-
- /**
- * 正则
- * @param {Object} $char
- */
- this._getRegexpToken = function($char){
- var $sep = $char;
- var $escape = false;
- var $resultString = $char;
- var $inCharClass = false;
- while ($escape || $inCharClass || this.content[this.parsePos] !== $sep){
- $resultString += this.content[this.parsePos];
- if (!$escape){
- $escape = (this.content[this.parsePos] === "\\");
- if (this.content[this.parsePos] === '['){
- $inCharClass = true;
- }else if(this.content[this.parsePos] === ']'){
- $inCharClass = false;
- }
- }else {
- $escape = false;
- }
- this.parsePos++;
- if (this.parsePos >= this.contentLength){
- return [$resultString, baidu.FL.JS_REGEXP];
- }
- }
- this.parsePos++;
- $resultString += $sep;
- while (this._is_match(this.content[this.parsePos], this._wordchar)
- && this.parsePos < this.contentLength ) {
-
- $resultString += this.content[this.parsePos];
- this.parsePos++;
- }
- return [$resultString, baidu.FL.JS_REGEXP];
- };
-
- /**
- * sharp varibles
- * @param {Object} $char
- */
- this._getSharpVariblesToken = function($char){
- var $sharp = $char;
- var $c,$next;
- if (this._is_match(this.content[this.parsePos], this._digits)){
- do{
- $c = this.content[this.parsePos];
- $sharp += $c;
- this.parsePos++;
- }while ($c !== '#' && $c !== '=' && this.parsePos < this.contentLength);
- $next = this.content.substr( this.parsePos, 2);
- if ($next === '[]' || $next === '{}'){
- $sharp += $next;
- this.parsePos += 2;
- }
- return [$sharp, baidu.FL.JS_WORD];
- }
- };
-
- /**
- * 操作符
- * @param {Object} $char
- */
- this._getPunctToken = function($char){
- while (this._is_match($char + this.content[this.parsePos], this._punct)
- && this.parsePos < this.contentLength){
-
- $char += this.content[this.parsePos];
- this.parsePos++;
- }
- return [$char, $char === '=' ? baidu.FL.JS_EQUALS : baidu.FL.JS_OPERATOR];
- };
-
- }
|