溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何理解編程語言的IDE支持

發(fā)布時(shí)間:2021-10-26 15:42:54 來源:億速云 閱讀:170 作者:iii 欄目:編程語言

本篇內(nèi)容主要講解“如何理解編程語言的IDE支持”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“如何理解編程語言的IDE支持”吧!

語法分析

對于開發(fā)工具來說,語法分析有幾個重要的功能:

  • 語法高亮,是指根據(jù)術(shù)語類別來顯示不同的顏色與字體以增強(qiáng)可讀性的一種編輯器特性。

  • 實(shí)現(xiàn)智能感知

  • 實(shí)現(xiàn)跳轉(zhuǎn)和引用分析

從我粗糙的調(diào)查來看,大致可以分析為四類:

  • 基于正則表達(dá)式來實(shí)現(xiàn)語法分析

Sublime Text 基于 YAML 形式的正則匹配方式:Sublime Syntax files

Textmate、VS Code 基于 JSON 的正則匹配方式:Language Grammars

  • 基于語法分析器(如 BNF)生成中間代碼

Jetbrins 基于 BNF 生成代碼的方式:Grammar and Parser

  • 自制 DSL 進(jìn)行語法解析

Vim 基于正則 + 自制 DSL:Vim documentation: syntax、Rust 示例

  • 手寫解析語法

Eclipse IDE 提供了個 JFace editor,但是似乎是要手寫:FAQ How do I provide syntax coloring  in an editor?

Emacs Mode: ModeTutorial

每一類各自有各自的優(yōu)缺點(diǎn)和編寫難度。但是,總的來說,沒有一個方式是簡單的。

正則實(shí)現(xiàn)語法分析

對于正則方式來說,不論是 Sublime Text 還是 Textmate 及基于 Textmate 語法規(guī)則的 VS  Code,它們都有一個顯著的缺點(diǎn):長,如 VCode 的java.tmLanguage.json,從長度上來說,我看到的這個版本有 1831  行。表達(dá)方式也有些繁瑣:

"comments": { "patterns": [ { "captures": { "0": { "name": "punctuation.definition.comment.java" } }, "match": "/\\*\\*/", "name": "comment.block.empty.java" }, { "include": "#comments-inline" } ] },

其中還有各種 include 關(guān)系等。對于 Sublime Text 也是類似的:

comments: - match: /\*\*/ scope: comment.block.empty.java punctuation.definition.comment.java - include: scope:text.html.javadoc - include: comments-inline

看了看,是不是會懷疑他們建立了語法同盟。

但是呢,yaml 和 json 是一個編程語言無關(guān)的東西。所以,VS Code 和 Atom 可以基于 Textmate  語法規(guī)則,快速建立對于主流語言的詞法分析,從而建立了語法高亮的支持。

我們也可以說 BNF 是一種編程語言無關(guān)的東西。但是,實(shí)際上在我們操作的時(shí)候,就會加入一些編程語言特定的要素。

語法分析器分析

由于先前編寫系統(tǒng)分析工具 Coca 和通用語法分析器 Chapi ,我對于 BNF  的詞法也是頗為上手的——實(shí)際上不難。唯一麻煩的地方就是,寫完之后,我們要編寫代碼做一些轉(zhuǎn)換,所以讓我們來看看 Jetbrians 插件的示例:

COMMENT = 'regexp://[^\r\n]*' BLOCK_COMMENT = 'regexp:[/][*][^*]*[*]+([^/*][^*]*[*]+)*[/]'

這一點(diǎn)上和 antlr 沒有太大的區(qū)別:

WS: [ \t\r\n\u000C]+ -> channel(HIDDEN); COMMENT: '/*' .*? '*/' -> channel(HIDDEN); LINE_COMMENT: '//' ~[\r\n]* -> channel(HIDDEN);

然后,就是設(shè)計(jì)和分析詞法了:

functionParameters ::= LPAREN inputParameters RPAREN outputParameters? | IN SUB GT inputParameters | outputParameters

接著,在 IDEA 里面,我們可以通過這個 BNF 文件生成對應(yīng)的 Lexer 文件和代碼等。對于使用 Antlr 編寫的詞法來說,Java  部分的代碼規(guī)模也就在 800 左右。

不過呢,從兩者的閱讀體驗(yàn)對比來看,顯然 BNF 會更加友好一點(diǎn)。

自制 DSL 語法解析

頗為遺憾的是,我尚未寫過任何的 Vim 插件,好在我還知道 Vim 是如何退出來的。我使用 Vim 作為 git 的 editor,還熟知一些 Vim  編輯的常用快捷鍵。所以,語法高亮這一部分主要是參考 Vim 的文檔編寫和代碼示例。這里我找到了一個不錯的中文翻譯:語法高亮

總的來說,語法規(guī)則就是: syn vim關(guān)鍵字 匹配規(guī)則,如:

syn region rustCommentLine start="//" end="$" contains=rustTodo,@Spell syn region rustCommentLineDoc start="//\%(//\@!\|!\)" end="$" contains=rustTodo,@Spell syn region rustCommentLineDocError start="//\%(//\@!\|!\)" end="$" contains=rustTodo,@Spell contained syn region rustCommentBlock matchgroup=rustCommentBlock start="/\*\%(!\|\*[*/]\@!\)\@!" end="\*/" contains=rustTodo,

看上去依舊是正則匹配,如 Float:

