Elisp: Syntax Table Tutorial
Emacs has a concept of Syntax Table. The basic idea is, each character (every Unicode character), is categorized into a class. Classes are: letters, punctuations, brackets, char for programing language identifiers, comment character, string delimiters, etc.
Syntax table is heavily used in emacs. For example,
- Most cursor movement commands rely on syntax table. For example, when you Alt+x
forward-word【Alt+f】, emacs will move cursor until it reaches a character that's not in the “word” class.
- Syntax coloring of strings and comments rely on syntax table. [see Elisp: How to Color Comment in Major Mode]
- Programing language comment/uncomment command also relies on syntax table. [see Elisp: How to Write Comment Command in Major Mode]
- Lisp mode's parenthesis navigation also depends on syntax table. [see Emacs: Navigate Lisp Code as Tree]
Each buffer has its own version of syntax table. Typically, when a major mode is activated, it changes the current buffer's syntax table.
View Current Syntax Table
describe-syntax to show current buffer's syntax table.
Each syntax class is identified by a 1-char code.
Here's the most important character classes and their 1-char code.
|word. (typically the alphabets A to Z, and other languages's letters and Chinese characters.)|
|symbol. (char of symbol class, plus chars of “word” class, together is programing language “identifier” chars.)|
For complete list, see (info "(elisp) Syntax Class Table")
A syntax descriptor is a lisp string that specifies a syntax class (the 1-char code), a matching character (used only for characters in the bracket class) and flags (used for comment delimiters).
Syntax Descriptor with the function
modify-syntax-entry, when you create a syntax table. Here's a quick example.
;; make period to have syntax class of symbol (modify-syntax-entry ?. "_" my-syn-table) ;; make the «French double quote» to be brackets (modify-syntax-entry ?« "(»" my-syn-table) (modify-syntax-entry ?» ")«" my-syn-table) ;; make char's syntax for C++ style comment “// …” (modify-syntax-entry ?/ ". 12b" my-syn-table) (modify-syntax-entry ?\n "> b" my-syn-table)
Now let's look at the line
(modify-syntax-entry ?. "_" my-syn-table)
modify-syntax-entry take 3 args.
- A character. [see Elisp: Character Type]
- A syntax descriptor string.
- A variable of syntax table.
?. is the character period ..
"_" is the syntax descriptor string. It means the period character is in symbol class.
Now let's look at this line:
(modify-syntax-entry ?« "(»" my-syn-table)
It means, the character « is in the class of opening bracket, and its matching character is ».
Now, this line:
(modify-syntax-entry ?/ ". 12b" my-syn-table)
Let's look at the syntax descriptor string
". 12b". It means:
- The first character in syntax descriptor is period. It means the slash / character is punctuation class.
- The second character in syntax descriptor is space. Since it's not in bracket class, so there's no matching character, space character is used to mean none.
- The rest characters in syntax descriptor is flags. They are used for comment class character. Because the comment delimiter characters in programing languages is complex. The char usually have multiple purposes, and also depends on whether the character is repeated, or if it can be nested.
The flags in syntax descriptor is very complex. See elisp manual (info "(elisp) Syntax Flags")
For practical examples of using the syntax flags for comments, see Elisp: How to Color Comment in Major Mode
Basic Facts of Syntax Table
- Syntax table is a lookup table, and is implemented as a special vector. You use
make-syntax-tableand others to create it.
- Each buffer has its own syntax table. (so, it's like a buffer-local variable, but there's no variable.)
set-syntax-tableto set a syntax table for current buffer.
Create Syntax Table
Here's typical way to create a syntax table.
;; typical way to create and set syntax table (defvar xpy-mode-syntax-table nil "Syntax table for `xpy-mode'.") (setq xpy-mode-syntax-table (let ( (synTable (make-syntax-table))) ;; set/modify each char's class (modify-syntax-entry ?# "<" synTable) (modify-syntax-entry ?\n ">" synTable) ;; more lines here ... ;; return it synTable)) ;; then, have this line inside your mode definition. So that, when user calls your major mode, it will set syntax table for whatever is the current buffer of user (set-syntax-table xpy-mode-syntax-table)
Standard Syntax Table
standard-syntax-table returns the standard syntax table.
Standard syntax table is the syntax table used by
[see Emacs: What's Major Mode]
Every syntax table is derived from standard syntax table.
Syntax Table Inheritance
Emacs syntax table has inheritance. That is, each syntax table you create inherits a parent syntax table. You do not need to set every character's syntax class. When a syntax table does not have entry for a character, it uses the parent table.
Syntax table commands have optional parameter for a table name of a parent table. When not specified, the parent syntax table is the standard syntax table.
Writing Major Mode
- How to Write a Emacs Major Mode for Syntax Coloring
- Elisp: html6-mode
- Elisp: Font Lock Mode Basics
- Elisp: How to Define Face
- Elisp: How to Color Comment in Major Mode
- Elisp: How to Write Comment Command in Major Mode
- Elisp: How to Write Your Own Comment Command from Scratch
- Elisp: How to Write Keyword Completion Command
- Elisp: How to Create Keymap for Major Mode
- Elisp: Abbrev, Template, for Major Mode
- Elisp: Text Properties
- Elisp: Overlay Highlighting
- Emacs: Lookup Google, Dictionary, Documentation
- Elisp: Syntax Table Tutorial
If you have a question, put $5 at patreon and message me.