syntax.lua 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. local syntax = {}
  2. syntax.items = {}
  3. local plain_text_syntax = { patterns = {}, symbols = {} }
  4. local function matches_pattern(text, pattern)
  5. if type(pattern) == "string" then
  6. return text:find(pattern)
  7. end
  8. for _, p in ipairs(pattern) do
  9. if matches_pattern(text, p) then return true end
  10. end
  11. return false
  12. end
  13. function syntax.add(t)
  14. table.insert(syntax.items, t)
  15. end
  16. function syntax.get(filename)
  17. for i = #syntax.items, 1, -1 do
  18. local t = syntax.items[i]
  19. if matches_pattern(filename, t.files) then
  20. return t
  21. end
  22. end
  23. return plain_text_syntax
  24. end
  25. local lua_pattern_matcher, lua_restore_state, lua_save_state
  26. do
  27. local expect_len
  28. function lua_restore_state(state)
  29. expect_len = state and state.lua__expect_len
  30. end
  31. function lua_save_state(state)
  32. if state then
  33. state.lua__expect_len = expect_len
  34. end
  35. end
  36. function lua_pattern_matcher(text, pattern, offset)
  37. local s, e = text:find(pattern, offset)
  38. if not s then
  39. return nil
  40. end
  41. if not expect_len then
  42. -- Not inside a comment or string
  43. if pattern == "^%-%-%[=*%[" then
  44. expect_len = e - s - 2
  45. elseif pattern == "^%[=*%[" then
  46. expect_len = e - s
  47. end
  48. return s, e
  49. end
  50. -- At this point, we're inside a comment or string
  51. if pattern == "%]=*%]" then
  52. -- If one is found, it must match the expected length;
  53. -- if it doesn't, it may be the wrong match, so keep trying.
  54. while s and e - s ~= expect_len do
  55. s, e = text:find(pattern, s + 1)
  56. end
  57. if s then
  58. return s, e
  59. end
  60. end
  61. return nil
  62. end
  63. end
  64. syntax.add {
  65. files = "%.lua$",
  66. comment = "--",
  67. match_fn = lua_pattern_matcher,
  68. restore_state = lua_restore_state,
  69. save_state = lua_save_state,
  70. patterns = {
  71. { pattern = { '"', '"', '\\' }, type = "string" },
  72. { pattern = { "'", "'", '\\' }, type = "string" },
  73. { pattern = { "%[=*%[", "%]=*%]" }, type = "string" },
  74. { pattern = { "%-%-%[=*%[", "%]=*%]" }, type = "comment" },
  75. { pattern = "%-%-.-\n", type = "comment" },
  76. { pattern = "-?0x%x+", type = "number" },
  77. { pattern = "-?%d+[%d%.eE]*", type = "number" },
  78. { pattern = "-?%.?%d+", type = "number" },
  79. { pattern = "%.%.%.?", type = "operator" },
  80. { pattern = "[<>~=]=", type = "operator" },
  81. { pattern = "[%+%-=/%*%^%%#<>]", type = "operator" },
  82. { pattern = "[%a_][%w_]*%s*%f[(\"{]", type = "function" },
  83. { pattern = "[%a_][%w_]*", type = "symbol" },
  84. },
  85. symbols = {
  86. ["if"] = "keyword",
  87. ["then"] = "keyword",
  88. ["else"] = "keyword",
  89. ["elseif"] = "keyword",
  90. ["end"] = "keyword",
  91. ["do"] = "keyword",
  92. ["function"] = "keyword",
  93. ["repeat"] = "keyword",
  94. ["until"] = "keyword",
  95. ["while"] = "keyword",
  96. ["for"] = "keyword",
  97. ["break"] = "keyword",
  98. ["return"] = "keyword",
  99. ["local"] = "keyword",
  100. ["in"] = "keyword",
  101. ["not"] = "keyword",
  102. ["and"] = "keyword",
  103. ["or"] = "keyword",
  104. ["self"] = "keyword2",
  105. ["true"] = "literal",
  106. ["false"] = "literal",
  107. ["nil"] = "literal",
  108. },
  109. }
  110. syntax.add {
  111. files = { "%.c$", "%.h$", "%.inl$", "%.cpp$", "%.hpp$" },
  112. comment = "//",
  113. patterns = {
  114. { pattern = "//.-\n", type = "comment" },
  115. { pattern = { "/%*", "%*/" }, type = "comment" },
  116. { pattern = { "#", "[^\\]\n" }, type = "comment" },
  117. { pattern = { '"', '"', '\\' }, type = "string" },
  118. { pattern = { "'", "'", '\\' }, type = "string" },
  119. { pattern = "-?0x%x+", type = "number" },
  120. { pattern = "-?%d+[%d%.eE]*f?", type = "number" },
  121. { pattern = "-?%.?%d+f?", type = "number" },
  122. { pattern = "[%+%-=/%*%^%%<>!~|&]", type = "operator" },
  123. { pattern = "[%a_][%w_]*%f[(]", type = "function" },
  124. { pattern = "[%a_][%w_]*", type = "symbol" },
  125. },
  126. symbols = {
  127. ["if"] = "keyword",
  128. ["then"] = "keyword",
  129. ["else"] = "keyword",
  130. ["elseif"] = "keyword",
  131. ["do"] = "keyword",
  132. ["while"] = "keyword",
  133. ["for"] = "keyword",
  134. ["break"] = "keyword",
  135. ["continue"] = "keyword",
  136. ["return"] = "keyword",
  137. ["goto"] = "keyword",
  138. ["struct"] = "keyword",
  139. ["typedef"] = "keyword",
  140. ["enum"] = "keyword",
  141. ["extern"] = "keyword",
  142. ["static"] = "keyword",
  143. ["volatile"] = "keyword",
  144. ["const"] = "keyword",
  145. ["inline"] = "keyword",
  146. ["switch"] = "keyword",
  147. ["case"] = "keyword",
  148. ["default"] = "keyword",
  149. ["auto"] = "keyword",
  150. ["const"] = "keyword",
  151. ["void"] = "keyword",
  152. ["int"] = "keyword2",
  153. ["float"] = "keyword2",
  154. ["double"] = "keyword2",
  155. ["char"] = "keyword2",
  156. ["unsigned"] = "keyword2",
  157. ["bool"] = "keyword2",
  158. ["true"] = "literal",
  159. ["false"] = "literal",
  160. ["NULL"] = "literal",
  161. },
  162. }
  163. syntax.add {
  164. files = { "%.md$", "%.markdown$" },
  165. patterns = {
  166. { pattern = "\\.", type = "normal" },
  167. { pattern = { "<!%-%-", "%-%->" }, type = "comment" },
  168. { pattern = { "```", "```" }, type = "string" },
  169. { pattern = { "`", "`", "\\" }, type = "string" },
  170. { pattern = { "~~", "~~", "\\" }, type = "keyword2" },
  171. { pattern = "%-%-%-+", type = "comment" },
  172. { pattern = "%*%s+", type = "operator" },
  173. { pattern = { "%*", "[%*\n]", "\\" }, type = "operator" },
  174. { pattern = { "%_", "[%_\n]", "\\" }, type = "keyword2" },
  175. { pattern = "#.-\n", type = "keyword" },
  176. { pattern = "!?%[.*%]%(.*%)", type = "function" },
  177. { pattern = "https?://%S+", type = "function" },
  178. },
  179. symbols = { },
  180. }
  181. return syntax