gmnon.cn-疯狂蹂躏欧美一区二区精品,欧美精品久久久久a,高清在线视频日韩欧美,日韩免费av一区二区

站長資訊網
最全最豐富的資訊網站

談談JS實現AST抽象語法樹問題

談談JS實現AST抽象語法樹問題

免費學習推薦:javascript學習教程

前端中的AST抽象語法樹問題

  • 四則運算
  • 正則表達式
  • 詞法分析
  • 語法分析
  • 完整代碼

四則運算

首先明確,此次的代碼都是基于LL的語法分析來實現的,實現的是四則混合運算的功能,先看下定義:
TokenNumber:
· 1 2 3 4 5 6 7 8 9 0 的組合
Operator:
+ - * / 之一
WhiteSpace:
<SP>
LineTerminator:
<LF> <CR>

看下產生式:
談談JS實現AST抽象語法樹問題

正則表達式

我們首先實現正則表達式的匹配原則:

<script>     var regexp = /([0-9.]+)|([ t]+)|([rn]+)|(*)|(/)|(+)|(-)/g      var dictionary = ["Number", "Whitespace", "LineTerminator", "*", "/", "+", "-"];      function tokenize(source) {         var result = null;         while(true) {             result = regexp.exec(source);              if(!result) break;              for(var i = 1; i <= dictionary.length; i ++) {                 if(result[i])                     console.log(dictionary[i - 1]);             }             console.log(result);         }     }      tokenize("1024 + 10 * 25");</script>

此時我們看一下頁面的運行打印結果:
談談JS實現AST抽象語法樹問題
值得一提的是這里用到了exec方法,exec() 方法用于檢索字符串中的正則表達式的匹配。
我們看一下它的語法:
RegExpObject.exec(string)

如果 exec() 找到了匹配的文本,則返回一個結果數組。否則,返回 null。此數組的第 0 個元素是與正則表達式相匹配的文本,第 1 個元素是與 RegExpObject 的第 1 個子表達式相匹配的文本(如果有的話),第 2 個元素是與 RegExpObject 的第 2 個子表達式相匹配的文本(如果有的話),以此類推。除了數組元素和 length 屬性之外,exec() 方法還返回兩個屬性。index 屬性聲明的是匹配文本的第一個字符的位置。input 屬性則存放的是被檢索的字符串 string。我們可以看得出,在調用非全局的 RegExp 對象的 exec() 方法時,返回的數組與調用方法 String.match() 返回的數組是相同的。

但是,當 RegExpObject 是一個全局正則表達式時,exec() 的行為就稍微復雜一些。它會在 RegExpObject 的 lastIndex 屬性指定的字符處開始檢索字符串 string。當 exec() 找到了與表達式相匹配的文本時,在匹配后,它將把 RegExpObject 的 lastIndex 屬性設置為匹配文本的最后一個字符的下一個位置。這就是說,您可以通過反復調用 exec() 方法來遍歷字符串中的所有匹配文本。當 exec() 再也找不到匹配的文本時,它將返回 null,并把 lastIndex 屬性重置為 0。

詞法分析

我們在這一部分對上面的代碼做優化。
首先是剛才提到的:
當 RegExpObject 是一個全局正則表達式時,exec() 的行為就稍微復雜一些。它會在 RegExpObject 的 lastIndex 屬性指定的字符處開始檢索字符串 string。當 exec() 找到了與表達式相匹配的文本時,在匹配后,它將把 RegExpObject 的 lastIndex 屬性設置為匹配文本的最后一個字符的下一個位置。
那么我們就要考慮到沒有匹配上字符的情況,做一個判斷處理:

