iT邦幫忙

2022 iThome 鐵人賽

DAY 28
0
Modern Web

Parser 的深入研究系列 第 28

[Day28] - Lezer.js - 利用 Grammar 定義我們的語言

  • 分享至 

  • xImage
  •  

前言

在 [Day-22] 中,我們討論了 CodeMirror 可以利用它來做 語法的 Highlight,但是 CodeMirror 並不支援 SCSS 語法的高亮。

這時我們就需要自定義一個語法的 Highlight,這時就需要用到 Lezer.js 了。

下面我們就來說說 Lezer.js,如何利用昨天說到的 Grammar 來定義語法。

第一步,安裝 @lezer/generator 跟 rollup

# init package.json
npm init -y
# The lezer packages used in our script
npm i -s @lezer/generator
# Rollup 
npm i -D rollup 

第二步,定義 lang.grammar

先來定義簡單的 grammar,用於解析 (100-(2+4)) 或 (a+1) 這種算式。

@top Program { expression }

expression { Name | Number | BinaryExpression }

@skip { space | Comment }

BinaryExpression { "(" expression ("+" | "-") expression ")" }

@tokens {
  space { @whitespace+ }
  Comment { "//" ![\n]* }
  Name { @asciiLetter+ }
  Number { @digit+ }
}

第三步,產生 dist/lang.js

lezer-generator src/lang.grammar -o dist/lang.js

第四步,利用產生的 dist/lang.js 來 Parse 定義的語法並 Travel Tree Nodes

import {parser} from '../dist/lang.js';

const tree = parser.parse('(a+1)');

// 利用 iterate 走訪 tree 的每個節點,並輸出節點對應資訊
tree.iterate({
  enter(node) {
    const originStr = str.substring(node.from, node.to);
    console.log('type=',node.name,' \t (from,to) =',`(${node.from},${node.to})`,' \t對應字串 =',originStr);
  },
});
/*
type= Program             (from,to) = (0,5)      對應字串 = (a+1)
type= BinaryExpression    (from,to) = (0,5)      對應字串 = (a+1)
type= Name                (from,to) = (1,2)      對應字串 = a
type= Number              (from,to) = (3,4)      對應字串 = 1
*/

參考資料


上一篇
[Day27] - 語法分析(syntactic analysis)
下一篇
[Day29] - Lezer.js - 將自定義的 Grammar 拿到 CodeMirror 中做使用
系列文
Parser 的深入研究32
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言