logo

oasis-root

Compiled tree of Oasis Linux based on own branch at <https://hacktivis.me/git/oasis/> git clone https://anongit.hacktivis.me/git/oasis-root.git

gleam.lua (4282B)


  1. -- Copyright 2021-2024 Mitchell. See LICENSE.
  2. -- Gleam LPeg lexer
  3. -- https://gleam.run/
  4. -- Contributed by Tynan Beatty
  5. local lexer = require('lexer')
  6. local token, word_match = lexer.token, lexer.word_match
  7. local P, S = lpeg.P, lpeg.S
  8. local KEY, OP = lexer.KEYWORD, lexer.OPERATOR
  9. local lex = lexer.new('gleam')
  10. -- Whitespace.
  11. local gleam_ws = token(lexer.WHITESPACE, lexer.space^1)
  12. lex:add_rule('whitespace', gleam_ws)
  13. -- Types.
  14. local typ_tok = token(lexer.TYPE, lexer.upper * lexer.alnum^0)
  15. lex:add_rule('type', typ_tok)
  16. -- Modules.
  17. local name = (lexer.lower + '_') * (lexer.lower + lexer.digit + '_')^0
  18. local fn_name = token(lexer.FUNCTION, name)
  19. local mod_name = token('module', name)
  20. local typ_or_fn = typ_tok + fn_name
  21. local function mod_tok(ws)
  22. return token(KEY, 'import') * ws^1 * mod_name * (ws^0 * token(OP, '/') * ws^0 * mod_name)^0 *
  23. (ws^1 * token(KEY, 'as') * ws^1 * mod_name)^-1 *
  24. (ws^0 * token(OP, '.') * ws^0 * token(OP, '{') * ws^0 * typ_or_fn *
  25. (ws^0 * token(OP, ',') * ws^0 * typ_or_fn)^0 * ws^0 * token(OP, '}'))^-1
  26. end
  27. lex:add_rule('module', mod_tok(gleam_ws))
  28. lex:add_style('module', lexer.styles.constant)
  29. -- Keywords.
  30. local key_tok = token(KEY, word_match(
  31. 'as assert case const external fn if import let opaque pub todo try tuple type'))
  32. lex:add_rule('keyword', key_tok)
  33. -- Functions.
  34. local function fn_tok(ws)
  35. local mod_name_op = mod_name * ws^0 * token(OP, '.')
  36. local fn_def_call = mod_name_op^-1 * ws^0 * fn_name * ws^0 * #P('(')
  37. local fn_pipe = token(OP, '|>') * ws^0 * (token(KEY, 'fn') + mod_name_op^-1 * fn_name)
  38. return fn_def_call + fn_pipe
  39. end
  40. lex:add_rule('function', fn_tok(gleam_ws))
  41. -- Labels.
  42. local id = token(lexer.IDENTIFIER, name)
  43. local function lab_tok(ws)
  44. return token(OP, S('(,')) * ws^0 * token(lexer.LABEL, name) * #(ws^1 * id)
  45. end
  46. lex:add_rule('label', lab_tok(gleam_ws))
  47. -- Identifiers.
  48. local discard_id = token('discard', '_' * name)
  49. local id_tok = discard_id + id
  50. lex:add_rule('identifier', id_tok)
  51. lex:add_style('discard', lexer.styles.comment)
  52. -- Strings.
  53. local str_tok = token(lexer.STRING, lexer.range('"'))
  54. lex:add_rule('string', str_tok)
  55. -- Comments.
  56. local com_tok = token(lexer.COMMENT, lexer.to_eol('//'))
  57. lex:add_rule('comment', com_tok)
  58. -- Numbers.
  59. local function can_neg(patt) return (lpeg.B(lexer.space + S('+-/*%<>=&|:,.')) * '-')^-1 * patt end
  60. local function can_sep(patt) return (P('_')^-1 * patt^1)^1 end
  61. local dec = lexer.digit * can_sep(lexer.digit)^0
  62. local float = dec * '.' * dec^0
  63. local bin = '0' * S('bB') * can_sep(S('01')) * -lexer.xdigit
  64. local oct = '0' * S('oO') * can_sep(lpeg.R('07'))
  65. local hex = '0' * S('xX') * can_sep(lexer.xdigit)
  66. local num_tok = token(lexer.NUMBER, can_neg(float) + bin + oct + hex + can_neg(dec))
  67. lex:add_rule('number', num_tok)
  68. -- Operators.
  69. local op_tok = token(OP, S('+-*/%#!=<>&|.,:;{}[]()'))
  70. lex:add_rule('operator', op_tok)
  71. -- Errors.
  72. local err_tok = token(lexer.ERROR, lexer.any)
  73. lex:add_rule('error', err_tok)
  74. -- Fold points.
  75. lex:add_fold_point(lexer.OPERATOR, '{', '}')
  76. lex:add_fold_point(lexer.OPERATOR, '[', ']')
  77. lex:add_fold_point(lexer.OPERATOR, '(', ')')
  78. -- Embedded Bit Strings.
  79. -- Mimic lexer.load() by creating a bitstring-specific whitespace style.
  80. local bitstring = lexer.new(lex._name .. '_bitstring')
  81. local bitstring_ws = token(bitstring._name .. '_whitespace', lexer.space^1)
  82. bitstring:add_rule('whitespace', bitstring_ws)
  83. bitstring:add_style(bitstring._name .. '_whitespace', lexer.styles.whitespace)
  84. bitstring:add_rule('type', typ_tok)
  85. bitstring:add_rule('module', mod_tok(bitstring_ws))
  86. bitstring:add_rule('keyword', key_tok + token(KEY, word_match{
  87. 'binary', 'bytes', 'int', 'float', 'bit_string', 'bits', 'utf8', 'utf16', 'utf32',
  88. 'utf8_codepoint', 'utf16_codepoint', 'utf32_codepoint', 'signed', 'unsigned', 'big', 'little',
  89. 'native', 'unit', 'size'
  90. }))
  91. bitstring:add_rule('function', fn_tok(bitstring_ws))
  92. bitstring:add_rule('label', lab_tok(bitstring_ws))
  93. bitstring:add_rule('identifier', id_tok)
  94. bitstring:add_rule('string', str_tok)
  95. bitstring:add_rule('comment', com_tok)
  96. bitstring:add_rule('number', num_tok)
  97. bitstring:add_rule('operator', op_tok)
  98. bitstring:add_rule('error', err_tok)
  99. lex:embed(bitstring, token(OP, '<<'), token(OP, '>>'))
  100. lexer.property['scintillua.comment'] = '//'
  101. return lex