91 lines
3.0 KiB
Lua
91 lines
3.0 KiB
Lua
|
-- Copyright (c) 2014-2019 Piotr Orzechowski [drzewo.org]. See License.txt.
|
||
|
-- Xtend LPeg lexer.
|
||
|
|
||
|
local lexer = require('lexer')
|
||
|
local token, word_match = lexer.token, lexer.word_match
|
||
|
local P, R, S = lpeg.P, lpeg.R, lpeg.S
|
||
|
|
||
|
local lex = lexer.new('xtend')
|
||
|
|
||
|
-- Whitespace.
|
||
|
local ws = token(lexer.WHITESPACE, lexer.space^1)
|
||
|
lex:add_rule('whitespace', ws)
|
||
|
|
||
|
-- Classes.
|
||
|
lex:add_rule('class', token(lexer.KEYWORD, P('class')) * ws^1 *
|
||
|
token(lexer.CLASS, lexer.word))
|
||
|
|
||
|
-- Keywords.
|
||
|
lex:add_rule('keyword', token(lexer.KEYWORD, word_match[[
|
||
|
-- General.
|
||
|
abstract annotation as case catch class create def default dispatch do else
|
||
|
enum extends extension final finally for if implements import interface
|
||
|
instanceof it new override package private protected public return self static
|
||
|
super switch synchronized this throw throws try typeof val var while
|
||
|
-- Templates.
|
||
|
-- AFTER BEFORE ENDFOR ENDIF FOR IF SEPARATOR
|
||
|
-- Literals.
|
||
|
true false null
|
||
|
]]))
|
||
|
|
||
|
-- Types.
|
||
|
lex:add_rule('type', token(lexer.TYPE, word_match[[
|
||
|
boolean byte char double float int long short void
|
||
|
Boolean Byte Character Double Float Integer Long Short String
|
||
|
]]))
|
||
|
|
||
|
-- Functions.
|
||
|
lex:add_rule('function', token(lexer.FUNCTION, lexer.word) * #P('('))
|
||
|
|
||
|
-- Identifiers.
|
||
|
lex:add_rule('identifier', token(lexer.IDENTIFIER, lexer.word))
|
||
|
|
||
|
-- Templates.
|
||
|
lex:add_rule('template', token('template', "'''" * (lexer.any - P("'''"))^0 *
|
||
|
P("'''")^-1))
|
||
|
lex:add_style('template', lexer.STYLE_EMBEDDED)
|
||
|
|
||
|
-- Strings.
|
||
|
lex:add_rule('string', token(lexer.STRING, lexer.delimited_range("'", true) +
|
||
|
lexer.delimited_range('"', true)))
|
||
|
|
||
|
-- Comments.
|
||
|
local line_comment = '//' * lexer.nonnewline_esc^0
|
||
|
local block_comment = '/*' * (lexer.any - '*/')^0 * P('*/')^-1
|
||
|
lex:add_rule('comment', token(lexer.COMMENT, line_comment + block_comment))
|
||
|
|
||
|
-- Numbers.
|
||
|
local small_suff = S('lL')
|
||
|
local med_suff = S('bB') * S('iI')
|
||
|
local large_suff = S('dD') + S('fF') + S('bB') * S('dD')
|
||
|
local exp = S('eE') * lexer.digit^1
|
||
|
|
||
|
local dec_inf = ('_' * lexer.digit^1)^0
|
||
|
local hex_inf = ('_' * lexer.xdigit^1)^0
|
||
|
local float_pref = lexer.digit^1 * '.' * lexer.digit^1
|
||
|
local float_suff = exp^-1 * med_suff^-1 * large_suff^-1
|
||
|
|
||
|
local dec = lexer.digit * dec_inf * (small_suff^-1 + float_suff)
|
||
|
local hex = lexer.hex_num * hex_inf * P('#' * (small_suff + med_suff))^-1
|
||
|
local float = float_pref * dec_inf * float_suff
|
||
|
|
||
|
lex:add_rule('number', token(lexer.NUMBER, float + hex + dec))
|
||
|
|
||
|
-- Annotations.
|
||
|
lex:add_rule('annotation', token('annotation', '@' * lexer.word))
|
||
|
lex:add_style('annotation', lexer.STYLE_PREPROCESSOR)
|
||
|
|
||
|
-- Operators.
|
||
|
lex:add_rule('operator', token(lexer.OPERATOR, S('+-/*%<>!=^&|?~:;.()[]{}#')))
|
||
|
|
||
|
-- Error.
|
||
|
lex:add_rule('error', token(lexer.ERROR, lexer.any))
|
||
|
|
||
|
-- Fold points.
|
||
|
lex:add_fold_point(lexer.OPERATOR, '{', '}')
|
||
|
lex:add_fold_point(lexer.COMMENT, '/*', '*/')
|
||
|
lex:add_fold_point(lexer.COMMENT, '//', lexer.fold_line_comments('//'))
|
||
|
lex:add_fold_point(lexer.KEYWORD, 'import', lexer.fold_line_comments('import'))
|
||
|
|
||
|
return lex
|