-- Copyright 2006-2019 Mitchell mitchell.att.foicica.com. See License.txt. -- CoffeeScript LPeg lexer. local lexer = require('lexer') local token, word_match = lexer.token, lexer.word_match local P, S = lpeg.P, lpeg.S local lex = lexer.new('coffeescript', {fold_by_indentation = true}) -- Whitespace. lex:add_rule('whitespace', token(lexer.WHITESPACE, lexer.space^1)) -- Keywords. lex:add_rule('keyword', token(lexer.KEYWORD, word_match[[ all and bind break by case catch class const continue default delete do each else enum export extends false finally for function if import in instanceof is isnt let loop native new no not of off on or return super switch then this throw true try typeof unless until var void when while with yes ]])) -- Fields: object properties and methods. lex:add_rule('field', token(lexer.FUNCTION, '.' * (S('_$') + lexer.alpha) * (S('_$') + lexer.alnum)^0)) -- Identifiers. lex:add_rule('identifier', token(lexer.IDENTIFIER, lexer.word)) -- Strings. local regex_str = #P('/') * lexer.last_char_includes('+-*%<>!=^&|?~:;,([{') * lexer.delimited_range('/', true) * S('igm')^0 lex:add_rule('string', token(lexer.STRING, lexer.delimited_range("'") + lexer.delimited_range('"')) + token(lexer.REGEX, regex_str)) -- Comments. local block_comment = '###' * (lexer.any - '###')^0 * P('###')^-1 local line_comment = '#' * lexer.nonnewline_esc^0 lex:add_rule('comment', token(lexer.COMMENT, block_comment + line_comment)) -- Numbers. lex:add_rule('number', token(lexer.NUMBER, lexer.float + lexer.integer)) -- Operators. lex:add_rule('operator', token(lexer.OPERATOR, S('+-/*%<>!=^&|?~:;,.()[]{}'))) return lex