简介
GNU Source-highlight可以将C、Java等语言的源代码转换成HTML、LaTeX等格式的文档,并带有语法高亮的效果。
它主要用正则表达式来定义(或识别)语言的各类元素,并用CSS样式表为各类元素指定样式。
定义某一语言的所有正则表达式放在一个.lang文件中,如c.lang、java.lang等。因此,一个.lang文件定义了一种语言。下面就讲解如何编写.lang文件。
定义语言
基本语句
语法
element = 'regular expression'
element
定义元素名,常用的有以下几类元素:
keyword
:关键字type
:类型名variable
:变量名string
:字符串number
:数字function
:函数名comment
:注释
'regular expression'
识别该类元素的正则表达式。表达式必须用双引号(
"
)、单引号('
)或反引号(`
)包围,它们的区别如下:"expression"
普通字符串。特殊字符
|
用于选择。'expression'
正则表达式,不支持捕获分组。
`expression`
正则表达式,支持捕获分组。
例子
定义C语言的关键字:
keyword = "break|case|catch|cdecl|const|continue|default|do", "else|enum|extern|for|goto|if|pascal", "register|return|sizeof|static|struct", "switch|typedef|union|volatile|while"
定义C语言的数字:
number = '\<[+-]?((0x[[:xdigit:]]+)|(([[:digit:]]*\.)?[[:digit:]]+([eE][+-]?[[:digit:]]+)?))u?((int(?:8|16|32|64))|L)?\>'
注意
对同一元素的多条定义语句会累加,而不会覆盖。例如,下面的语句等效于例1:
keyword = "break|case|catch|cdecl|const|continue|default|do" keyword = "else|enum|extern|for|goto|if|pascal" keyword = "register|return|sizeof|static|struct" keyword = "switch|typedef|union|volatile|while"
语句和正则表达式中的换行符会被忽略,因此可以适当添加换行来提高代码可读性。例如,下面的语句等效于例2:
number = '\<[+-]? ((0x[[:xdigit:]]+)| (([[:digit:]]*\.)?[[:digit:]]+ ([eE][+-]?[[:digit:]]+)?))u?((int(?:8|16|32|64))|L)?\>'
行中的
#
及其后面的字符为注释。若多条语句匹配同一处代码,则先出现的语句优先级更高。例如,下面的定义中,
keyword
和variable
都匹配字符串"while"
,但"while"
是keyword
元素。keyword = "switch|typedef|union|volatile|while" variable = '[a-zA-Z0-9_]+'
start语句
语法
element start 'regexp'
表示element
元素的范围从'regexp'
开始直到行末。
例子
定义C++风格的注释:
comment start "//"
delim语句
语法
element delim 'left delim' 'right delim' [escape "escape-character"] [multiline] [nested]
表示element
元素的范围从'left delim'
开始,到'right delim'
结束。
escape "escape-character"
可选项,表示转义字符。例如,要定义C语言字符串,从
"
开始,到"
结束。在字符串中间要表示"
,则要用转义字符\
来转义:\"
。字符串的定义见例1.multiline
可选项,表示元素的范围可以跨行。
nested
可选项,表示元素可以嵌套。
例子
定义C语言的字符串:
string delim "\"" "\"" escape "\\"
定义C风格的注释:
comment delim "/*" "*/" multiline nested
include语句
语法
include "another_file.lang"
用于将其他.lang文件包含进来,类似于C语言的#include
语句。它有助于定义语句的重用,例如,C、C++和Java的注释都相同,可以将注释元素的定义放到c_comment.lang文件里,然后在各语言的定义文件里写一条包含语句即可。
例子
将C/C++风格的注释包含进java.lang中:
# java.lang include "c_comment.lang"
state/environment语句
有些元素只在其他元素内部才有意义,例如想对C语言注释内的URL着色时,URL元素必须出现在注释内部。state/environment语句可以解决这种问题。
语法
state|environment <standard definition> begin <other definitions> end
由standard definition
定义的元素的范围构成了一个环境。在该环境内部时,other definitions
会生效,而环境外面的定义语句会失效。
state
与environment
的区别是:state内未匹配的元素不着色,而environment内的未匹配的元素按standard definiton
的元素样式着色。
该语句可以嵌套。
例子
定义注释内的URL:
environment comment delim "/*" "*/" multiline nested begin include "url.lang" end