grammar.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. /*
  2. * Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  3. * Exceptions. See /LICENSE for license information.
  4. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  5. */
  6. // This grammar is more permissive than toolchain because it is geared towards
  7. // editor use.
  8. function repeat_sep1(thing, sep) {
  9. return seq(thing, repeat(seq(sep, thing)));
  10. }
  11. function comma_sep(thing) {
  12. // Trailing comma is only allowed if there is at least one element.
  13. return optional(seq(repeat_sep1(thing, ','), optional(',')));
  14. }
  15. // This is based on toolchain/parser/precedence.cpp
  16. const PREC = {
  17. TermPrefix: 12,
  18. TermPostfix: 12,
  19. NumericPrefix: 11,
  20. NumericPostfix: 11,
  21. Multiplicative: 10,
  22. Additive: 9,
  23. BitwisePrefix: 8,
  24. BitwiseAnd: 7,
  25. BitwiseOr: 7,
  26. BitwiseXor: 7,
  27. BitShift: 7,
  28. TypePostfix: 6,
  29. LogicalPrefix: 5,
  30. Relational: 4,
  31. LogicalAnd: 3,
  32. LogicalOr: 3,
  33. IfExpression: 2,
  34. WhereClause: 1,
  35. };
  36. module.exports = grammar({
  37. name: 'carbon',
  38. word: ($) => $.ident,
  39. conflicts: ($) => [
  40. [$.paren_pattern, $.paren_expression],
  41. [$.struct_literal, $.struct_type_literal],
  42. [$._pattern_without_expression, $._simple_expression],
  43. ],
  44. extras: ($) => [/\s/, $.comment],
  45. // NOTE: This must match the order in src/scanner.c, names are not used for matching.
  46. externals: ($) => [$.binary_star, $.postfix_star, $.string],
  47. rules: {
  48. source_file: ($) =>
  49. seq(
  50. optional($.package_directive),
  51. repeat($.import_directive),
  52. repeat($.declaration)
  53. ),
  54. api_or_impl: ($) => choice('api', 'impl'),
  55. library_path: ($) => seq('library', $.string),
  56. package_directive: ($) =>
  57. seq('package', $.ident, optional($.library_path), $.api_or_impl, ';'),
  58. import_directive: ($) =>
  59. seq('import', $.ident, optional($.library_path), ';'),
  60. comment: ($) => token(seq('//', /.*/)),
  61. // NOTE: this must be before ident rule to increase its priority.
  62. // https://github.com/carbon-language/carbon-lang/blob/trunk/proposals/p2015.md#syntax
  63. numeric_type_literal: ($) => /[iuf][1-9][0-9]*/,
  64. ident: ($) => /[A-Za-z_][A-Za-z0-9_]*/,
  65. bool_literal: ($) => choice('true', 'false'),
  66. numeric_literal: ($) => {
  67. // This is using variables because rules are not allowed in
  68. // token.immediate and token.
  69. // https://github.com/tree-sitter/tree-sitter/issues/449
  70. const decimal_integer_literal = choice('0', /[1-9](_?[0-9])*/);
  71. const hex_digits = /[0-9A-F](_?[0-9A-F])*/;
  72. const binary_integer_literal = /0b[01](_?[01])*/;
  73. const hex_integer_literal = seq('0x', token.immediate(hex_digits));
  74. const decimal_real_number_literal = seq(
  75. decimal_integer_literal,
  76. token.immediate(/\.[0-9](_?[0-9])*/),
  77. optional(
  78. seq(
  79. token.immediate(/e[+-]?/),
  80. token.immediate(decimal_integer_literal)
  81. )
  82. )
  83. );
  84. const hex_real_number_literal = seq(
  85. hex_integer_literal,
  86. token.immediate('.'),
  87. token.immediate(hex_digits),
  88. optional(
  89. seq(
  90. token.immediate(/p[+-]?/),
  91. token.immediate(decimal_integer_literal)
  92. )
  93. )
  94. );
  95. return token(
  96. choice(
  97. decimal_integer_literal,
  98. binary_integer_literal,
  99. hex_integer_literal,
  100. decimal_real_number_literal,
  101. hex_real_number_literal
  102. )
  103. );
  104. },
  105. array_literal: ($) =>
  106. seq(
  107. '[',
  108. field('type', $._expression),
  109. ';',
  110. optional(field('size', $._expression)),
  111. ']'
  112. ),
  113. struct_literal: ($) =>
  114. seq('{', comma_sep(seq($.designator, '=', $._expression)), '}'),
  115. struct_type_literal: ($) =>
  116. seq('{', comma_sep(seq($.designator, ':', $._expression)), '}'),
  117. builtin_type: ($) => choice('Self', 'String', 'bool', 'type'),
  118. literal: ($) =>
  119. choice(
  120. $.bool_literal,
  121. $.numeric_literal,
  122. $.numeric_type_literal,
  123. $.string,
  124. $.struct_literal,
  125. $.struct_type_literal
  126. ),
  127. binding_lhs: ($) => choice($.ident, '_'),
  128. paren_pattern: ($) =>
  129. seq(
  130. '(',
  131. comma_sep(choice($._pattern_without_expression, $._expression)),
  132. ')'
  133. ),
  134. _pattern_without_expression: ($) =>
  135. choice(
  136. 'auto',
  137. seq(optional('ref'), 'self', optional(seq(':', $._expression))),
  138. seq($.binding_lhs, ':', $._expression),
  139. seq($.binding_lhs, ':!', $._expression),
  140. seq('template', $.binding_lhs, ':!', $._expression),
  141. seq('var', $._pattern),
  142. $.paren_pattern,
  143. // alternative patterns
  144. // example: Optional(i32).Some(x: i32)
  145. seq($._simple_expression, $.paren_pattern)
  146. ),
  147. _pattern: ($) =>
  148. choice($._pattern_without_expression, $._simple_expression),
  149. unary_prefix_expression: ($) => {
  150. const table = [
  151. [PREC.NumericPrefix, '-'],
  152. [PREC.NumericPrefix, '--'],
  153. [PREC.NumericPrefix, '++'],
  154. [PREC.BitwisePrefix, '^'],
  155. [PREC.LogicalPrefix, 'not'],
  156. ];
  157. return choice(
  158. ...table.map(([precedence, operator]) =>
  159. prec(
  160. precedence,
  161. seq(field('operator', operator), field('value', $._expression))
  162. )
  163. )
  164. );
  165. },
  166. binary_expression: ($) => {
  167. const table = [
  168. [PREC.LogicalAnd, 'and'],
  169. [PREC.LogicalOr, 'or'],
  170. [PREC.BitwiseAnd, '&'],
  171. [PREC.BitwiseOr, '|'],
  172. [PREC.BitwiseXor, '^'],
  173. [PREC.BitShift, choice('<<', '>>')],
  174. [PREC.Relational, choice('==', '!=', '<', '<=', '>', '>=')],
  175. [PREC.Additive, choice('+', '-')],
  176. [PREC.Multiplicative, choice($.binary_star, '/', '%')],
  177. ];
  178. return choice(
  179. ...table.map(([precedence, operator]) =>
  180. prec.left(
  181. precedence,
  182. seq(
  183. field('left', $._expression),
  184. field('operator', operator),
  185. field('right', $._expression)
  186. )
  187. )
  188. )
  189. );
  190. },
  191. // This should be non-associative but conflicts are not allowed in tree-sitter
  192. as_expression: ($) => prec.left(seq($._expression, 'as', $._expression)),
  193. ref_expression: ($) =>
  194. prec.right(PREC.TermPrefix, seq('&', $._simple_expression)),
  195. deref_expression: ($) =>
  196. prec.right(PREC.TermPrefix, seq('*', $._simple_expression)),
  197. fn_type_expression: ($) =>
  198. prec.left(seq('__Fn', $.paren_expression, '->', $._simple_expression)),
  199. if_expression: ($) =>
  200. prec(
  201. PREC.IfExpression,
  202. seq('if', $._expression, 'then', $._expression, 'else', $._expression)
  203. ),
  204. paren_expression: ($) => seq('(', comma_sep($._expression), ')'),
  205. index_expression: ($) =>
  206. prec(
  207. PREC.TermPostfix,
  208. seq($._simple_expression, '[', $._expression, ']')
  209. ),
  210. designator: ($) => seq('.', choice('base', $.ident)),
  211. postfix_expression: ($) =>
  212. prec(
  213. PREC.TermPostfix,
  214. seq(
  215. $._simple_expression,
  216. choice(
  217. '++',
  218. '--',
  219. $.designator,
  220. seq('->', $.ident),
  221. seq(choice('.', '->'), '(', $._expression, ')')
  222. )
  223. )
  224. ),
  225. where_clause: ($) =>
  226. choice(
  227. seq($._simple_expression, '==', $._simple_expression),
  228. seq($._simple_expression, 'impls', $._simple_expression),
  229. seq($._simple_expression, '=', $._simple_expression),
  230. prec.left(
  231. PREC.WhereClause + 1,
  232. seq($.where_clause, 'and', $.where_clause)
  233. )
  234. ),
  235. where_expression: ($) =>
  236. prec.left(PREC.WhereClause, seq($._expression, 'where', $.where_clause)),
  237. call_expression: ($) =>
  238. prec(PREC.TermPostfix, seq($._simple_expression, $.paren_expression)),
  239. pointer_expression: ($) =>
  240. prec(PREC.TypePostfix, seq($._simple_expression, $.postfix_star)),
  241. _simple_expression: ($) =>
  242. choice(
  243. $.array_literal,
  244. $.builtin_type,
  245. $.call_expression,
  246. $.deref_expression,
  247. $.fn_type_expression,
  248. $.ident,
  249. $.index_expression,
  250. $.literal,
  251. $.paren_expression,
  252. $.pointer_expression,
  253. $.postfix_expression,
  254. $.ref_expression,
  255. 'self',
  256. '.Self',
  257. $.designator
  258. ),
  259. _expression: ($) =>
  260. choice(
  261. $.as_expression,
  262. $.binary_expression,
  263. $.if_expression,
  264. $.unary_prefix_expression,
  265. $.where_expression,
  266. $._simple_expression
  267. ),
  268. var_declaration: ($) =>
  269. seq(
  270. seq(optional('static'), 'var'),
  271. $._pattern_without_expression,
  272. optional(seq('=', $._expression)),
  273. ';'
  274. ),
  275. let_declaration: ($) =>
  276. seq('let', $._pattern_without_expression, '=', $._expression, ';'),
  277. assign_statement: ($) =>
  278. seq($._expression, $._assign_operator, $._expression, ';'),
  279. _assign_operator: ($) =>
  280. choice('=', '+=', '/=', '*=', '%=', '-=', '&=', '|=', '^=', '<<=', '>>='),
  281. match_clause: ($) =>
  282. seq(choice(seq('case', $._pattern), 'default'), '=>', $.block),
  283. match_statement: ($) =>
  284. seq('match', '(', $._expression, ')', '{', repeat($.match_clause), '}'),
  285. returned_var_statement: ($) => seq('returned', $.var_declaration),
  286. while_statement: ($) => seq('while', '(', $._expression, ')', $.block),
  287. break_statement: ($) => seq('break', ';'),
  288. continue_statement: ($) => seq('continue', ';'),
  289. return_statement: ($) =>
  290. seq('return', optional(choice('var', $._expression)), ';'),
  291. if_statement: ($) =>
  292. seq('if', '(', $._expression, ')', $.block, optional($.else)),
  293. else: ($) => choice(seq('else', $.if_statement), seq('else', $.block)),
  294. for_statement: ($) =>
  295. seq('for', '(', $._pattern, 'in', $._expression, ')', $.block),
  296. statement: ($) =>
  297. choice(
  298. seq($._expression, ';'),
  299. $.assign_statement,
  300. $.var_declaration,
  301. $.let_declaration,
  302. $.match_statement,
  303. $.returned_var_statement,
  304. $.if_statement,
  305. $.while_statement,
  306. $.break_statement,
  307. $.continue_statement,
  308. $.return_statement,
  309. $.for_statement
  310. ),
  311. block: ($) => seq('{', repeat($.statement), '}'),
  312. declared_name: ($) => repeat_sep1($.ident, '.'),
  313. generic_binding: ($) =>
  314. seq(optional('template'), $.ident, ':!', $._expression),
  315. deduced_param: ($) => $.generic_binding,
  316. deduced_params: ($) => seq('[', comma_sep($.deduced_param), ']'),
  317. return_type: ($) => seq('->', choice('auto', $._expression)),
  318. function_declaration: ($) =>
  319. seq(
  320. optional(choice('abstract', 'virtual', 'impl')),
  321. 'fn',
  322. $.declared_name,
  323. optional($.deduced_params),
  324. $.paren_pattern,
  325. optional($.return_type),
  326. choice($.block, ';')
  327. ),
  328. namespace_declaration: ($) => seq('namespace', $.declared_name, ';'),
  329. alias_declaration: ($) =>
  330. seq('alias', $.declared_name, '=', $._expression, ';'),
  331. type_params: ($) => $.paren_pattern,
  332. interface_body_item: ($) =>
  333. choice(
  334. $.function_declaration,
  335. seq('let', $.generic_binding, ';'),
  336. seq('extend', $._expression, ';'),
  337. seq('require', $._expression, 'impls', $._expression, ';')
  338. ),
  339. interface_body: ($) => seq('{', repeat($.interface_body_item), '}'),
  340. interface_declaration: ($) =>
  341. seq(
  342. 'interface',
  343. $.declared_name,
  344. optional($.deduced_params),
  345. optional($.type_params),
  346. choice(';', $.interface_body)
  347. ),
  348. constraint_declaration: ($) =>
  349. seq(
  350. 'constraint',
  351. $.declared_name,
  352. optional($.deduced_params),
  353. optional($.type_params),
  354. choice(';', $.interface_body)
  355. ),
  356. impl_body_item: ($) => choice($.function_declaration, $.alias_declaration),
  357. impl_body: ($) => seq('{', repeat($.impl_body_item), '}'),
  358. impl_declaration: ($) =>
  359. seq(
  360. 'impl',
  361. optional(seq('forall', $.deduced_params)),
  362. optional($._expression),
  363. 'as',
  364. $._expression,
  365. $.impl_body
  366. ),
  367. extend_impl_declaration: ($) =>
  368. seq('extend', 'impl', 'as', $._expression, $.impl_body),
  369. extend_base_declaration: ($) =>
  370. seq('extend', 'base', ':', $._expression, ';'),
  371. destructor_declaration: ($) =>
  372. seq(
  373. optional(choice('virtual', 'impl')),
  374. 'destructor',
  375. optional($.deduced_params),
  376. choice($.block, ';')
  377. ),
  378. class_body_item: ($) =>
  379. choice(
  380. $.declaration,
  381. $.extend_base_declaration,
  382. $.extend_impl_declaration,
  383. $.mix_declaration,
  384. $.destructor_declaration
  385. ),
  386. class_body: ($) => seq('{', repeat($.class_body_item), '}'),
  387. class_declaration: ($) =>
  388. seq(
  389. optional(choice('base', 'abstract')),
  390. 'class',
  391. $.declared_name,
  392. optional($.deduced_params),
  393. optional($.type_params),
  394. choice(';', $.class_body)
  395. ),
  396. choice_declaration: ($) =>
  397. seq(
  398. 'choice',
  399. $.declared_name,
  400. optional($.type_params),
  401. '{',
  402. comma_sep(seq($.ident, optional($.paren_expression))),
  403. '}'
  404. ),
  405. empty_declaration: ($) => ';',
  406. declaration: ($) =>
  407. choice(
  408. $.empty_declaration,
  409. $.namespace_declaration,
  410. $.var_declaration,
  411. $.let_declaration,
  412. $.function_declaration,
  413. $.alias_declaration,
  414. $.interface_declaration,
  415. $.constraint_declaration,
  416. $.impl_declaration,
  417. $.class_declaration,
  418. $.choice_declaration,
  419. $.mixin_declaration,
  420. $.match_first_declaration
  421. ),
  422. // Explorer only experimental featurues
  423. mix_declaration: ($) => seq('__mix', $._expression, ';'),
  424. mixin_declaration: ($) =>
  425. seq(
  426. '__mixin',
  427. $.declared_name,
  428. optional($.type_params),
  429. optional(seq('for', $._expression)),
  430. '{',
  431. repeat(choice($.function_declaration, $.mix_declaration)),
  432. '}'
  433. ),
  434. match_first_declaration: ($) =>
  435. seq('__match_first', '{', repeat($.impl_declaration), '}'),
  436. },
  437. });