syn match rustFloat display "\<[0-9][0-9_]*\%(\.[0-9][0-9_]*\)\%([eE][+-]\=[0-9_]\+\)\=\(f32\|f64\)\=" syn match rustFloat display "\<[0-9][0-9_]*\%(\.[0-9][0-9_]*\)\=\%([eE][+-]\=[0-9_]\+\)\(f32\|f64\)\=" syn match rustFloat display "\<[0-9][0-9_]*\%(\.[0-9][0-9_]*\)\=\%([eE][+-]\=[0-9_]\+\)\=\(f32\|f64\)"

不過,從算法形式上來說,完勝 Textmate 和 Sublime,畢竟是高級的 DSL。

編程語言語法解析

Emacs 的 mode 里包含了對于語法高亮的處理,于是為了這個高亮,我們需要寫寫 emacs lisp 代碼。如:

(defvar rust-formatting-macro-opening-re "[[:space:]\n]*[({[][[:space:]\n]*" "Regular expression to match the opening delimiter of a Rust formatting macro.")  (defvar rust-start-of-string-re "\\(?:r#*\\)?\"" "Regular expression to match the start of a Rust raw string.")

對于 Eclipse 來說,這個過程就更加麻煩了。

語言的高級支持

在我們實(shí)現(xiàn)了開發(fā)工具的詞法分析接口之后,我們就能按不同的  IDE/編輯器所定義的接口,進(jìn)行定制了。這是一個繁雜,而又充滿挑戰(zhàn)的工作。對于不同的工具來說,它們的接口相關(guān)也甚多。我也并非都能一一了解  API,所以只能簡單的以 IDEA 作為一個示例來展示。主要原因大概有兩個:1. 我日常使用的是 Jetbrains 相關(guān)的 IDE;2.  我已經(jīng)有一部分代碼了。

語法高亮

在進(jìn)行了復(fù)雜的語法分析之后,接著,我們就可以快速進(jìn)入一個簡單的環(huán)節(jié),對代碼進(jìn)行高亮。關(guān)于高亮的話,我們可以快速進(jìn)行一個分類:

  • 關(guān)鍵詞。即編程語言的關(guān)鍵詞,如 C 語言中的 32 個關(guān)鍵詞。

  • 標(biāo)識符。用戶定義的字符串,如變量名、結(jié)構(gòu)體名、函數(shù)名等等。

  • 特殊詞法。

  • 重要的詞法。根據(jù)需要,可以針對于函數(shù)名、靜態(tài)函數(shù)名等進(jìn)行標(biāo)識,以提升識別度。

如下是 Go 語言的一些關(guān)鍵詞:

(defconst go-mode-keywords '("break" "default" "func" "interface" "select" "case" "defer" "go" "map" "struct" "chan" "else" "goto" "package" "switch" "const" "fallthrough" "if" "range" "type" "continue" "for" "import" "return" "var") "All keywords in the Go language. Used for font locking.")

所以,在這個場景之下,不論是何種的 IDE 又或者是編輯器都可以快速實(shí)現(xiàn)。

跳轉(zhuǎn) goto

不同開發(fā)工具,有各種的跳轉(zhuǎn)規(guī)則,不同的語言也有各自的跳轉(zhuǎn)方式。如 Emacs 的 go-mode 就定義了一系列的跳轉(zhuǎn):

(let ((m (define-prefix-command 'go-goto-map))) (define-key m "a" #'go-goto-arguments) (define-key m "d" #'go-goto-docstring) (define-key m "f" #'go-goto-function) (define-key m "i" #'go-goto-imports) (define-key m "m" #'go-goto-method-receiver) (define-key m "n" #'go-goto-function-name) (define-key m "r" #'go-goto-return-values))

而 IDEA 也提供了一系列接口來實(shí)現(xiàn)類似的功能,如:

gotoActionAliasMatcher gotoClassContributor gotoSymbolContributor gotoFileContributor gotoRelatedProvider

我們只需要分析光標(biāo)符所在的位置,其所定義的語法,如 IDEA 里是 PSI,再實(shí)現(xiàn)對應(yīng)的邏輯即可。如:

@Override public @NotNull NavigationItem[] getItemsByName(String name, String pattern, Project project, boolean includeNonProjectItems) { List<CharjStructDeclaration> properties = findStructByKey(project, name); return properties.toArray(new NavigationItem[properties.size()]); }

這里定義的是數(shù)據(jù)結(jié)構(gòu)的導(dǎo)航。當(dāng)我們按下快捷鍵的時(shí)候,會傳入 name、pattern 等信息。接著,從所有相關(guān)的文件(VirtualFile)中尋找對應(yīng)的  struct,返回即可。

自動填充

主要可以分為兩類,一類是:代碼段(Snippets),一類是:自動填充(Completion)

好像也沒啥說的,就是綁定在特定關(guān)鍵字上的內(nèi)容。

其它

剩下的就是一些比較有意思的功能,諸如于:

  • fileType。文件圖標(biāo)支持。即某一類型的文件,使用特定的圖標(biāo)來展示。

  • commet 。即按下注釋的快捷鍵,能快速的注釋和反注釋代碼。

  • line marker。IDEA 提供的功能,用于在行上通過圖標(biāo)來展示特定的功能。

  • folding。提供特定的代碼段的折疊功能。

  • 數(shù)據(jù)視圖。展示特定數(shù)據(jù)結(jié)構(gòu)關(guān)系及參數(shù)等的視圖。

  • &hellip;&hellip;

到此,相信大家對“如何理解編程語言的IDE支持”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

ide
AI