definition.go 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. package syntax
  2. import "regexp"
  3. type Regexp = *regexp.Regexp
  4. func r (pattern string) Regexp { return regexp.MustCompile(`^` + pattern) }
  5. const IdentifierPartName = "Name"
  6. var IgnoreTokens = [] string { "Comment", "Blank", "LF" }
  7. var EscapeMap = map[string] string {
  8. "_bang1": "!",
  9. "_bang2": "!!",
  10. "_bar1": "|",
  11. "_bar2": "||",
  12. "_at": "@",
  13. }
  14. const LF = `\n`
  15. const Blanks = ` \t\r `
  16. const Symbols = `\{\}\[\]\(\)\.\,\:\;\$#@~\&\|\\'"` + "`"
  17. var Tokens = [...] Token {
  18. Token { Name: "String", Pattern: r(`'[^']*'`) },
  19. Token { Name: "Text", Pattern: r(`"[^"]*"`) },
  20. Token { Name: "Comment", Pattern: r(`/\*([^\*]|[^/]|\*[^/]|[^\*]/|\*/)*\*/`) },
  21. Token { Name: "Doc", Pattern: r(`///[^`+LF+`]*`) },
  22. Token { Name: "Comment", Pattern: r(`//[^`+LF+`]*`) },
  23. Token { Name: "Pragma", Pattern: r(`#[^`+LF+`]*`) },
  24. Token { Name: "Blank", Pattern: r(`[`+Blanks+`]+`) },
  25. Token { Name: "LF", Pattern: r(`[`+LF+`]+`) },
  26. Token { Name: "Int", Pattern: r(`\-?0[xX][0-9A-Fa-f]+`) },
  27. Token { Name: "Int", Pattern: r(`\-?0[oO][0-7]+`) },
  28. Token { Name: "Int", Pattern: r(`\-?0[bB][01]+`) },
  29. Token { Name: "Float", Pattern: r(`\-?\d+(\.\d+)?[Ee][\+\-]?\d+`) },
  30. Token { Name: "Float", Pattern: r(`\-?\d+\.\d+`) },
  31. Token { Name: "Int", Pattern: r(`\-?\d[\d_]*`) },
  32. Token { Name: "(", Pattern: r(`\(`) },
  33. Token { Name: ")", Pattern: r(`\)`) },
  34. Token { Name: "[", Pattern: r(`\[`) },
  35. Token { Name: "]", Pattern: r(`\]`) },
  36. Token { Name: "{", Pattern: r(`\{`) },
  37. Token { Name: "}", Pattern: r(`\}`) },
  38. Token { Name: "...", Pattern: r(`\.\.\.`) },
  39. Token { Name: "..", Pattern: r(`\.\.`) },
  40. Token { Name: ".", Pattern: r(`\.`) },
  41. Token { Name: ",", Pattern: r(`\,`) },
  42. Token { Name: "::", Pattern: r(`\:\:`) },
  43. Token { Name: ":=", Pattern: r(`\:\=`) },
  44. Token { Name: ":", Pattern: r(`\:`) },
  45. Token { Name: ";", Pattern: r(`\;`) },
  46. Token { Name: "$$", Pattern: r(`\$$`) },
  47. Token { Name: "$", Pattern: r(`\$`) },
  48. Token { Name: "@@", Pattern: r(`@@`) },
  49. Token { Name: "@", Pattern: r(`@`) },
  50. Token { Name: "~~", Pattern: r(`~~`) },
  51. Token { Name: "~", Pattern: r(`~`) },
  52. Token { Name: "`", Pattern: r("`") },
  53. Token { Name: "&&", Pattern: r(`\&\&`) },
  54. Token { Name: "&", Pattern: r(`\&`) },
  55. Token { Name: "||", Pattern: r(`\|\|`) },
  56. Token { Name: "|", Pattern: r(`\|`) },
  57. Token { Name: `\`, Pattern: r(`\\`) },
  58. Token { Name: "Name", Pattern: r(`[^`+Symbols+Blanks+LF+`]+`) },
  59. }
  60. var ConditionalKeywords = [...] string {
  61. "@module", "@import", "@from",
  62. "@type", "@union", "@native", "@protected", "@opaque",
  63. "@private", "@public", "@function", "@const", "@do",
  64. "@if", "@else", "@switch", "@case", "@default",
  65. "@lambda", "@let", "@rec", "@return",
  66. }
  67. var SyntaxDefinition = [...] string {
  68. "module = shebang module_name! commands",
  69. "shebang? = Pragma",
  70. "module_name = @module name! ;!",
  71. "name = Name",
  72. "commands? = command commands",
  73. "command = import | decl_type | decl_func | decl_const | do",
  74. "import = @import name! @from! string! ;!",
  75. "do = @do expr! ;!",
  76. "ref = module_prefix name type_args",
  77. "module_prefix? = name :: | ::",
  78. "type_args? = [ type! more_types ]!",
  79. "more_types? = , type! more_types",
  80. "type = type_literal | type_ref",
  81. "type_ref = ref",
  82. "type_literal = repr",
  83. "repr = repr_tuple | repr_bundle | repr_func",
  84. "repr_tuple = ( ) | ( type_list )!",
  85. "type_list = type! more_types",
  86. "repr_bundle = { } | { field_list }!",
  87. "field_list = field! more_fields",
  88. "field = name :! type!",
  89. "more_fields? = , field! more_fields",
  90. "repr_func = @lambda input_type! output_type!",
  91. "input_type = type",
  92. "output_type = type",
  93. "decl_type = @type name! type_params docs_brief type_value ;!",
  94. "docs_brief = docs",
  95. "docs? = doc docs",
  96. "doc = Doc",
  97. "type_value = native_type | union_type | boxed_type",
  98. "native_type = @native",
  99. "union_type = @union {! decl_type! more_decl_types }!",
  100. "type_params? = [ name! more_names ]!",
  101. "more_names? = , name! more_names",
  102. "more_decl_types? = decl_type more_decl_types",
  103. "boxed_type = box_option inner_type",
  104. "box_option? = @protected | @opaque",
  105. "inner_type? = type",
  106. "decl_func = scope @function name! type_params {! docs_brief signature! :! body docs_detail }! ;!",
  107. "scope = @public | @private",
  108. "signature = repr_func",
  109. "body = native | lambda!",
  110. "native = @native string!",
  111. "lambda = @lambda pattern! terms!",
  112. "terms = call",
  113. "pattern = pattern_trivial | pattern_tuple | pattern_bundle",
  114. "pattern_trivial = name",
  115. "pattern_tuple = ( ) | ( namelist )!",
  116. "namelist = name more_names",
  117. "pattern_bundle = { } | { namelist }!",
  118. "docs_detail = docs",
  119. "decl_const = scope @const name! :=! [! type! ]! docs_brief const_value ;!",
  120. "const_value = native | expr!",
  121. "expr = call pipeline",
  122. "call = func arg",
  123. "func = term",
  124. "arg? = call",
  125. "pipeline? = pipe_op pipe_func pipe_arg pipeline",
  126. "pipe_op = _bar1",
  127. "pipe_func = term!",
  128. "pipe_arg? = call",
  129. "term = cast | lambda | switch | if | block | bundle | get | tuple | infix | array | text | literal | ref",
  130. "cast = [ type! ]! (! expr! )!",
  131. "switch = @switch term {! branch_list }!",
  132. "branch_list = branch! more_branches",
  133. "more_branches? = , branch more_branches",
  134. "branch = branch_key :! expr!",
  135. "branch_key = @default | @case type_ref! opt_pattern",
  136. "opt_pattern? = pattern",
  137. // TODO: multi-switch
  138. "if = @if term {! if_yes }! elifs @else! {! if_no }!",
  139. "elifs? = elif elifs",
  140. "elif = @else @if term! {! expr! }!",
  141. "if_yes = expr!",
  142. "if_no = expr!",
  143. "block = @let { binding! more_bindings return! }!",
  144. "more_bindings? = , binding! more_bindings",
  145. "binding = rec_opt pattern := binding_type expr!",
  146. "rec_opt? = ( @rec! )!",
  147. "binding_type? = [ type! ]!",
  148. "return = , @return expr!",
  149. "bundle = { } | { update pairlist }!",
  150. "pairlist = pair! more_pairs",
  151. "more_pairs? = , pair! more_pairs",
  152. "pair = name : expr! | name",
  153. "update? = ... expr! ,!",
  154. "get = $ { expr! member! more_members }!",
  155. "more_members? = member more_members",
  156. "member = . name!",
  157. "tuple = ( ) | ( exprlist )!",
  158. "exprlist = expr! more_exprs",
  159. "more_exprs? = , expr! more_exprs",
  160. "infix = $ (! operand1 operator operand2 )!",
  161. "operand1 = term!",
  162. "operator = term!",
  163. "operand2 = term!",
  164. "array = _at ( ) | _at (! exprlist )!",
  165. "text = Text",
  166. "literal = string | int | float",
  167. "string = String",
  168. "int = Int",
  169. "float = Float",
  170. }