Elisp: Syntax Table
What is Syntax Table
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, programing language identifiers, comment character, string delimiters, etc.
Where is Syntax Table Used
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]
Syntax Table is Local to Buffer
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. (characters of symbol class, plus chars of “word” class, together is programing language identifier characters.)|
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).
(info "(elisp) Syntax Descriptors")
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 whose value is a 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
- The function
standard-syntax-tablereturns the standard syntax table.
- Standard syntax table is the syntax table used by
fundamental-mode. [see Emacs: What is 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.
(info "(elisp) Syntax Table Functions")