vhdl.js 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  2. // Distributed under an MIT license: https://codemirror.net/LICENSE
  3. // Originally written by Alf Nielsen, re-written by Michael Zhou
  4. ;(function (mod) {
  5. if (typeof exports == 'object' && typeof module == 'object')
  6. // CommonJS
  7. mod(require('../../lib/codemirror'))
  8. else if (typeof define == 'function' && define.amd)
  9. // AMD
  10. define(['../../lib/codemirror'], mod)
  11. // Plain browser env
  12. else mod(CodeMirror)
  13. })(function (CodeMirror) {
  14. 'use strict'
  15. function words(str) {
  16. var obj = {},
  17. words = str.split(',')
  18. for (var i = 0; i < words.length; ++i) {
  19. var allCaps = words[i].toUpperCase()
  20. var firstCap = words[i].charAt(0).toUpperCase() + words[i].slice(1)
  21. obj[words[i]] = true
  22. obj[allCaps] = true
  23. obj[firstCap] = true
  24. }
  25. return obj
  26. }
  27. function metaHook(stream) {
  28. stream.eatWhile(/[\w\$_]/)
  29. return 'meta'
  30. }
  31. CodeMirror.defineMode('vhdl', function (config, parserConfig) {
  32. var indentUnit = config.indentUnit,
  33. atoms = parserConfig.atoms || words('null'),
  34. hooks = parserConfig.hooks || { '`': metaHook, $: metaHook },
  35. multiLineStrings = parserConfig.multiLineStrings
  36. var keywords = words(
  37. 'abs,access,after,alias,all,and,architecture,array,assert,attribute,begin,block,' +
  38. 'body,buffer,bus,case,component,configuration,constant,disconnect,downto,else,elsif,end,end block,end case,' +
  39. 'end component,end for,end generate,end if,end loop,end process,end record,end units,entity,exit,file,for,' +
  40. 'function,generate,generic,generic map,group,guarded,if,impure,in,inertial,inout,is,label,library,linkage,' +
  41. 'literal,loop,map,mod,nand,new,next,nor,null,of,on,open,or,others,out,package,package body,port,port map,' +
  42. 'postponed,procedure,process,pure,range,record,register,reject,rem,report,return,rol,ror,select,severity,signal,' +
  43. 'sla,sll,sra,srl,subtype,then,to,transport,type,unaffected,units,until,use,variable,wait,when,while,with,xnor,xor'
  44. )
  45. var blockKeywords = words('architecture,entity,begin,case,port,else,elsif,end,for,function,if')
  46. var isOperatorChar = /[&|~><!\)\(*#%@+\/=?\:;}{,\.\^\-\[\]]/
  47. var curPunc
  48. function tokenBase(stream, state) {
  49. var ch = stream.next()
  50. if (hooks[ch]) {
  51. var result = hooks[ch](stream, state)
  52. if (result !== false) return result
  53. }
  54. if (ch == '"') {
  55. state.tokenize = tokenString2(ch)
  56. return state.tokenize(stream, state)
  57. }
  58. if (ch == "'") {
  59. state.tokenize = tokenString(ch)
  60. return state.tokenize(stream, state)
  61. }
  62. if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
  63. curPunc = ch
  64. return null
  65. }
  66. if (/[\d']/.test(ch)) {
  67. stream.eatWhile(/[\w\.']/)
  68. return 'number'
  69. }
  70. if (ch == '-') {
  71. if (stream.eat('-')) {
  72. stream.skipToEnd()
  73. return 'comment'
  74. }
  75. }
  76. if (isOperatorChar.test(ch)) {
  77. stream.eatWhile(isOperatorChar)
  78. return 'operator'
  79. }
  80. stream.eatWhile(/[\w\$_]/)
  81. var cur = stream.current()
  82. if (keywords.propertyIsEnumerable(cur.toLowerCase())) {
  83. if (blockKeywords.propertyIsEnumerable(cur)) curPunc = 'newstatement'
  84. return 'keyword'
  85. }
  86. if (atoms.propertyIsEnumerable(cur)) return 'atom'
  87. return 'variable'
  88. }
  89. function tokenString(quote) {
  90. return function (stream, state) {
  91. var escaped = false,
  92. next,
  93. end = false
  94. while ((next = stream.next()) != null) {
  95. if (next == quote && !escaped) {
  96. end = true
  97. break
  98. }
  99. escaped = !escaped && next == '--'
  100. }
  101. if (end || !(escaped || multiLineStrings)) state.tokenize = tokenBase
  102. return 'string'
  103. }
  104. }
  105. function tokenString2(quote) {
  106. return function (stream, state) {
  107. var escaped = false,
  108. next,
  109. end = false
  110. while ((next = stream.next()) != null) {
  111. if (next == quote && !escaped) {
  112. end = true
  113. break
  114. }
  115. escaped = !escaped && next == '--'
  116. }
  117. if (end || !(escaped || multiLineStrings)) state.tokenize = tokenBase
  118. return 'string-2'
  119. }
  120. }
  121. function Context(indented, column, type, align, prev) {
  122. this.indented = indented
  123. this.column = column
  124. this.type = type
  125. this.align = align
  126. this.prev = prev
  127. }
  128. function pushContext(state, col, type) {
  129. return (state.context = new Context(state.indented, col, type, null, state.context))
  130. }
  131. function popContext(state) {
  132. var t = state.context.type
  133. if (t == ')' || t == ']' || t == '}') state.indented = state.context.indented
  134. return (state.context = state.context.prev)
  135. }
  136. // Interface
  137. return {
  138. startState: function (basecolumn) {
  139. return {
  140. tokenize: null,
  141. context: new Context((basecolumn || 0) - indentUnit, 0, 'top', false),
  142. indented: 0,
  143. startOfLine: true,
  144. }
  145. },
  146. token: function (stream, state) {
  147. var ctx = state.context
  148. if (stream.sol()) {
  149. if (ctx.align == null) ctx.align = false
  150. state.indented = stream.indentation()
  151. state.startOfLine = true
  152. }
  153. if (stream.eatSpace()) return null
  154. curPunc = null
  155. var style = (state.tokenize || tokenBase)(stream, state)
  156. if (style == 'comment' || style == 'meta') return style
  157. if (ctx.align == null) ctx.align = true
  158. if ((curPunc == ';' || curPunc == ':') && ctx.type == 'statement') popContext(state)
  159. else if (curPunc == '{') pushContext(state, stream.column(), '}')
  160. else if (curPunc == '[') pushContext(state, stream.column(), ']')
  161. else if (curPunc == '(') pushContext(state, stream.column(), ')')
  162. else if (curPunc == '}') {
  163. while (ctx.type == 'statement') ctx = popContext(state)
  164. if (ctx.type == '}') ctx = popContext(state)
  165. while (ctx.type == 'statement') ctx = popContext(state)
  166. } else if (curPunc == ctx.type) popContext(state)
  167. else if (ctx.type == '}' || ctx.type == 'top' || (ctx.type == 'statement' && curPunc == 'newstatement')) pushContext(state, stream.column(), 'statement')
  168. state.startOfLine = false
  169. return style
  170. },
  171. indent: function (state, textAfter) {
  172. if (state.tokenize != tokenBase && state.tokenize != null) return 0
  173. var firstChar = textAfter && textAfter.charAt(0),
  174. ctx = state.context,
  175. closing = firstChar == ctx.type
  176. if (ctx.type == 'statement') return ctx.indented + (firstChar == '{' ? 0 : indentUnit)
  177. else if (ctx.align) return ctx.column + (closing ? 0 : 1)
  178. else return ctx.indented + (closing ? 0 : indentUnit)
  179. },
  180. electricChars: '{}',
  181. }
  182. })
  183. CodeMirror.defineMIME('text/x-vhdl', 'vhdl')
  184. })