摘要:生成語法解析器五個文法,行代碼搞定,表示四則運算的文法,可以參考此文。這些相互依賴的文法組成了一個文法鏈條,完整表達了四則運算的邏輯函數第一個參數接收根文法表達式,第二個參數是詞法解析器,我們將上面創建的傳入。
syntax-parser 是完全利用 JS 編寫的詞法解析+語法解析引擎,所以完全支持在瀏覽器、NodeJS 環境執行。
它可以幫助你快速生成 詞法解析器,亦或進一步生成 語法解析器,將字符串解析成語法樹,語法解析器還支持下一步智能提示功能,輸入光標位置,給出輸入推薦。
目前 syntax-parser 功能逐漸穩定,內核性能還在逐步優化中,我們會利用 syntax-parser 引擎的能力,完成一些令人驚喜的小 DEMO,如果與你的業務場景恰好契合,歡迎使用!
這次的 DEMO 是:利用 syntax-parser 快速完成四則運算語法解析器!
1. 生成詞法解析器通過下面 20 行配置,生成一個能解析英文、數字、加減乘除、左右括號的詞法解析器,so easy!
import { createLexer } from "syntax-parser" const myLexer = createLexer([ { type: "whitespace", regexes: [/^(s+)/], ignore: true }, { type: "word", regexes: [/^([a-zA-Z0-9]+)/] // 解析數字 }, { type: "operator", regexes: [ /^((|))/, // 解析 ( ) /^(+|-|*|/)/ // 解析 + - * / ] } ]);
我們可以使用 myLexer 將字符串解析為一個個 Token:
myLexer("1 + 2 - 3 * b / (x + y)")
不過這次的目的是生成語法樹,所以我們會把 myLexer 作為參數傳給語法解析器。
2. 生成語法解析器五個文法,20 行代碼搞定,表示四則運算的文法,可以參考 此文。
利用 chain ,可以高效表示每一個文法表達式要匹配的字符串、表示匹配次數,還支持嵌入新的文法函數。這些相互依賴的文法組成了一個文法鏈條,完整表達了四則運算的邏輯:
import { chain, createParser, many, matchTokenType } from "syntax-parser" const root = () => chain(term, many(addOp, root))(parseTermAst); const term = () => chain(factor, many(mulOp, root))(parseTermAst); const mulOp = () => chain(["*", "/"])(ast => ast[0].value); const addOp = () => chain(["+", "-"])(ast => ast[0].value); const factor = () => chain([ chain("(", root, ")")(ast => ast[1]), chain(matchTokenType("word"))(ast => ast[0].value) ])(ast => ast[0]); const myParser = createParser( root, // Root grammar. myLexer // Created in lexer example. );
createParser 函數第一個參數接收根文法表達式,第二個參數是詞法解析器,我們將上面創建的 myLexer 傳入。 parseTermAst 函數多帶帶提出來,目的是輔助生成語法樹,一共 20 行代碼:
const parseTermAst = (ast: any) => ast[1] ? ast[1].reduce( (obj: any, next: any) => next[0] ? { operator: next[0], left: obj || ast[0], right: next[1] } : { operator: next[1] && next[1].operator, left: obj || ast[0], right: next[1] && next[1].right }, null ) : ast[0];
這個函數是為了將語法樹變得更規整,否則得到的 AST 解析將會是數組,而不是像 left right operator 這么有含義的對象。
PS:本文的 DEMO 沒有考慮乘除高優先級問題。3. 運行詞法解析器
最后得到的 myParser 就是語法解析器了!直接執行就能拿到語法樹結果!
const result = myParser("1 + 2 - (3 - 4 + 5) * 6 / 7"); console.log(result.ast)
我們打印出語法樹,運行結果如下:
{ "operator": "/", "left": { "operator": "-", "left": { "operator": "+", "left": "1", "right": "2" }, "right": { "operator": "*", "left": { "operator": "+", "left": { "operator": "-", "left": "3", "right": "4" }, "right": "5" }, "right": "6" } }, "right": "7" }4. 錯誤提示
不僅語法樹,我們構造一個錯誤的輸入試試!
const result = myParser("1 + 2 - (3 - 4 + 5) * 6 / "); console.log(result.error)
這次我們打印錯誤信息:
{ "suggestions": [ { "type": "string", "value": "(" }, { "type": "special", "value": "word" } ], "token": { "type": "operator", "value": "/", "position": [ 24, 25 ] }, "reason": "incomplete" }
精準的提示了最后一個 / 位置不完整,建議是填寫 ( 或者一個單詞。這都是根據文法自動生成的建議,提示不多一個,不少一個!
5. 任意位置輸入提示最精髓的功能到了,這個語法解析器就是為了做自動提示,所以支持多傳一個參數,告訴我當前你光標的位置:
const result = myParser("1 + 1", 5) console.log(result.nextMatchings)
假設語句寫到這里,我們光標位置定位到 5 的位置,也就是最后一個 1 后面,nextMatchings 屬性會告訴我們后面的可能情況:
[ { "type": "string", "value": "-" }, { "type": "string", "value": "+" }, { "type": "string", "value": "/" }, { "type": "string", "value": "*" } ]6. 結合業務,用在文本編輯器
筆者拿 monaco-editor 舉例,利用上面的語法樹解析,我們可以輕松完成下面的效果:
光標智能補全 錯誤提示無論是智能補全,還是錯誤提示都是 100% 精準無誤的(根據上面編寫的文法表達式)。
相比普通的語法解析器在解析錯誤時直接拋出錯誤,syntax-parser 不僅提供語法樹,還能根據文法智能提示光標位置的輸入推薦,哪怕是輸入錯誤的情況下,是不是解決了大家的痛點呢?如果覺得好用,歡迎給 syntax-parser 提 建議 或者 pr !
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/97674.html
摘要:它是一門解析型的語言,何為解析型語言呢就是在運行時通過解析器將源代碼一行行解析成機器碼。而像語言,等則是編譯型的語言,即通過編譯器將所有的源代碼一次性編譯成二進制指令,生成一個可執行的程序。 ...
摘要:將每一行作為返回,其中是每行中的列名。對于每一行,都會生成一個對象,其中包含和列中的值。它返回一個迭代器,是迭代結果都為的情況。深度解析至此全劇終。 簡單實戰 大家好,我又來了,在經過之前兩篇文章的介紹后相信大家對itertools的一些常見的好用的方法有了一個大致的了解,我自己在學完之后仿照別人的例子進行了真實場景下的模擬練習,今天和大家一起分享,有很多部分還可以優化,希望有更好主意...
摘要:遵循特定規則,利用操作符,終止節點和其他非終止節點,構造新的字符串非終結符是表示字符串的樹的內部節點。語法中的生產具有這種形式非終結符終結,非終結符和運算符的表達式語法的非終結點之一被指定為根。 大綱 基于狀態的構建 基于自動機的編程 設計模式:Memento提供了將對象恢復到之前狀態的功能(撤消)。 設計模式:狀態允許對象在其內部狀態改變時改變其行為。 表驅動結構* 基于語法的構...
摘要:當然這不是只限于使用或者其他打包工具的方式都能支持使用優點模塊化和可重用性沒有沖突顯性依賴不會污染全局可以配合預處理器使用少開發單獨文件寫法基本一致 To define is to limit. 定義一樣東西,就意味著限制了它?!鯛柕?《道林·格雷的畫像》 React系列 React系列 --- 簡單模擬語法(一)React系列 --- Jsx, 合成事件與Refs(二)Reac...
摘要:來源編程精解中文第三版翻譯項目原文譯者飛龍協議自豪地采用谷歌翻譯部分參考了編程精解第版確定編程語言中的表達式含義的求值器只是另一個程序。若文本不是一個合法程序,解析器應該指出錯誤。 來源:ApacheCN『JavaScript 編程精解 中文第三版』翻譯項目原文:Project: A Programming Language 譯者:飛龍 協議:CC BY-NC-SA 4.0 自豪地采用...
閱讀 1329·2021-11-15 11:37
閱讀 2214·2021-09-23 11:21
閱讀 1300·2019-08-30 15:55
閱讀 2105·2019-08-30 15:55
閱讀 2815·2019-08-30 15:52
閱讀 2819·2019-08-30 11:12
閱讀 1573·2019-08-29 18:45
閱讀 1885·2019-08-29 14:04