-- Copyright 2014-2017 Joshua Krämer. See LICENSE.
-- Tcl LPeg lexer.
-- This lexer follows the TCL dodekalogue (http://wiki.tcl.tk/10259).
-- It is based on the previous lexer by Mitchell.

local l = require('lexer')
local token, word_match = l.token, l.word_match
local P, R, S = lpeg.P, lpeg.R, lpeg.S

local M = {_NAME = 'tcl'}

-- Whitespace.
local whitespace = token(l.WHITESPACE, l.space^1)

-- Separator (semicolon).
local separator = token(l.CLASS, P(';'))

-- Delimiters.
local braces = token(l.KEYWORD, S('{}'))
local quotes = token(l.FUNCTION, '"')
local brackets = token(l.VARIABLE, S('[]'))

-- Argument expander.
local expander = token(l.LABEL, P('{*}'))

-- Variable substitution.
local variable = token(l.STRING, '$' * (l.alnum + '_' + P(':')^2)^0)

-- Backslash substitution.
local backslash = token(l.TYPE, '\\' * ((l.digit * l.digit^-2) +
                        ('x' * l.xdigit^1) + ('u' * l.xdigit * l.xdigit^-3) +
                        ('U' * l.xdigit * l.xdigit^-7) + P(1)))

-- Comment.
local comment = token(l.COMMENT, '#' * P(function(input, index)
  local i = index - 2
  while i > 0 and input:find('^[ \t]', i) do i = i - 1 end
  if i < 1 or input:find('^[\r\n;]', i) then return index end
end) * l.nonnewline^0)

M._rules = {
  {'whitespace', whitespace},
  {'comment', comment},
  {'separator', separator},
  {'expander', expander},
  {'braces', braces},
  {'quotes', quotes},
  {'brackets', brackets},
  {'variable', variable},
  {'backslash', backslash},
}

M._foldsymbols = {
  _patterns = {'[{}]', '#'},
  [l.KEYWORD] = {['{'] = 1, ['}'] = -1},
  [l.COMMENT] = {['#'] = l.fold_line_comments('#')}
}

return M