<script>     var regexp = /([0-9.]+)|([ t]+)|([rn]+)|(*)|(/)|(+)|(-)/g      var dictionary = ["Number", "Whitespace", "LineTerminator", "*", "/", "+", "-"];      function* tokenize(source) {         var result = null;         var lastIndex = 0;         while(true) {             lastIndex = regexp.lastIndex;             result = regexp.exec(source);              if(!result) break;              if(regexp.lastIndex - lastIndex > result[0].length)                 break;                          let token = {                 type: null,                 value: null             }              for(var i = 1; i <= dictionary.length; i ++) {                 if(result[i])                     token.type = dictionary[i - 1];             }             token.value = result[0];             yield token        }         yield {             type: 'EOF'         }     }      for (let token of tokenize("1024 + 10 * 25")) {         console.log(token)     }</script>

如上,我們對regexp.lastIndex - lastIndexresult[0] 的長度進行比較,判斷是否有字符串沒有匹配上。
將整個函數改成generator函數的形式,我們看下運行的結果:
談談JS實現AST抽象語法樹問題

語法分析

首先編寫分塊的產生式,我們看一下總的代碼結構:

<script>     var regexp = /([0-9.]+)|([ t]+)|([rn]+)|(*)|(/)|(+)|(-)/g      var dictionary = ["Number", "Whitespace", "LineTerminator", "*", "/", "+", "-"];      function* tokenize(source) {         var result = null;         var lastIndex = 0;         while(true) {             lastIndex = regexp.lastIndex;             result = regexp.exec(source);              if(!result) break;              if(regexp.lastIndex - lastIndex > result[0].length)                 break;                          let token = {                 type: null,                 value: null             }              for(var i = 1; i <= dictionary.length; i ++) {                 if(result[i])                     token.type = dictionary[i - 1];             }             token.value = result[0];             yield token        }         yield {             type: 'EOF'         }     }      let source = [];      for(let token of tokenize("10 * 25")) {         if (token.type !== "Whitespace" && token.type !== "LineTerminator")             source.push(token);     }      function Expression(tokens) {      }      function AdditiveExpression(source){      }      function MultiplicativeExpresson(source) {         console.log(source);     }      MultiplicativeExpresson("10 * 25")</script>

我們先從MultiplicativeExpresson來進行研究,它分為四種情況:

