highlight.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. package cst
  2. import (
  3. "kumachan/lang/textual/scanner"
  4. "kumachan/lang/textual/syntax"
  5. )
  6. type Color struct { R,G,B int }
  7. type ColorKey int
  8. type ColorScheme (map[ColorKey] Color)
  9. const (
  10. CK_NULL ColorKey = iota
  11. CK_Keyword
  12. CK_Type
  13. CK_Const
  14. CK_Callable
  15. CK_Text
  16. CK_Number
  17. )
  18. var defaultColorScheme = ColorScheme {
  19. CK_Keyword: Color { 0, 51, 179 },
  20. CK_Type: Color { 51, 110, 204 },
  21. CK_Const: Color { 135, 16, 148 },
  22. CK_Callable: Color { 40, 109, 115 },
  23. CK_Text: Color { 6, 125, 23 },
  24. CK_Number: Color { 23, 80, 235 },
  25. }
  26. func DefaultColorScheme() ColorScheme { return defaultColorScheme }
  27. type HighlightRange struct {
  28. Span scanner.Span
  29. Color ColorKey
  30. }
  31. type HighlightRanges ([] HighlightRange)
  32. func Highlight(tree *Tree) HighlightRanges {
  33. var out = make(HighlightRanges, 0)
  34. for ptr := 0; ptr < len(tree.Nodes); ptr += 1 {
  35. var key = highlight(ptr, tree.Nodes)
  36. if key != CK_NULL {
  37. out = append(out, HighlightRange {
  38. Span: tree.Nodes[ptr].Span,
  39. Color: key,
  40. })
  41. }
  42. }
  43. return out
  44. }
  45. func highlight(ptr int, nodes ([] TreeNode)) ColorKey {
  46. var node = &nodes[ptr]
  47. switch node.Part.PartType {
  48. case syntax.MatchKeyword:
  49. return CK_Keyword
  50. case syntax.MatchToken:
  51. var id = node.Part.Id
  52. switch id {
  53. case __at:
  54. return CK_Keyword
  55. case __Text:
  56. return CK_Text
  57. case __Int, __Float, __Byte, __Char:
  58. return CK_Number
  59. default:
  60. var token = syntax.Id2Token(id)
  61. if (token.Keyword && (id != __equal) && (id != __derive)) {
  62. return CK_Keyword
  63. }
  64. }
  65. case syntax.Recursive:
  66. var id = node.Part.Id
  67. switch id {
  68. case __ref_base:
  69. if matchAncestors(&ptr, nodes, __ref) {
  70. if matchAncestors(&ptr, nodes, __type) {
  71. return CK_Type
  72. }
  73. if matchAncestors(&ptr, nodes, __ref_term, __term) {
  74. var ref_term_ptr = nodes[ptr].Children[0]
  75. var new_ptr = nodes[ref_term_ptr].Children[0]
  76. if (nodes[new_ptr].Length > 0) {
  77. return CK_Type
  78. }
  79. var pipes = nodes[ptr+1]
  80. if pipes.Length > 0 {
  81. var pipe = nodes[pipes.Children[0]]
  82. var pipe_content = nodes[pipe.Children[0]]
  83. if pipe_content.Part.Id == __pipe_call {
  84. return CK_Callable
  85. }
  86. }
  87. }
  88. if matchAncestors(&ptr, nodes, __pipe_infix) {
  89. return CK_Callable
  90. }
  91. if matchAncestors(&ptr, nodes, __operator) {
  92. return CK_Callable
  93. }
  94. if matchAncestors(&ptr, nodes, __binding_cps) {
  95. return CK_Keyword
  96. }
  97. }
  98. case __name:
  99. if matchAncestors(&ptr, nodes, __ref_base) {
  100. break
  101. }
  102. skipListIntermediateAncestors(&ptr, nodes)
  103. if matchAncestors(&ptr, nodes, __case) {
  104. return CK_Type
  105. }
  106. { ptr = nodes[ptr].Parent
  107. if matchAncestors(&ptr, nodes, __stmt) {
  108. var stmt_content = nodes[node.Parent]
  109. switch stmt_content.Part.Id {
  110. case __decl_func:
  111. return CK_Callable
  112. case __decl_const:
  113. return CK_Const
  114. }
  115. }
  116. if matchAncestors(&ptr, nodes, __pattern) {
  117. var pattern_index = nodes[ptr].Index
  118. if matchAncestors(&ptr, nodes, __binding_plain) {
  119. var prev = (pattern_index - 1)
  120. var let_ptr = nodes[ptr].Children[prev]
  121. var kw_ptr = nodes[let_ptr].Children[0]
  122. if nodes[kw_ptr].Part.Id == __Const {
  123. return CK_Const
  124. }
  125. }
  126. }}
  127. }
  128. }
  129. return CK_NULL
  130. }
  131. var __at = syntax.Name2IdMustExist("@")
  132. var __Text = syntax.Name2IdMustExist("Text")
  133. var __Int = syntax.Name2IdMustExist("Int")
  134. var __Float = syntax.Name2IdMustExist("Float")
  135. var __Byte = syntax.Name2IdMustExist("Byte")
  136. var __Char = syntax.Name2IdMustExist("Char")
  137. var __equal = syntax.Name2IdMustExist("=")
  138. var __derive = syntax.Name2IdMustExist("=>")
  139. var __ref_base = syntax.Name2IdMustExist("ref_base")
  140. var __ref = syntax.Name2IdMustExist("ref")
  141. var __type = syntax.Name2IdMustExist("type")
  142. var __ref_term = syntax.Name2IdMustExist("ref_term")
  143. var __term = syntax.Name2IdMustExist("term")
  144. var __pipe_call = syntax.Name2IdMustExist("pipe_call")
  145. var __pipe_infix = syntax.Name2IdMustExist("pipe_infix")
  146. var __operator = syntax.Name2IdMustExist("operator")
  147. var __binding_cps = syntax.Name2IdMustExist("binding_cps")
  148. var __name = syntax.Name2IdMustExist("name")
  149. var __stmt = syntax.Name2IdMustExist("stmt")
  150. var __pattern = syntax.Name2IdMustExist("pattern")
  151. var __binding_plain = syntax.Name2IdMustExist("binding_plain")
  152. var __Const = syntax.Name2IdMustExist("Const")
  153. var __case = syntax.Name2IdMustExist("case")
  154. var __decl_func = syntax.Name2IdMustExist("decl_func")
  155. var __decl_const = syntax.Name2IdMustExist("decl_const")
  156. func matchAncestors(ptr *int, nodes ([] TreeNode), ancestors ...syntax.Id) bool {
  157. for {
  158. if len(ancestors) > 0 {
  159. var id = ancestors[0]
  160. ancestors = ancestors[1:]
  161. var parent = nodes[*ptr].Parent
  162. if parent >= 0 {
  163. if nodes[parent].Part.Id == id {
  164. *ptr = parent
  165. continue
  166. } else {
  167. return false
  168. }
  169. } else {
  170. return false
  171. }
  172. } else {
  173. return true
  174. }
  175. }
  176. }
  177. func skipListIntermediateAncestors(ptr *int, nodes ([] TreeNode)) {
  178. for {
  179. var parent = nodes[*ptr].Parent
  180. if parent >= 0 {
  181. var name = syntax.Id2Name(nodes[parent].Part.Id)
  182. if syntax.IsList(name) {
  183. *ptr = parent
  184. continue
  185. }
  186. }
  187. break
  188. }
  189. }