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

ruby.lua (5330B)


  1. -- Copyright 2006-2024 Mitchell. See LICENSE.
  2. -- Ruby LPeg lexer.
  3. local lexer = lexer
  4. local P, S = lpeg.P, lpeg.S
  5. local lex = lexer.new(...)
  6. -- Keywords.
  7. lex:add_rule('keyword', lex:tag(lexer.KEYWORD, lex:word_match(lexer.KEYWORD)))
  8. -- Functions.
  9. local builtin_func = lex:tag(lexer.FUNCTION_BUILTIN, lex:word_match(lexer.FUNCTION_BUILTIN))
  10. lex:add_rule('function', -lpeg.B('.') * builtin_func * -S('.:|'))
  11. -- Identifiers.
  12. local word_char = lexer.alnum + S('_!?')
  13. local word = (lexer.alpha + '_') * word_char^0
  14. lex:add_rule('identifier', lex:tag(lexer.IDENTIFIER, word))
  15. -- Comments.
  16. local line_comment = lexer.to_eol('#', true)
  17. local block_comment = lexer.range(lexer.starts_line('=begin'), lexer.starts_line('=end'))
  18. lex:add_rule('comment', lex:tag(lexer.COMMENT, block_comment + line_comment))
  19. -- Strings.
  20. local delimiter_matches = {['('] = ')', ['['] = ']', ['{'] = '}'}
  21. local literal_delimited = P(function(input, index)
  22. local delimiter = input:sub(index, index)
  23. if not delimiter:find('[%w\r\n\f\t ]') then -- only non alpha-numerics
  24. local match_pos, patt
  25. if delimiter_matches[delimiter] then
  26. -- Handle nested delimiter/matches in strings.
  27. local s, e = delimiter, delimiter_matches[delimiter]
  28. patt = lexer.range(s, e, false, true, true)
  29. else
  30. patt = lexer.range(delimiter)
  31. end
  32. match_pos = lpeg.match(patt, input, index)
  33. return match_pos or #input + 1
  34. end
  35. end)
  36. local cmd_str = lexer.range('`')
  37. local lit_cmd = '%x' * literal_delimited
  38. local lit_array = '%w' * literal_delimited
  39. local sq_str = lexer.range("'")
  40. local dq_str = lexer.range('"')
  41. local lit_str = '%' * S('qQ')^-1 * literal_delimited
  42. local heredoc = '<<' * P(function(input, index)
  43. local s, e, indented, _, delimiter = input:find('([%-~]?)(["`]?)([%a_][%w_]*)%2[\n\r\f;]+', index)
  44. if s == index and delimiter then
  45. local end_heredoc = (#indented > 0 and '[\n\r\f]+ *' or '[\n\r\f]+')
  46. s, e = input:find(end_heredoc .. delimiter, e)
  47. return e and e + 1 or #input + 1
  48. end
  49. end)
  50. local string = lex:tag(lexer.STRING, (sq_str + dq_str + lit_str + heredoc + cmd_str + lit_cmd +
  51. lit_array) * S('f')^-1)
  52. -- TODO: regex_str fails with `obj.method /patt/` syntax.
  53. local regex_str = lexer.after_set('!%^&*([{-=+|:;,?<>~', lexer.range('/', true) * S('iomx')^0)
  54. local lit_regex = '%r' * literal_delimited * S('iomx')^0
  55. local regex = lex:tag(lexer.REGEX, regex_str + lit_regex)
  56. lex:add_rule('string', string + regex)
  57. -- Numbers.
  58. local numeric_literal = '?' * (lexer.any - lexer.space) * -word_char -- TODO: meta, control, etc.
  59. lex:add_rule('number', lex:tag(lexer.NUMBER, lexer.number_('_') * S('ri')^-1 + numeric_literal))
  60. -- Variables.
  61. local global_var = '$' *
  62. (word + S('!@L+`\'=~/\\,.;<>_*"$?:') + lexer.digit + '-' * S('0FadiIKlpvw'))
  63. local class_var = '@@' * word
  64. local inst_var = '@' * word
  65. lex:add_rule('variable', lex:tag(lexer.VARIABLE, global_var + class_var + inst_var))
  66. -- Symbols.
  67. lex:add_rule('symbol', lex:tag(lexer.STRING .. '.symbol', ':' * P(function(input, index)
  68. if input:sub(index - 2, index - 2) ~= ':' then return true end
  69. end) * (word_char^1 + sq_str + dq_str)))
  70. -- Operators.
  71. lex:add_rule('operator', lex:tag(lexer.OPERATOR, S('!%^&*()[]{}-=+/|:;.,?<>~')))
  72. -- Fold points.
  73. local function disambiguate(text, pos, line, s)
  74. return line:sub(1, s - 1):match('^%s*$') and not text:sub(1, pos - 1):match('\\[ \t]*\r?\n$') and
  75. 1 or 0
  76. end
  77. lex:add_fold_point(lexer.KEYWORD, 'begin', 'end')
  78. lex:add_fold_point(lexer.KEYWORD, 'class', 'end')
  79. lex:add_fold_point(lexer.KEYWORD, 'def', 'end')
  80. lex:add_fold_point(lexer.KEYWORD, 'do', 'end')
  81. lex:add_fold_point(lexer.KEYWORD, 'for', 'end')
  82. lex:add_fold_point(lexer.KEYWORD, 'module', 'end')
  83. lex:add_fold_point(lexer.KEYWORD, 'case', 'end')
  84. lex:add_fold_point(lexer.KEYWORD, 'if', disambiguate)
  85. lex:add_fold_point(lexer.KEYWORD, 'while', disambiguate)
  86. lex:add_fold_point(lexer.KEYWORD, 'unless', disambiguate)
  87. lex:add_fold_point(lexer.KEYWORD, 'until', disambiguate)
  88. lex:add_fold_point(lexer.OPERATOR, '(', ')')
  89. lex:add_fold_point(lexer.OPERATOR, '[', ']')
  90. lex:add_fold_point(lexer.OPERATOR, '{', '}')
  91. lex:add_fold_point(lexer.COMMENT, '=begin', '=end')
  92. -- Word lists.
  93. lex:set_word_list(lexer.KEYWORD, {
  94. 'BEGIN', 'END', 'alias', 'and', 'begin', 'break', 'case', 'class', 'def', 'defined?', 'do',
  95. 'else', 'elsif', 'end', 'ensure', 'false', 'for', 'if', 'in', 'module', 'next', 'nil', 'not',
  96. 'or', 'redo', 'rescue', 'retry', 'return', 'self', 'super', 'then', 'true', 'undef', 'unless',
  97. 'until', 'when', 'while', 'yield', '__FILE__', '__LINE__'
  98. })
  99. lex:set_word_list(lexer.FUNCTION_BUILTIN, {
  100. 'at_exit', 'autoload', 'binding', 'caller', 'catch', 'chop', 'chop!', 'chomp', 'chomp!', 'eval',
  101. 'exec', 'exit', 'exit!', 'extend', 'fail', 'fork', 'format', 'gets', 'global_variables', 'gsub',
  102. 'gsub!', 'include', 'iterator?', 'lambda', 'load', 'local_variables', 'loop', 'module_function',
  103. 'open', 'p', 'print', 'printf', 'proc', 'putc', 'puts', 'raise', 'rand', 'readline', 'readlines',
  104. 'require', 'require_relative', 'select', 'sleep', 'split', 'sprintf', 'srand', 'sub', 'sub!',
  105. 'syscall', 'system', 'test', 'trace_var', 'trap', 'untrace_var'
  106. })
  107. lexer.property['scintillua.comment'] = '#'
  108. lexer.property['scintillua.word.chars'] =
  109. 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_?!'
  110. return lex