SMIE 内置一个预定义的词法分析器,它按如下方式使用语法表:
任意具有单词或符号语法的字符序列会被视为一个标记,
任意具有标点符号语法的字符序列同样如此。
这个默认词法分析器通常是不错的起点,
但对任意特定语言而言很少能完全适用。
例如,它会将 "2,+3" 拆分为 3 个标记:"2"、",+" 和 "3"。
若要向 SMIE 描述你所用语言的词法规则,需要两个函数: 一个用于获取下一个标记,另一个用于获取上一个标记。 这些函数通常会先跳过空白符与注释, 再查看下一段文本是否为特殊标记。 若是,则应跳过该标记并返回其描述。 通常直接返回从缓冲区提取的字符串即可, 但也可返回任意自定义内容。示例如下:
(defvar sample-keywords-regexp
(regexp-opt '("+" "*" "," ";" ">" ">=" "<" "<=" ":=" "=")))
(defun sample-smie-forward-token ()
(forward-comment (point-max))
(cond
((looking-at sample-keywords-regexp)
(goto-char (match-end 0))
(match-string-no-properties 0))
(t (buffer-substring-no-properties
(point)
(progn (skip-syntax-forward "w_")
(point))))))
(defun sample-smie-backward-token ()
(forward-comment (- (point)))
(cond
((looking-back sample-keywords-regexp (- (point) 2) t)
(goto-char (match-beginning 0))
(match-string-no-properties 0))
(t (buffer-substring-no-properties
(point)
(progn (skip-syntax-backward "w_")
(point))))))
注意这些词法分析器在遇到括号时会返回空串。
原因是 SMIE 会自动处理语法表中定义的括号。
更具体地说,若词法分析器返回 nil 或空串,
SMIE 会依据语法表将对应文本当作 S 表达式处理。