1 -- Copyright 2014-2015 Joshua Krämer. See LICENSE.
3 -- This lexer follows the TCL dodekalogue (http://wiki.tcl.tk/10259).
4 -- It is based on the previous lexer by Mitchell.
6 local l
= require('lexer')
7 local token
, word_match
= l
.token
, l
.word_match
8 local P
, R
, S
= lpeg
.P
, lpeg
.R
, lpeg
.S
10 local M
= {_NAME
= 'tcl'}
13 local whitespace
= token(l
.WHITESPACE
, l
.space^
1)
15 -- Separator (semicolon).
16 local separator
= token(l
.CLASS
, P(';'))
19 local braces
= token(l
.KEYWORD
, S('{}'))
20 local quotes
= token(l
.FUNCTION
, '"')
21 local brackets
= token(l
.VARIABLE
, S('[]'))
24 local expander
= token(l
.LABEL
, P('{*}'))
26 -- Variable substitution.
27 local variable
= token(l
.STRING
, '$' * (l
.alnum
+ '_' + P(':')^
2)^
0)
29 -- Backslash substitution.
30 local backslash
= token(l
.TYPE
, '\\' * ((l
.digit
* l
.digit^
-2) +
31 ('x' * l
.xdigit^
1) + ('u' * l
.xdigit
* l
.xdigit^
-3) +
32 ('U' * l
.xdigit
* l
.xdigit^
-7) + P(1)))
35 local comment
= token(l
.COMMENT
, '#' * P(function(input
, index
)
37 while i
> 0 and input
:find('^[ \t]', i
) do i
= i
- 1 end
38 if i
< 1 or input
:find('^[\r\n;]', i
) then return index
end
39 end) * l
.nonnewline^
0)
42 {'whitespace', whitespace
},
44 {'separator', separator
},
45 {'expander', expander
},
48 {'brackets', brackets
},
49 {'variable', variable
},
50 {'backslash', backslash
},
54 _patterns
= {'[{}]', '#'},
55 [l
.KEYWORD
] = {['{'] = 1, ['}'] = -1},
56 [l
.COMMENT
] = {['#'] = l
.fold_line_comments('#')}