function MultiplicativeExpresson(source) { 	//如果是數字則進行封裝      if(source[0].type === "Number") {          let node = {              type: "MultiplicativeExpresson",              children:[source[0]]          }          source[0] = node;          return MultiplicativeExpresson(source)      }       //如果是乘號或者除號,則將三項出棧,進行重組      if(source[0].type === "MultiplicativeExpresson" && source[1] && source[1].type === "*") {          let node = {              type: "MultiplicativeExpresson",              operator: "*",              children: []          }          node.children.push(source.shift());          node.children.push(source.shift());          node.children.push(source.shift());          source.unshift(node);          return MultiplicativeExpresson(source)      }       if(source[0].type === "MultiplicativeExpresson" && source[1] && source[1].type === "/") {          let node = {              type: "MultiplicativeExpresson",              operator: "*",              children: []          }          node.children.push(source.shift());          node.children.push(source.shift());          node.children.push(source.shift());          source.unshift(node);          return MultiplicativeExpresson(source)      }       //遞歸結束的條件      if(source[0].type === "MultiplicativeExpresson")          return source[0];       return MultiplicativeExpresson(source);  }

我們看一下當source為"10 * 25 / 2"時調用console.log(MultiplicativeExpresson(source))最后運行的結果:
談談JS實現AST抽象語法樹問題
接下來看AdditiveExpression 本質上和MultiplicativeExpresson沒有什么不同,差異點已經標注在代碼當中了:

    function AdditiveExpression(source){         if(source[0].type === "MultiplicativeExpresson") {             let node = {                 type: "AdditiveExpression",                 children:[source[0]]             }             source[0] = node;             return AdditiveExpression(source)         }          //如果是乘號或者除號,則將三項出棧,進行重組         if(source[0].type === "AdditiveExpression" && source[1] && source[1].type === "+") {             let node = {                 type: "AdditiveExpression",                 operator: "+",                 children: []             }             node.children.push(source.shift());             node.children.push(source.shift());             //考慮到第三個數可能時Number 需要在這里再次調用一下 MultiplicativeExpresson 做處理             MultiplicativeExpresson(source);             node.children.push(source.shift());             source.unshift(node);             return AdditiveExpression(source)         }          if(source[0].type === "AdditiveExpression" && source[1] && source[1].type === "-") {             let node = {                 type: "AdditiveExpression",                 operator: "-",                 children: []             }             node.children.push(source.shift());             node.children.push(source.shift());             MultiplicativeExpresson(source);             node.children.push(source.shift());             source.unshift(node);             return AdditiveExpression(source)         }          //遞歸結束的條件         if(source[0].type === "AdditiveExpression")             return source[0];          //第一次進循環 調用         MultiplicativeExpresson(source);         return AdditiveExpression(source);     }

我們看一下當source為"10 * 25 / 2"時調用console.log(AdditiveExpression(source))最后運行的結果:
談談JS實現AST抽象語法樹問題
那么Expression的代碼邏輯就很好表達了:

function Expression(tokens) {      if(source[0].type === "AdditiveExpression" && source[1] && source[1].type === "EOF") {          let node = {              type: "Expression",              children: [source.shift(), source.shift()]          }          source.unshift(node);          return node;      }      AdditiveExpression(source);      return Expression(source);  }

看下運行后的結果:
談談JS實現AST抽象語法樹問題

贊(0)
分享到: 更多 (0)
?
網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
gmnon.cn-疯狂蹂躏欧美一区二区精品,欧美精品久久久久a,高清在线视频日韩欧美,日韩免费av一区二区
农村妇女精品一二区| 91性高潮久久久久久久| 永久免费在线看片视频| 日本成人在线免费视频| 成人久久久久久久久| 青青视频免费在线| 欧美 国产 精品| 在线观看18视频网站| 久久av秘一区二区三区| 国内自拍第二页| 特级西西444www| 不卡中文字幕在线| 日韩中文字幕亚洲精品欧美| 中文字幕av导航| 肉大捧一出免费观看网站在线播放 | xxxx18hd亚洲hd捆绑| 国产不卡一区二区视频| 欧美爱爱视频免费看| 99免费视频观看| 五月花丁香婷婷| 国产探花在线观看视频| 红桃视频 国产| 国产日韩亚洲欧美在线| 91猫先生在线| 亚洲精品免费一区亚洲精品免费精品一区| 亚洲欧美另类动漫| 激情久久综合网| 加勒比成人在线| 亚洲欧洲日本精品| 影音先锋男人的网站| 国产精品秘入口18禁麻豆免会员| 手机看片福利盒子久久| 一区二区久久精品| 国内少妇毛片视频| 亚洲综合日韩欧美| 日本福利视频在线观看| www日韩视频| 999久久久精品视频| 亚洲自偷自拍熟女另类| 中文字幕超清在线免费观看| 被灌满精子的波多野结衣| 黄色国产小视频| 色一情一乱一乱一区91| 亚洲少妇久久久| 国产夫妻自拍一区| 色免费在线视频| 欧美一区二区三区爽大粗免费| 免费看污黄网站| 成年人午夜视频在线观看| 日韩精品视频一二三| 精品久久一二三| 中文字幕超清在线免费观看| 在线看的黄色网址| 丝袜老师办公室里做好紧好爽| 亚洲成年人专区| 日日噜噜噜噜久久久精品毛片| 免费高清一区二区三区| 最近中文字幕免费mv| 久久久久久久高清| www.夜夜爽| 亚洲男人天堂色| 精品一区二区中文字幕| 成人av在线不卡| 91国在线高清视频| 日韩第一页在线观看| 一区二区三区 欧美| 9久久婷婷国产综合精品性色 | 日韩欧美视频免费在线观看| 亚洲一区二区福利视频| 91国产精品视频在线观看| 久久精品免费一区二区| 黄色成人在线看| 夜夜添无码一区二区三区| 大地资源网在线观看免费官网| 超碰超碰超碰超碰超碰| 少妇久久久久久被弄到高潮| 久无码久无码av无码| 欧美精品卡一卡二| 无码播放一区二区三区| 男人天堂网视频| 可以免费在线看黄的网站| 亚洲精品高清无码视频| 成人亚洲精品777777大片| 亚洲欧美日韩三级| 亚洲成人手机在线观看| 国产人妻人伦精品| 男人日女人下面视频| 国产天堂在线播放| 亚洲污视频在线观看| 久久6免费视频| 97超碰在线视| 男人天堂999| 一路向西2在线观看| 波多野结衣三级在线| 国产极品尤物在线| 成年人在线观看视频免费| 天天久久综合网| 久草视频这里只有精品| 99免费视频观看| 亚洲小视频在线播放| 欧美精品自拍视频| 青青在线免费观看视频| 一区二区三区国产好的精华液| 久久99久久久久久| 日韩av片网站| 青青草精品视频在线| 在线黄色免费看| 国产白丝袜美女久久久久| 最新国产黄色网址| 日韩伦理在线免费观看| 亚洲视频第二页| 六月丁香激情网| 日本免费a视频| 99日在线视频| 国产99久久九九精品无码| 久久精品一二三四| 日本在线视频www| 黄色一级片黄色| 天天操天天干天天做| 91av资源网| 精品久久一二三| 免费的av在线| 一区二区三区国产好的精华液| 国产av麻豆mag剧集| 欧美又黄又嫩大片a级| 日日碰狠狠躁久久躁婷婷| 日韩国产精品毛片| 激情文学亚洲色图| 校园春色 亚洲色图| 伊人色在线视频| 国产性生交xxxxx免费| 男操女免费网站| 国产日韩成人内射视频| 欧美,日韩,国产在线| 91视频 - 88av| 国内自拍中文字幕| 日本a在线天堂| 91精品国产三级| 亚洲一二三av| 国内av免费观看| 男女h黄动漫啪啪无遮挡软件| 亚欧美在线观看| 国产又爽又黄ai换脸| 欧美日韩视频免费在线观看| 欧美在线a视频| 精产国品一二三区| 最新黄色av网站| 99re6这里有精品热视频| 免费观看亚洲视频| 一本久道高清无码视频| 日韩精品视频久久| 国产色视频在线播放| 善良的小姨在线| 妞干网视频在线观看| 国模吧无码一区二区三区| 成人免费毛片播放| 五月天六月丁香| 奇米精品一区二区三区| 成人三级视频在线播放| 国产色视频在线播放| 亚洲啊啊啊啊啊| 亚洲熟妇国产熟妇肥婆| 香蕉视频禁止18| 黄色激情在线视频| 欧美一级黄色影院| 激情视频小说图片| 国产精品天天av精麻传媒| 在线免费看污网站| 夫妻免费无码v看片| 国产xxxxhd| 一本久道中文无码字幕av| 亚洲精品偷拍视频| 亚洲熟妇av一区二区三区| 小早川怜子一区二区三区| 国产黄色一级网站| 国产又爽又黄ai换脸| 日日橹狠狠爱欧美超碰| 中文字幕 91| 又粗又黑又大的吊av| 特级黄色录像片| 欧美日韩中文不卡| 5月婷婷6月丁香| 看全色黄大色大片| 日本999视频| 鲁一鲁一鲁一鲁一澡| 福利片一区二区三区| 337p粉嫩大胆噜噜噜鲁| 久久久久久久香蕉| 久久久久xxxx| 日韩av卡一卡二| 九一精品在线观看| 人妻夜夜添夜夜无码av| 天天操精品视频| 久久久久久久久久久久久久久国产| 免费不卡av在线| 99在线精品免费视频| www.成年人视频| www.男人天堂网| 欧美国产综合在线| 日韩欧美一级在线|