« ^ »
[WIP]

Emacsのsyntax-tableを扱う

所要時間: 約 5分

多くのテキストエディタや統合開発環境は、既に各プログラミング言語ごとにシンタックスハイライトしたり、補完などの機能が組み込まれている。そのため、特に何も考える事なくそれらの機能を使えるだろう。または使いたいプログラミング言語用の拡張をインストールする事で、その機能を使えるようになる。それはとても便利で良い事だけれど、独自のプログラミング言語(他にも独自の構文を持つDSLなど)を自作した場合、それに対する言語的サポートは当然どこにもなく、自分で実装するしかない。

ただ、テキストエディタや統合開発環境には、それらを自作する機構も含まれている事が多いだろう。Emacsの場合、いくつかの機能を組み合せて機能を構成する。その1つとしてシンタッステーブルを使う。これはバッファ上の文字の並びから、その部分が何を表わしているかを決める。今回はこの機能を見ていく。

シンタックステーブルとは

シンタックステーブルはEmacsのバッファ上の文字の特定のパターンに対し、意味付けしfaceを設定する役割を持つ。Emacsは、このデータ構造を利用する事で、プログラミング言語の構文を解釈し、シンタックスハイライトを実現する。 syntax-table の実体は char-table らしい。

https://www.gnu.org/software/emacs/manual/html_node/elisp/Syntax-Tables.html

新しいシンタックステーブルを作る

新しいシンタックステーブルは make-syntax-table 関数によりを作る事ができる。

(setq example-syntax-table (make-syntax-table))

このシンタックステーブルを set-syntax-table 関数で登録する。

(set-syntax-table example-syntax-table)

このシンタックテーブルの登録は、通常メジャーモードの開始時に行うようにメジャーモードの定義に含める。

シンタックステーブルを変更する

シンタックステーブルは、 modify-syntax-entry 関数を使う事で、設定を変更する事ができる。この関数は第1引数 CHAR 、第2引数 NEWENTRY 、 第3引数 SYNTAX-TABLE (省略可能)を指定する。これは CHAR で指定した対象に対して NEWENTRY のルールを SYNTAX-TABLE に設置する。

usage: (modify-syntax-entry CHAR NEWENTRY &optional SYNTAX-TABLE)

シンタックステーブルにコメントを設定する

ここでは例としてコメントの設定をシンタックステーブルに追加する。

コメント1

;; # コメント
(let ((table (make-syntax-table)))
  (modify-syntax-entry ?# "<" table)
  (modify-syntax-entry ?\n ">" table)
  (set-syntax-table table)
  (font-lock-mode))\

コメント2

;; // コメント
(let ((table (make-syntax-table text-mode-syntax-table)))
  (modify-syntax-entry ?/ ". 12" table)
  (modify-syntax-entry ?\n ">" table)
  (set-syntax-table table)
  (font-lock-mode))

コメント3

;; /* コメント */
(let ((table (make-syntax-table text-mode-syntax-table)))
  (modify-syntax-entry ?/ ". 14" table)
  (modify-syntax-entry ?* ". 23" table)
  (set-syntax-table table)
  (font-lock-mode))

コメント4

;; ; コメント
(let ((table (make-syntax-table text-mode-syntax-table)))
  (modify-syntax-entry ?\; "<" table)
  (modify-syntax-entry ?\n ">" table)
  (set-syntax-table table)
  (font-lock-mode))

コメント5

;; <-- コメント -->
(let ((table (make-syntax-table)))
  (modify-syntax-entry ?< ". 1" table)
  (modify-syntax-entry ?> ". 4" table)
  (modify-syntax-entry ?- ". 23" table)
  (set-syntax-table table)
  (font-lock-mode))

NEWENTRYで使用できる最初の文字

NEWENTRY には次の文字列を指定できる。

文字説明
Space or -whitespace syntax.空白
_symbol constituent.シンボル
(open-parenthesis.開きカッコ
"string quote.文字列クォート
$paired delimiter.対になる区切り文字
<comment starter.コメント開始
/character-quote.文字クォート
PIPEgeneric string fence.文字列フェンス
wword constituent.単語
.punctuation.区切り文字
)close-parenthesis.閉じカッコ
\escape.エスケープ
\\='expression quote or prefix operator.式の前に付けるオペレータ
>comment ender.コメント終了
@inherit from parent table.親テーブルを継承
!generic comment fence.コメントフェンス

modify-syntax-entryのコメントの日本語訳

modify-syntax-entryemacs/src/syntax.c に定義されており、そこに詳しい説明がdocstringとして記述されている。それを日本語訳した。

emacs/src/syntax.c

Set syntax for character CHAR according to string NEWENTRY.

n 文字列NEWENTRYに従って文字CHARの構文を設定します。

The syntax is changed only for table SYNTAX-TABLE, which defaults to the current buffer's syntax table.

デフォルトではカレントバッファに設定されているシンタックステーブルの設定のみ変更します。

CHAR may be a cons (MIN . MAX), in which case, syntaxes of all characters in the range MIN to MAX are changed.

CHARが文字ではなく(MIN . MAX)という形式のconsであれば、MINからMAXの範囲のすべての文字の構文が変更されます。

The first character of NEWENTRY should be one of the following:

NEWENTRYの最初の文字は、次のいずれかである必要があります。

  Space or -  whitespace syntax.    w   word constituent.
  _           symbol constituent.   .   punctuation.
  (           open-parenthesis.     )   close-parenthesis.
  "           string quote.         \\   escape.
  $           paired delimiter.     \\='   expression quote or prefix operator.
  <           comment starter.      >   comment ender.
  /           character-quote.      @   inherit from parent table.
  |           generic string fence. !   generic comment fence.

Only single-character comment start and end sequences are represented thus.

したがって、1文字のコメントの開始シーケンスと終了シーケンスのみが表されます。

Two-character sequences are represented as described below.

2文字のシーケンスは、以下のように表されます。

The second character of NEWENTRY is the matching parenthesis, used only if the first character is `(' or `)'.

NEWENTRYの2番目の文字は一致する括弧であり、最初の文字が `( 'または`)'の場合にのみ使用されます。

Any additional characters are flags.

追加の文字はフラグです。

Defined flags are the characters 1, 2, 3, 4, b, p, and n.

定義されているフラグは、文字1、2、3、4、b、p、およびnです。

1 means CHAR is the start of a two-char comment start sequence.

1は、CHARが2文字のコメント開始シーケンスの開始であることを意味します。

2 means CHAR is the second character of such a sequence.

2は、CHARがそのようなシーケンスの2番目の文字であることを意味します。

3 means CHAR is the start of a two-char comment end sequence.

3は、CHARが2文字のコメント終了シーケンスの開始であることを意味します。

4 means CHAR is the second character of such a sequence.

4は、CHARがそのようなシーケンスの2番目の文字であることを意味します。

There can be several orthogonal comment sequences. This is to support language modes such as C++. By default, all comment sequences are of style a, but you can set the comment sequence style to b (on the second character of a comment-start, and the first character of a comment-end sequence) and/or c (on any of its chars) using this flag

いくつかの直交するコメントシーケンスが存在する可能性があります。これは、C ++などの言語モードをサポートするためです。デフォルトでは、すべてのコメントシーケンスのスタイルはaですが、コメントシーケンスのスタイルをb(コメント開始シーケンスの2番目の文字、およびコメント終了シーケンスの最初の文字)および/またはc(任意のその文字の)このフラグを使用する:

b means CHAR is part of comment sequence b.

bは、CHARがコメントシーケンスbの一部であることを意味します。

c means CHAR is part of comment sequence c.

cは、CHARがコメントシーケンスcの一部であることを意味します。

n means CHAR is part of a nestable comment sequence.

nは、CHARがネスト可能なコメントシーケンスの一部であることを意味します。

p means CHAR is a prefix character for `backward-prefix-chars';

pは、CHARが `backward-prefix-chars 'のプレフィックス文字であることを意味します。

such characters are treated as whitespace when they occur between expressions.

このような文字は、式の間にある場合は空白として扱われます。