/src/grammar.coffee

http://github.com/jashkenas/coffee-script · CoffeeScript · 963 lines · 678 code · 118 blank · 167 comment · 22 complexity · 27a38b3ee8e956b727f2abd4f0a90d7d MD5 · raw file

  1. # The CoffeeScript parser is generated by [Jison](https://github.com/zaach/jison)
  2. # from this grammar file. Jison is a bottom-up parser generator, similar in
  3. # style to [Bison](http://www.gnu.org/software/bison), implemented in JavaScript.
  4. # It can recognize [LALR(1), LR(0), SLR(1), and LR(1)](https://en.wikipedia.org/wiki/LR_grammar)
  5. # type grammars. To create the Jison parser, we list the pattern to match
  6. # on the left-hand side, and the action to take (usually the creation of syntax
  7. # tree nodes) on the right. As the parser runs, it
  8. # shifts tokens from our token stream, from left to right, and
  9. # [attempts to match](https://en.wikipedia.org/wiki/Bottom-up_parsing)
  10. # the token sequence against the rules below. When a match can be made, it
  11. # reduces into the [nonterminal](https://en.wikipedia.org/wiki/Terminal_and_nonterminal_symbols)
  12. # (the enclosing name at the top), and we proceed from there.
  13. #
  14. # If you run the `cake build:parser` command, Jison constructs a parse table
  15. # from our rules and saves it into `lib/parser.js`.
  16. # The only dependency is on the **Jison.Parser**.
  17. {Parser} = require 'jison'
  18. # Jison DSL
  19. # ---------
  20. # Since we're going to be wrapped in a function by Jison in any case, if our
  21. # action immediately returns a value, we can optimize by removing the function
  22. # wrapper and just returning the value directly.
  23. unwrap = /^function\s*\(\)\s*\{\s*return\s*([\s\S]*);\s*\}/
  24. # Our handy DSL for Jison grammar generation, thanks to
  25. # [Tim Caswell](https://github.com/creationix). For every rule in the grammar,
  26. # we pass the pattern-defining string, the action to run, and extra options,
  27. # optionally. If no action is specified, we simply pass the value of the
  28. # previous nonterminal.
  29. o = (patternString, action, options) ->
  30. patternString = patternString.replace /\s{2,}/g, ' '
  31. patternCount = patternString.split(' ').length
  32. if action
  33. action = if match = unwrap.exec action then match[1] else "(#{action}())"
  34. # All runtime functions we need are defined on `yy`
  35. action = action.replace /\bnew /g, '$&yy.'
  36. action = action.replace /\b(?:Block\.wrap|extend)\b/g, 'yy.$&'
  37. # Returns strings of functions to add to `parser.js` which add extra data
  38. # that nodes may have, such as comments or location data. Location data
  39. # is added to the first parameter passed in, and the parameter is returned.
  40. # If the parameter is not a node, it will just be passed through unaffected.
  41. getAddDataToNodeFunctionString = (first, last, forceUpdateLocation = yes) ->
  42. "yy.addDataToNode(yy, @#{first}, #{if first[0] is '$' then '$$' else '$'}#{first}, #{if last then "@#{last}, #{if last[0] is '$' then '$$' else '$'}#{last}" else 'null, null'}, #{if forceUpdateLocation then 'true' else 'false'})"
  43. returnsLoc = /^LOC/.test action
  44. action = action.replace /LOC\(([0-9]*)\)/g, getAddDataToNodeFunctionString('$1')
  45. action = action.replace /LOC\(([0-9]*),\s*([0-9]*)\)/g, getAddDataToNodeFunctionString('$1', '$2')
  46. performActionFunctionString = "$$ = #{getAddDataToNodeFunctionString(1, patternCount, not returnsLoc)}(#{action});"
  47. else
  48. performActionFunctionString = '$$ = $1;'
  49. [patternString, performActionFunctionString, options]
  50. # Grammatical Rules
  51. # -----------------
  52. # In all of the rules that follow, you'll see the name of the nonterminal as
  53. # the key to a list of alternative matches. With each match's action, the
  54. # dollar-sign variables are provided by Jison as references to the value of
  55. # their numeric position, so in this rule:
  56. #
  57. # 'Expression UNLESS Expression'
  58. #
  59. # `$1` would be the value of the first `Expression`, `$2` would be the token
  60. # for the `UNLESS` terminal, and `$3` would be the value of the second
  61. # `Expression`.
  62. grammar =
  63. # The **Root** is the top-level node in the syntax tree. Since we parse bottom-up,
  64. # all parsing must end here.
  65. Root: [
  66. o '', -> new Root new Block
  67. o 'Body', -> new Root $1
  68. ]
  69. # Any list of statements and expressions, separated by line breaks or semicolons.
  70. Body: [
  71. o 'Line', -> Block.wrap [$1]
  72. o 'Body TERMINATOR Line', -> $1.push $3
  73. o 'Body TERMINATOR'
  74. ]
  75. # Block and statements, which make up a line in a body. YieldReturn is a
  76. # statement, but not included in Statement because that results in an ambiguous
  77. # grammar.
  78. Line: [
  79. o 'Expression'
  80. o 'ExpressionLine'
  81. o 'Statement'
  82. o 'FuncDirective'
  83. ]
  84. FuncDirective: [
  85. o 'YieldReturn'
  86. o 'AwaitReturn'
  87. ]
  88. # Pure statements which cannot be expressions.
  89. Statement: [
  90. o 'Return'
  91. o 'STATEMENT', -> new StatementLiteral $1
  92. o 'Import'
  93. o 'Export'
  94. ]
  95. # All the different types of expressions in our language. The basic unit of
  96. # CoffeeScript is the **Expression** -- everything that can be an expression
  97. # is one. Blocks serve as the building blocks of many other rules, making
  98. # them somewhat circular.
  99. Expression: [
  100. o 'Value'
  101. o 'Code'
  102. o 'Operation'
  103. o 'Assign'
  104. o 'If'
  105. o 'Try'
  106. o 'While'
  107. o 'For'
  108. o 'Switch'
  109. o 'Class'
  110. o 'Throw'
  111. o 'Yield'
  112. ]
  113. # Expressions which are written in single line and would otherwise require being
  114. # wrapped in braces: E.g `a = b if do -> f a is 1`, `if f (a) -> a*2 then ...`,
  115. # `for x in do (obj) -> f obj when x > 8 then f x`
  116. ExpressionLine: [
  117. o 'CodeLine'
  118. o 'IfLine'
  119. o 'OperationLine'
  120. ]
  121. Yield: [
  122. o 'YIELD', -> new Op $1, new Value new Literal ''
  123. o 'YIELD Expression', -> new Op $1, $2
  124. o 'YIELD INDENT Object OUTDENT', -> new Op $1, $3
  125. o 'YIELD FROM Expression', -> new Op $1.concat($2), $3
  126. ]
  127. # An indented block of expressions. Note that the [Rewriter](rewriter.html)
  128. # will convert some postfix forms into blocks for us, by adjusting the
  129. # token stream.
  130. Block: [
  131. o 'INDENT OUTDENT', -> new Block
  132. o 'INDENT Body OUTDENT', -> $2
  133. ]
  134. Identifier: [
  135. o 'IDENTIFIER', -> new IdentifierLiteral $1
  136. o 'JSX_TAG', -> new JSXTag $1.toString(),
  137. tagNameLocationData: $1.tagNameToken[2]
  138. closingTagOpeningBracketLocationData: $1.closingTagOpeningBracketToken?[2]
  139. closingTagSlashLocationData: $1.closingTagSlashToken?[2]
  140. closingTagNameLocationData: $1.closingTagNameToken?[2]
  141. closingTagClosingBracketLocationData: $1.closingTagClosingBracketToken?[2]
  142. ]
  143. Property: [
  144. o 'PROPERTY', -> new PropertyName $1.toString()
  145. ]
  146. # Alphanumerics are separated from the other **Literal** matchers because
  147. # they can also serve as keys in object literals.
  148. AlphaNumeric: [
  149. o 'NUMBER', -> new NumberLiteral $1.toString(), parsedValue: $1.parsedValue
  150. o 'String'
  151. ]
  152. String: [
  153. o 'STRING', ->
  154. new StringLiteral(
  155. $1.slice 1, -1 # strip artificial quotes and unwrap to primitive string
  156. quote: $1.quote
  157. initialChunk: $1.initialChunk
  158. finalChunk: $1.finalChunk
  159. indent: $1.indent
  160. double: $1.double
  161. heregex: $1.heregex
  162. )
  163. o 'STRING_START Interpolations STRING_END', -> new StringWithInterpolations Block.wrap($2), quote: $1.quote, startQuote: LOC(1)(new Literal $1.toString())
  164. ]
  165. Interpolations: [
  166. o 'InterpolationChunk', -> [$1]
  167. o 'Interpolations InterpolationChunk', -> $1.concat $2
  168. ]
  169. InterpolationChunk: [
  170. o 'INTERPOLATION_START Body INTERPOLATION_END', -> new Interpolation $2
  171. o 'INTERPOLATION_START INDENT Body OUTDENT INTERPOLATION_END', -> new Interpolation $3
  172. o 'INTERPOLATION_START INTERPOLATION_END', -> new Interpolation
  173. o 'String', -> $1
  174. ]
  175. # The .toString() calls here and elsewhere are to convert `String` objects
  176. # back to primitive strings now that we've retrieved stowaway extra properties
  177. Regex: [
  178. o 'REGEX', -> new RegexLiteral $1.toString(), delimiter: $1.delimiter, heregexCommentTokens: $1.heregexCommentTokens
  179. o 'REGEX_START Invocation REGEX_END', -> new RegexWithInterpolations $2, heregexCommentTokens: $3.heregexCommentTokens
  180. ]
  181. # All of our immediate values. Generally these can be passed straight
  182. # through and printed to JavaScript.
  183. Literal: [
  184. o 'AlphaNumeric'
  185. o 'JS', -> new PassthroughLiteral $1.toString(), here: $1.here, generated: $1.generated
  186. o 'Regex'
  187. o 'UNDEFINED', -> new UndefinedLiteral $1
  188. o 'NULL', -> new NullLiteral $1
  189. o 'BOOL', -> new BooleanLiteral $1.toString(), originalValue: $1.original
  190. o 'INFINITY', -> new InfinityLiteral $1.toString(), originalValue: $1.original
  191. o 'NAN', -> new NaNLiteral $1
  192. ]
  193. # Assignment of a variable, property, or index to a value.
  194. Assign: [
  195. o 'Assignable = Expression', -> new Assign $1, $3
  196. o 'Assignable = TERMINATOR Expression', -> new Assign $1, $4
  197. o 'Assignable = INDENT Expression OUTDENT', -> new Assign $1, $4
  198. ]
  199. # Assignment when it happens within an object literal. The difference from
  200. # the ordinary **Assign** is that these allow numbers and strings as keys.
  201. AssignObj: [
  202. o 'ObjAssignable', -> new Value $1
  203. o 'ObjRestValue'
  204. o 'ObjAssignable : Expression', -> new Assign LOC(1)(new Value $1), $3, 'object',
  205. operatorToken: LOC(2)(new Literal $2)
  206. o 'ObjAssignable :
  207. INDENT Expression OUTDENT', -> new Assign LOC(1)(new Value $1), $4, 'object',
  208. operatorToken: LOC(2)(new Literal $2)
  209. o 'SimpleObjAssignable = Expression', -> new Assign LOC(1)(new Value $1), $3, null,
  210. operatorToken: LOC(2)(new Literal $2)
  211. o 'SimpleObjAssignable =
  212. INDENT Expression OUTDENT', -> new Assign LOC(1)(new Value $1), $4, null,
  213. operatorToken: LOC(2)(new Literal $2)
  214. ]
  215. SimpleObjAssignable: [
  216. o 'Identifier'
  217. o 'Property'
  218. o 'ThisProperty'
  219. ]
  220. ObjAssignable: [
  221. o 'SimpleObjAssignable'
  222. o '[ Expression ]', -> new Value new ComputedPropertyName $2
  223. o '@ [ Expression ]', -> new Value LOC(1)(new ThisLiteral $1), [LOC(3)(new ComputedPropertyName($3))], 'this'
  224. o 'AlphaNumeric'
  225. ]
  226. # Object literal spread properties.
  227. ObjRestValue: [
  228. o 'SimpleObjAssignable ...', -> new Splat new Value $1
  229. o '... SimpleObjAssignable', -> new Splat new Value($2), postfix: no
  230. o 'ObjSpreadExpr ...', -> new Splat $1
  231. o '... ObjSpreadExpr', -> new Splat $2, postfix: no
  232. ]
  233. ObjSpreadExpr: [
  234. o 'ObjSpreadIdentifier'
  235. o 'Object'
  236. o 'Parenthetical'
  237. o 'Super'
  238. o 'This'
  239. o 'SUPER OptFuncExist Arguments', -> new SuperCall LOC(1)(new Super), $3, $2.soak, $1
  240. o 'DYNAMIC_IMPORT Arguments', -> new DynamicImportCall LOC(1)(new DynamicImport), $2
  241. o 'SimpleObjAssignable OptFuncExist Arguments', -> new Call (new Value $1), $3, $2.soak
  242. o 'ObjSpreadExpr OptFuncExist Arguments', -> new Call $1, $3, $2.soak
  243. ]
  244. ObjSpreadIdentifier: [
  245. o 'SimpleObjAssignable Accessor', -> (new Value $1).add $2
  246. o 'ObjSpreadExpr Accessor', -> (new Value $1).add $2
  247. ]
  248. # A return statement from a function body.
  249. Return: [
  250. o 'RETURN Expression', -> new Return $2
  251. o 'RETURN INDENT Object OUTDENT', -> new Return new Value $3
  252. o 'RETURN', -> new Return
  253. ]
  254. YieldReturn: [
  255. o 'YIELD RETURN Expression', -> new YieldReturn $3, returnKeyword: LOC(2)(new Literal $2)
  256. o 'YIELD RETURN', -> new YieldReturn null, returnKeyword: LOC(2)(new Literal $2)
  257. ]
  258. AwaitReturn: [
  259. o 'AWAIT RETURN Expression', -> new AwaitReturn $3, returnKeyword: LOC(2)(new Literal $2)
  260. o 'AWAIT RETURN', -> new AwaitReturn null, returnKeyword: LOC(2)(new Literal $2)
  261. ]
  262. # The **Code** node is the function literal. It's defined by an indented block
  263. # of **Block** preceded by a function arrow, with an optional parameter list.
  264. Code: [
  265. o 'PARAM_START ParamList PARAM_END FuncGlyph Block', -> new Code $2, $5, $4, LOC(1)(new Literal $1)
  266. o 'FuncGlyph Block', -> new Code [], $2, $1
  267. ]
  268. # The Codeline is the **Code** node with **Line** instead of indented **Block**.
  269. CodeLine: [
  270. o 'PARAM_START ParamList PARAM_END FuncGlyph Line', -> new Code $2, LOC(5)(Block.wrap [$5]), $4,
  271. LOC(1)(new Literal $1)
  272. o 'FuncGlyph Line', -> new Code [], LOC(2)(Block.wrap [$2]), $1
  273. ]
  274. # CoffeeScript has two different symbols for functions. `->` is for ordinary
  275. # functions, and `=>` is for functions bound to the current value of *this*.
  276. FuncGlyph: [
  277. o '->', -> new FuncGlyph $1
  278. o '=>', -> new FuncGlyph $1
  279. ]
  280. # An optional, trailing comma.
  281. OptComma: [
  282. o ''
  283. o ','
  284. ]
  285. # The list of parameters that a function accepts can be of any length.
  286. ParamList: [
  287. o '', -> []
  288. o 'Param', -> [$1]
  289. o 'ParamList , Param', -> $1.concat $3
  290. o 'ParamList OptComma TERMINATOR Param', -> $1.concat $4
  291. o 'ParamList OptComma INDENT ParamList OptComma OUTDENT', -> $1.concat $4
  292. ]
  293. # A single parameter in a function definition can be ordinary, or a splat
  294. # that hoovers up the remaining arguments.
  295. Param: [
  296. o 'ParamVar', -> new Param $1
  297. o 'ParamVar ...', -> new Param $1, null, on
  298. o '... ParamVar', -> new Param $2, null, postfix: no
  299. o 'ParamVar = Expression', -> new Param $1, $3
  300. o '...', -> new Expansion
  301. ]
  302. # Function Parameters
  303. ParamVar: [
  304. o 'Identifier'
  305. o 'ThisProperty'
  306. o 'Array'
  307. o 'Object'
  308. ]
  309. # A splat that occurs outside of a parameter list.
  310. Splat: [
  311. o 'Expression ...', -> new Splat $1
  312. o '... Expression', -> new Splat $2, {postfix: no}
  313. ]
  314. # Variables and properties that can be assigned to.
  315. SimpleAssignable: [
  316. o 'Identifier', -> new Value $1
  317. o 'Value Accessor', -> $1.add $2
  318. o 'Code Accessor', -> new Value($1).add $2
  319. o 'ThisProperty'
  320. ]
  321. # Everything that can be assigned to.
  322. Assignable: [
  323. o 'SimpleAssignable'
  324. o 'Array', -> new Value $1
  325. o 'Object', -> new Value $1
  326. ]
  327. # The types of things that can be treated as values -- assigned to, invoked
  328. # as functions, indexed into, named as a class, etc.
  329. Value: [
  330. o 'Assignable'
  331. o 'Literal', -> new Value $1
  332. o 'Parenthetical', -> new Value $1
  333. o 'Range', -> new Value $1
  334. o 'Invocation', -> new Value $1
  335. o 'DoIife', -> new Value $1
  336. o 'This'
  337. o 'Super', -> new Value $1
  338. o 'MetaProperty', -> new Value $1
  339. ]
  340. # A `super`-based expression that can be used as a value.
  341. Super: [
  342. o 'SUPER . Property', -> new Super LOC(3)(new Access $3), LOC(1)(new Literal $1)
  343. o 'SUPER INDEX_START Expression INDEX_END', -> new Super LOC(3)(new Index $3), LOC(1)(new Literal $1)
  344. o 'SUPER INDEX_START INDENT Expression OUTDENT INDEX_END', -> new Super LOC(4)(new Index $4), LOC(1)(new Literal $1)
  345. ]
  346. # A "meta-property" access e.g. `new.target`
  347. MetaProperty: [
  348. o 'NEW_TARGET . Property', -> new MetaProperty LOC(1)(new IdentifierLiteral $1), LOC(3)(new Access $3)
  349. ]
  350. # The general group of accessors into an object, by property, by prototype
  351. # or by array index or slice.
  352. Accessor: [
  353. o '. Property', -> new Access $2
  354. o '?. Property', -> new Access $2, soak: yes
  355. o ':: Property', -> [LOC(1)(new Access new PropertyName('prototype'), shorthand: yes), LOC(2)(new Access $2)]
  356. o '?:: Property', -> [LOC(1)(new Access new PropertyName('prototype'), shorthand: yes, soak: yes), LOC(2)(new Access $2)]
  357. o '::', -> new Access new PropertyName('prototype'), shorthand: yes
  358. o '?::', -> new Access new PropertyName('prototype'), shorthand: yes, soak: yes
  359. o 'Index'
  360. ]
  361. # Indexing into an object or array using bracket notation.
  362. Index: [
  363. o 'INDEX_START IndexValue INDEX_END', -> $2
  364. o 'INDEX_START INDENT IndexValue OUTDENT INDEX_END', -> $3
  365. o 'INDEX_SOAK Index', -> extend $2, soak: yes
  366. ]
  367. IndexValue: [
  368. o 'Expression', -> new Index $1
  369. o 'Slice', -> new Slice $1
  370. ]
  371. # In CoffeeScript, an object literal is simply a list of assignments.
  372. Object: [
  373. o '{ AssignList OptComma }', -> new Obj $2, $1.generated
  374. ]
  375. # Assignment of properties within an object literal can be separated by
  376. # comma, as in JavaScript, or simply by newline.
  377. AssignList: [
  378. o '', -> []
  379. o 'AssignObj', -> [$1]
  380. o 'AssignList , AssignObj', -> $1.concat $3
  381. o 'AssignList OptComma TERMINATOR AssignObj', -> $1.concat $4
  382. o 'AssignList OptComma INDENT AssignList OptComma OUTDENT', -> $1.concat $4
  383. ]
  384. # Class definitions have optional bodies of prototype property assignments,
  385. # and optional references to the superclass.
  386. Class: [
  387. o 'CLASS', -> new Class
  388. o 'CLASS Block', -> new Class null, null, $2
  389. o 'CLASS EXTENDS Expression', -> new Class null, $3
  390. o 'CLASS EXTENDS Expression Block', -> new Class null, $3, $4
  391. o 'CLASS SimpleAssignable', -> new Class $2
  392. o 'CLASS SimpleAssignable Block', -> new Class $2, null, $3
  393. o 'CLASS SimpleAssignable EXTENDS Expression', -> new Class $2, $4
  394. o 'CLASS SimpleAssignable EXTENDS Expression Block', -> new Class $2, $4, $5
  395. ]
  396. Import: [
  397. o 'IMPORT String', -> new ImportDeclaration null, $2
  398. o 'IMPORT ImportDefaultSpecifier FROM String', -> new ImportDeclaration new ImportClause($2, null), $4
  399. o 'IMPORT ImportNamespaceSpecifier FROM String', -> new ImportDeclaration new ImportClause(null, $2), $4
  400. o 'IMPORT { } FROM String', -> new ImportDeclaration new ImportClause(null, new ImportSpecifierList []), $5
  401. o 'IMPORT { ImportSpecifierList OptComma } FROM String', -> new ImportDeclaration new ImportClause(null, new ImportSpecifierList $3), $7
  402. o 'IMPORT ImportDefaultSpecifier , ImportNamespaceSpecifier FROM String', -> new ImportDeclaration new ImportClause($2, $4), $6
  403. o 'IMPORT ImportDefaultSpecifier , { ImportSpecifierList OptComma } FROM String', -> new ImportDeclaration new ImportClause($2, new ImportSpecifierList $5), $9
  404. ]
  405. ImportSpecifierList: [
  406. o 'ImportSpecifier', -> [$1]
  407. o 'ImportSpecifierList , ImportSpecifier', -> $1.concat $3
  408. o 'ImportSpecifierList OptComma TERMINATOR ImportSpecifier', -> $1.concat $4
  409. o 'INDENT ImportSpecifierList OptComma OUTDENT', -> $2
  410. o 'ImportSpecifierList OptComma INDENT ImportSpecifierList OptComma OUTDENT', -> $1.concat $4
  411. ]
  412. ImportSpecifier: [
  413. o 'Identifier', -> new ImportSpecifier $1
  414. o 'Identifier AS Identifier', -> new ImportSpecifier $1, $3
  415. o 'DEFAULT', -> new ImportSpecifier LOC(1)(new DefaultLiteral $1)
  416. o 'DEFAULT AS Identifier', -> new ImportSpecifier LOC(1)(new DefaultLiteral($1)), $3
  417. ]
  418. ImportDefaultSpecifier: [
  419. o 'Identifier', -> new ImportDefaultSpecifier $1
  420. ]
  421. ImportNamespaceSpecifier: [
  422. o 'IMPORT_ALL AS Identifier', -> new ImportNamespaceSpecifier new Literal($1), $3
  423. ]
  424. Export: [
  425. o 'EXPORT { }', -> new ExportNamedDeclaration new ExportSpecifierList []
  426. o 'EXPORT { ExportSpecifierList OptComma }', -> new ExportNamedDeclaration new ExportSpecifierList $3
  427. o 'EXPORT Class', -> new ExportNamedDeclaration $2
  428. o 'EXPORT Identifier = Expression', -> new ExportNamedDeclaration LOC(2,4)(new Assign $2, $4, null,
  429. moduleDeclaration: 'export')
  430. o 'EXPORT Identifier = TERMINATOR Expression', -> new ExportNamedDeclaration LOC(2,5)(new Assign $2, $5, null,
  431. moduleDeclaration: 'export')
  432. o 'EXPORT Identifier = INDENT Expression OUTDENT', -> new ExportNamedDeclaration LOC(2,6)(new Assign $2, $5, null,
  433. moduleDeclaration: 'export')
  434. o 'EXPORT DEFAULT Expression', -> new ExportDefaultDeclaration $3
  435. o 'EXPORT DEFAULT INDENT Object OUTDENT', -> new ExportDefaultDeclaration new Value $4
  436. o 'EXPORT EXPORT_ALL FROM String', -> new ExportAllDeclaration new Literal($2), $4
  437. o 'EXPORT { } FROM String', -> new ExportNamedDeclaration new ExportSpecifierList([]), $5
  438. o 'EXPORT { ExportSpecifierList OptComma } FROM String', -> new ExportNamedDeclaration new ExportSpecifierList($3), $7
  439. ]
  440. ExportSpecifierList: [
  441. o 'ExportSpecifier', -> [$1]
  442. o 'ExportSpecifierList , ExportSpecifier', -> $1.concat $3
  443. o 'ExportSpecifierList OptComma TERMINATOR ExportSpecifier', -> $1.concat $4
  444. o 'INDENT ExportSpecifierList OptComma OUTDENT', -> $2
  445. o 'ExportSpecifierList OptComma INDENT ExportSpecifierList OptComma OUTDENT', -> $1.concat $4
  446. ]
  447. ExportSpecifier: [
  448. o 'Identifier', -> new ExportSpecifier $1
  449. o 'Identifier AS Identifier', -> new ExportSpecifier $1, $3
  450. o 'Identifier AS DEFAULT', -> new ExportSpecifier $1, LOC(3)(new DefaultLiteral $3)
  451. o 'DEFAULT', -> new ExportSpecifier LOC(1)(new DefaultLiteral $1)
  452. o 'DEFAULT AS Identifier', -> new ExportSpecifier LOC(1)(new DefaultLiteral($1)), $3
  453. ]
  454. # Ordinary function invocation, or a chained series of calls.
  455. Invocation: [
  456. o 'Value OptFuncExist String', -> new TaggedTemplateCall $1, $3, $2.soak
  457. o 'Value OptFuncExist Arguments', -> new Call $1, $3, $2.soak
  458. o 'SUPER OptFuncExist Arguments', -> new SuperCall LOC(1)(new Super), $3, $2.soak, $1
  459. o 'DYNAMIC_IMPORT Arguments', -> new DynamicImportCall LOC(1)(new DynamicImport), $2
  460. ]
  461. # An optional existence check on a function.
  462. OptFuncExist: [
  463. o '', -> soak: no
  464. o 'FUNC_EXIST', -> soak: yes
  465. ]
  466. # The list of arguments to a function call.
  467. Arguments: [
  468. o 'CALL_START CALL_END', -> []
  469. o 'CALL_START ArgList OptComma CALL_END', -> $2.implicit = $1.generated; $2
  470. ]
  471. # A reference to the *this* current object.
  472. This: [
  473. o 'THIS', -> new Value new ThisLiteral $1
  474. o '@', -> new Value new ThisLiteral $1
  475. ]
  476. # A reference to a property on *this*.
  477. ThisProperty: [
  478. o '@ Property', -> new Value LOC(1)(new ThisLiteral $1), [LOC(2)(new Access($2))], 'this'
  479. ]
  480. # The array literal.
  481. Array: [
  482. o '[ ]', -> new Arr []
  483. o '[ Elisions ]', -> new Arr $2
  484. o '[ ArgElisionList OptElisions ]', -> new Arr [].concat $2, $3
  485. ]
  486. # Inclusive and exclusive range dots.
  487. RangeDots: [
  488. o '..', -> exclusive: no
  489. o '...', -> exclusive: yes
  490. ]
  491. # The CoffeeScript range literal.
  492. Range: [
  493. o '[ Expression RangeDots Expression ]', -> new Range $2, $4, if $3.exclusive then 'exclusive' else 'inclusive'
  494. o '[ ExpressionLine RangeDots Expression ]', -> new Range $2, $4, if $3.exclusive then 'exclusive' else 'inclusive'
  495. ]
  496. # Array slice literals.
  497. Slice: [
  498. o 'Expression RangeDots Expression', -> new Range $1, $3, if $2.exclusive then 'exclusive' else 'inclusive'
  499. o 'Expression RangeDots', -> new Range $1, null, if $2.exclusive then 'exclusive' else 'inclusive'
  500. o 'ExpressionLine RangeDots Expression', -> new Range $1, $3, if $2.exclusive then 'exclusive' else 'inclusive'
  501. o 'ExpressionLine RangeDots', -> new Range $1, null, if $2.exclusive then 'exclusive' else 'inclusive'
  502. o 'RangeDots Expression', -> new Range null, $2, if $1.exclusive then 'exclusive' else 'inclusive'
  503. o 'RangeDots', -> new Range null, null, if $1.exclusive then 'exclusive' else 'inclusive'
  504. ]
  505. # The **ArgList** is the list of objects passed into a function call
  506. # (i.e. comma-separated expressions). Newlines work as well.
  507. ArgList: [
  508. o 'Arg', -> [$1]
  509. o 'ArgList , Arg', -> $1.concat $3
  510. o 'ArgList OptComma TERMINATOR Arg', -> $1.concat $4
  511. o 'INDENT ArgList OptComma OUTDENT', -> $2
  512. o 'ArgList OptComma INDENT ArgList OptComma OUTDENT', -> $1.concat $4
  513. ]
  514. # Valid arguments are Blocks or Splats.
  515. Arg: [
  516. o 'Expression'
  517. o 'ExpressionLine'
  518. o 'Splat'
  519. o '...', -> new Expansion
  520. ]
  521. # The **ArgElisionList** is the list of objects, contents of an array literal
  522. # (i.e. comma-separated expressions and elisions). Newlines work as well.
  523. ArgElisionList: [
  524. o 'ArgElision'
  525. o 'ArgElisionList , ArgElision', -> $1.concat $3
  526. o 'ArgElisionList OptComma TERMINATOR ArgElision', -> $1.concat $4
  527. o 'INDENT ArgElisionList OptElisions OUTDENT', -> $2.concat $3
  528. o 'ArgElisionList OptElisions INDENT ArgElisionList OptElisions OUTDENT', -> $1.concat $2, $4, $5
  529. ]
  530. ArgElision: [
  531. o 'Arg', -> [$1]
  532. o 'Elisions Arg', -> $1.concat $2
  533. ]
  534. OptElisions: [
  535. o 'OptComma', -> []
  536. o ', Elisions', -> [].concat $2
  537. ]
  538. Elisions: [
  539. o 'Elision', -> [$1]
  540. o 'Elisions Elision', -> $1.concat $2
  541. ]
  542. Elision: [
  543. o ',', -> new Elision
  544. o 'Elision TERMINATOR', -> $1
  545. ]
  546. # Just simple, comma-separated, required arguments (no fancy syntax). We need
  547. # this to be separate from the **ArgList** for use in **Switch** blocks, where
  548. # having the newlines wouldn't make sense.
  549. SimpleArgs: [
  550. o 'Expression'
  551. o 'ExpressionLine'
  552. o 'SimpleArgs , Expression', -> [].concat $1, $3
  553. o 'SimpleArgs , ExpressionLine', -> [].concat $1, $3
  554. ]
  555. # The variants of *try/catch/finally* exception handling blocks.
  556. Try: [
  557. o 'TRY Block', -> new Try $2
  558. o 'TRY Block Catch', -> new Try $2, $3
  559. o 'TRY Block FINALLY Block', -> new Try $2, null, $4, LOC(3)(new Literal $3)
  560. o 'TRY Block Catch FINALLY Block', -> new Try $2, $3, $5, LOC(4)(new Literal $4)
  561. ]
  562. # A catch clause names its error and runs a block of code.
  563. Catch: [
  564. o 'CATCH Identifier Block', -> new Catch $3, $2
  565. o 'CATCH Object Block', -> new Catch $3, LOC(2)(new Value($2))
  566. o 'CATCH Block', -> new Catch $2
  567. ]
  568. # Throw an exception object.
  569. Throw: [
  570. o 'THROW Expression', -> new Throw $2
  571. o 'THROW INDENT Object OUTDENT', -> new Throw new Value $3
  572. ]
  573. # Parenthetical expressions. Note that the **Parenthetical** is a **Value**,
  574. # not an **Expression**, so if you need to use an expression in a place
  575. # where only values are accepted, wrapping it in parentheses will always do
  576. # the trick.
  577. Parenthetical: [
  578. o '( Body )', -> new Parens $2
  579. o '( INDENT Body OUTDENT )', -> new Parens $3
  580. ]
  581. # The condition portion of a while loop.
  582. WhileLineSource: [
  583. o 'WHILE ExpressionLine', -> new While $2
  584. o 'WHILE ExpressionLine WHEN ExpressionLine', -> new While $2, guard: $4
  585. o 'UNTIL ExpressionLine', -> new While $2, invert: true
  586. o 'UNTIL ExpressionLine WHEN ExpressionLine', -> new While $2, invert: true, guard: $4
  587. ]
  588. WhileSource: [
  589. o 'WHILE Expression', -> new While $2
  590. o 'WHILE Expression WHEN Expression', -> new While $2, guard: $4
  591. o 'WHILE ExpressionLine WHEN Expression', -> new While $2, guard: $4
  592. o 'UNTIL Expression', -> new While $2, invert: true
  593. o 'UNTIL Expression WHEN Expression', -> new While $2, invert: true, guard: $4
  594. o 'UNTIL ExpressionLine WHEN Expression', -> new While $2, invert: true, guard: $4
  595. ]
  596. # The while loop can either be normal, with a block of expressions to execute,
  597. # or postfix, with a single expression. There is no do..while.
  598. While: [
  599. o 'WhileSource Block', -> $1.addBody $2
  600. o 'WhileLineSource Block', -> $1.addBody $2
  601. o 'Statement WhileSource', -> (Object.assign $2, postfix: yes).addBody LOC(1) Block.wrap([$1])
  602. o 'Expression WhileSource', -> (Object.assign $2, postfix: yes).addBody LOC(1) Block.wrap([$1])
  603. o 'Loop', -> $1
  604. ]
  605. Loop: [
  606. o 'LOOP Block', -> new While(LOC(1)(new BooleanLiteral 'true'), isLoop: yes).addBody $2
  607. o 'LOOP Expression', -> new While(LOC(1)(new BooleanLiteral 'true'), isLoop: yes).addBody LOC(2) Block.wrap [$2]
  608. ]
  609. # Array, object, and range comprehensions, at the most generic level.
  610. # Comprehensions can either be normal, with a block of expressions to execute,
  611. # or postfix, with a single expression.
  612. For: [
  613. o 'Statement ForBody', -> $2.postfix = yes; $2.addBody $1
  614. o 'Expression ForBody', -> $2.postfix = yes; $2.addBody $1
  615. o 'ForBody Block', -> $1.addBody $2
  616. o 'ForLineBody Block', -> $1.addBody $2
  617. ]
  618. ForBody: [
  619. o 'FOR Range', -> new For [], source: (LOC(2) new Value($2))
  620. o 'FOR Range BY Expression', -> new For [], source: (LOC(2) new Value($2)), step: $4
  621. o 'ForStart ForSource', -> $1.addSource $2
  622. ]
  623. ForLineBody: [
  624. o 'FOR Range BY ExpressionLine', -> new For [], source: (LOC(2) new Value($2)), step: $4
  625. o 'ForStart ForLineSource', -> $1.addSource $2
  626. ]
  627. ForStart: [
  628. o 'FOR ForVariables', -> new For [], name: $2[0], index: $2[1]
  629. o 'FOR AWAIT ForVariables', ->
  630. [name, index] = $3
  631. new For [], {name, index, await: yes, awaitTag: (LOC(2) new Literal($2))}
  632. o 'FOR OWN ForVariables', ->
  633. [name, index] = $3
  634. new For [], {name, index, own: yes, ownTag: (LOC(2) new Literal($2))}
  635. ]
  636. # An array of all accepted values for a variable inside the loop.
  637. # This enables support for pattern matching.
  638. ForValue: [
  639. o 'Identifier'
  640. o 'ThisProperty'
  641. o 'Array', -> new Value $1
  642. o 'Object', -> new Value $1
  643. ]
  644. # An array or range comprehension has variables for the current element
  645. # and (optional) reference to the current index. Or, *key, value*, in the case
  646. # of object comprehensions.
  647. ForVariables: [
  648. o 'ForValue', -> [$1]
  649. o 'ForValue , ForValue', -> [$1, $3]
  650. ]
  651. # The source of a comprehension is an array or object with an optional guard
  652. # clause. If it's an array comprehension, you can also choose to step through
  653. # in fixed-size increments.
  654. ForSource: [
  655. o 'FORIN Expression', -> source: $2
  656. o 'FOROF Expression', -> source: $2, object: yes
  657. o 'FORIN Expression WHEN Expression', -> source: $2, guard: $4
  658. o 'FORIN ExpressionLine WHEN Expression', -> source: $2, guard: $4
  659. o 'FOROF Expression WHEN Expression', -> source: $2, guard: $4, object: yes
  660. o 'FOROF ExpressionLine WHEN Expression', -> source: $2, guard: $4, object: yes
  661. o 'FORIN Expression BY Expression', -> source: $2, step: $4
  662. o 'FORIN ExpressionLine BY Expression', -> source: $2, step: $4
  663. o 'FORIN Expression WHEN Expression BY Expression', -> source: $2, guard: $4, step: $6
  664. o 'FORIN ExpressionLine WHEN Expression BY Expression', -> source: $2, guard: $4, step: $6
  665. o 'FORIN Expression WHEN ExpressionLine BY Expression', -> source: $2, guard: $4, step: $6
  666. o 'FORIN ExpressionLine WHEN ExpressionLine BY Expression', -> source: $2, guard: $4, step: $6
  667. o 'FORIN Expression BY Expression WHEN Expression', -> source: $2, step: $4, guard: $6
  668. o 'FORIN ExpressionLine BY Expression WHEN Expression', -> source: $2, step: $4, guard: $6
  669. o 'FORIN Expression BY ExpressionLine WHEN Expression', -> source: $2, step: $4, guard: $6
  670. o 'FORIN ExpressionLine BY ExpressionLine WHEN Expression', -> source: $2, step: $4, guard: $6
  671. o 'FORFROM Expression', -> source: $2, from: yes
  672. o 'FORFROM Expression WHEN Expression', -> source: $2, guard: $4, from: yes
  673. o 'FORFROM ExpressionLine WHEN Expression', -> source: $2, guard: $4, from: yes
  674. ]
  675. ForLineSource: [
  676. o 'FORIN ExpressionLine', -> source: $2
  677. o 'FOROF ExpressionLine', -> source: $2, object: yes
  678. o 'FORIN Expression WHEN ExpressionLine', -> source: $2, guard: $4
  679. o 'FORIN ExpressionLine WHEN ExpressionLine', -> source: $2, guard: $4
  680. o 'FOROF Expression WHEN ExpressionLine', -> source: $2, guard: $4, object: yes
  681. o 'FOROF ExpressionLine WHEN ExpressionLine', -> source: $2, guard: $4, object: yes
  682. o 'FORIN Expression BY ExpressionLine', -> source: $2, step: $4
  683. o 'FORIN ExpressionLine BY ExpressionLine', -> source: $2, step: $4
  684. o 'FORIN Expression WHEN Expression BY ExpressionLine', -> source: $2, guard: $4, step: $6
  685. o 'FORIN ExpressionLine WHEN Expression BY ExpressionLine', -> source: $2, guard: $4, step: $6
  686. o 'FORIN Expression WHEN ExpressionLine BY ExpressionLine', -> source: $2, guard: $4, step: $6
  687. o 'FORIN ExpressionLine WHEN ExpressionLine BY ExpressionLine', -> source: $2, guard: $4, step: $6
  688. o 'FORIN Expression BY Expression WHEN ExpressionLine', -> source: $2, step: $4, guard: $6
  689. o 'FORIN ExpressionLine BY Expression WHEN ExpressionLine', -> source: $2, step: $4, guard: $6
  690. o 'FORIN Expression BY ExpressionLine WHEN ExpressionLine', -> source: $2, step: $4, guard: $6
  691. o 'FORIN ExpressionLine BY ExpressionLine WHEN ExpressionLine', -> source: $2, step: $4, guard: $6
  692. o 'FORFROM ExpressionLine', -> source: $2, from: yes
  693. o 'FORFROM Expression WHEN ExpressionLine', -> source: $2, guard: $4, from: yes
  694. o 'FORFROM ExpressionLine WHEN ExpressionLine', -> source: $2, guard: $4, from: yes
  695. ]
  696. Switch: [
  697. o 'SWITCH Expression INDENT Whens OUTDENT', -> new Switch $2, $4
  698. o 'SWITCH ExpressionLine INDENT Whens OUTDENT', -> new Switch $2, $4
  699. o 'SWITCH Expression INDENT Whens ELSE Block OUTDENT', -> new Switch $2, $4, LOC(5,6) $6
  700. o 'SWITCH ExpressionLine INDENT Whens ELSE Block OUTDENT', -> new Switch $2, $4, LOC(5,6) $6
  701. o 'SWITCH INDENT Whens OUTDENT', -> new Switch null, $3
  702. o 'SWITCH INDENT Whens ELSE Block OUTDENT', -> new Switch null, $3, LOC(4,5) $5
  703. ]
  704. Whens: [
  705. o 'When', -> [$1]
  706. o 'Whens When', -> $1.concat $2
  707. ]
  708. # An individual **When** clause, with action.
  709. When: [
  710. o 'LEADING_WHEN SimpleArgs Block', -> new SwitchWhen $2, $3
  711. o 'LEADING_WHEN SimpleArgs Block TERMINATOR', -> LOC(1, 3) new SwitchWhen $2, $3
  712. ]
  713. # The most basic form of *if* is a condition and an action. The following
  714. # if-related rules are broken up along these lines in order to avoid
  715. # ambiguity.
  716. IfBlock: [
  717. o 'IF Expression Block', -> new If $2, $3, type: $1
  718. o 'IfBlock ELSE IF Expression Block', -> $1.addElse LOC(3,5) new If $4, $5, type: $3
  719. ]
  720. # The full complement of *if* expressions, including postfix one-liner
  721. # *if* and *unless*.
  722. If: [
  723. o 'IfBlock'
  724. o 'IfBlock ELSE Block', -> $1.addElse $3
  725. o 'Statement POST_IF Expression', -> new If $3, LOC(1)(Block.wrap [$1]), type: $2, postfix: true
  726. o 'Expression POST_IF Expression', -> new If $3, LOC(1)(Block.wrap [$1]), type: $2, postfix: true
  727. ]
  728. IfBlockLine: [
  729. o 'IF ExpressionLine Block', -> new If $2, $3, type: $1
  730. o 'IfBlockLine ELSE IF ExpressionLine Block', -> $1.addElse LOC(3,5) new If $4, $5, type: $3
  731. ]
  732. IfLine: [
  733. o 'IfBlockLine'
  734. o 'IfBlockLine ELSE Block', -> $1.addElse $3
  735. o 'Statement POST_IF ExpressionLine', -> new If $3, LOC(1)(Block.wrap [$1]), type: $2, postfix: true
  736. o 'Expression POST_IF ExpressionLine', -> new If $3, LOC(1)(Block.wrap [$1]), type: $2, postfix: true
  737. ]
  738. # Arithmetic and logical operators, working on one or more operands.
  739. # Here they are grouped by order of precedence. The actual precedence rules
  740. # are defined at the bottom of the page. It would be shorter if we could
  741. # combine most of these rules into a single generic *Operand OpSymbol Operand*
  742. # -type rule, but in order to make the precedence binding possible, separate
  743. # rules are necessary.
  744. OperationLine: [
  745. o 'UNARY ExpressionLine', -> new Op $1, $2
  746. o 'DO ExpressionLine', -> new Op $1, $2
  747. o 'DO_IIFE CodeLine', -> new Op $1, $2
  748. ]
  749. Operation: [
  750. o 'UNARY Expression', -> new Op $1.toString(), $2, undefined, undefined, originalOperator: $1.original
  751. o 'DO Expression', -> new Op $1, $2
  752. o 'UNARY_MATH Expression', -> new Op $1, $2
  753. o '- Expression', (-> new Op '-', $2), prec: 'UNARY_MATH'
  754. o '+ Expression', (-> new Op '+', $2), prec: 'UNARY_MATH'
  755. o 'AWAIT Expression', -> new Op $1, $2
  756. o 'AWAIT INDENT Object OUTDENT', -> new Op $1, $3
  757. o '-- SimpleAssignable', -> new Op '--', $2
  758. o '++ SimpleAssignable', -> new Op '++', $2
  759. o 'SimpleAssignable --', -> new Op '--', $1, null, true
  760. o 'SimpleAssignable ++', -> new Op '++', $1, null, true
  761. # [The existential operator](https://coffeescript.org/#existential-operator).
  762. o 'Expression ?', -> new Existence $1
  763. o 'Expression + Expression', -> new Op '+' , $1, $3
  764. o 'Expression - Expression', -> new Op '-' , $1, $3
  765. o 'Expression MATH Expression', -> new Op $2, $1, $3
  766. o 'Expression ** Expression', -> new Op $2, $1, $3
  767. o 'Expression SHIFT Expression', -> new Op $2, $1, $3
  768. o 'Expression COMPARE Expression', -> new Op $2.toString(), $1, $3, undefined, originalOperator: $2.original
  769. o 'Expression & Expression', -> new Op $2, $1, $3
  770. o 'Expression ^ Expression', -> new Op $2, $1, $3
  771. o 'Expression | Expression', -> new Op $2, $1, $3
  772. o 'Expression && Expression', -> new Op $2.toString(), $1, $3, undefined, originalOperator: $2.original
  773. o 'Expression || Expression', -> new Op $2.toString(), $1, $3, undefined, originalOperator: $2.original
  774. o 'Expression BIN? Expression', -> new Op $2, $1, $3
  775. o 'Expression RELATION Expression', -> new Op $2.toString(), $1, $3, undefined, invertOperator: $2.invert?.original ? $2.invert
  776. o 'SimpleAssignable COMPOUND_ASSIGN
  777. Expression', -> new Assign $1, $3, $2.toString(), originalContext: $2.original
  778. o 'SimpleAssignable COMPOUND_ASSIGN
  779. INDENT Expression OUTDENT', -> new Assign $1, $4, $2.toString(), originalContext: $2.original
  780. o 'SimpleAssignable COMPOUND_ASSIGN TERMINATOR
  781. Expression', -> new Assign $1, $4, $2.toString(), originalContext: $2.original
  782. ]
  783. DoIife: [
  784. o 'DO_IIFE Code', -> new Op $1 , $2
  785. ]
  786. # Precedence
  787. # ----------
  788. # Operators at the top of this list have higher precedence than the ones lower
  789. # down. Following these rules is what makes `2 + 3 * 4` parse as:
  790. #
  791. # 2 + (3 * 4)
  792. #
  793. # And not:
  794. #
  795. # (2 + 3) * 4
  796. operators = [
  797. ['right', 'DO_IIFE']
  798. ['left', '.', '?.', '::', '?::']
  799. ['left', 'CALL_START', 'CALL_END']
  800. ['nonassoc', '++', '--']
  801. ['left', '?']
  802. ['right', 'UNARY', 'DO']
  803. ['right', 'AWAIT']
  804. ['right', '**']
  805. ['right', 'UNARY_MATH']
  806. ['left', 'MATH']
  807. ['left', '+', '-']
  808. ['left', 'SHIFT']
  809. ['left', 'RELATION']
  810. ['left', 'COMPARE']
  811. ['left', '&']
  812. ['left', '^']
  813. ['left', '|']
  814. ['left', '&&']
  815. ['left', '||']
  816. ['left', 'BIN?']
  817. ['nonassoc', 'INDENT', 'OUTDENT']
  818. ['right', 'YIELD']
  819. ['right', '=', ':', 'COMPOUND_ASSIGN', 'RETURN', 'THROW', 'EXTENDS']
  820. ['right', 'FORIN', 'FOROF', 'FORFROM', 'BY', 'WHEN']
  821. ['right', 'IF', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS', 'IMPORT', 'EXPORT', 'DYNAMIC_IMPORT']
  822. ['left', 'POST_IF']
  823. ]
  824. # Wrapping Up
  825. # -----------
  826. # Finally, now that we have our **grammar** and our **operators**, we can create
  827. # our **Jison.Parser**. We do this by processing all of our rules, recording all
  828. # terminals (every symbol which does not appear as the name of a rule above)
  829. # as "tokens".
  830. tokens = []
  831. for name, alternatives of grammar
  832. grammar[name] = for alt in alternatives
  833. for token in alt[0].split ' '
  834. tokens.push token unless grammar[token]
  835. alt[1] = "return #{alt[1]}" if name is 'Root'
  836. alt
  837. # Initialize the **Parser** with our list of terminal **tokens**, our **grammar**
  838. # rules, and the name of the root. Reverse the operators because Jison orders
  839. # precedence from low to high, and we have it high to low
  840. # (as in [Yacc](http://dinosaur.compilertools.net/yacc/index.html)).
  841. exports.parser = new Parser
  842. tokens : tokens.join ' '
  843. bnf : grammar
  844. operators : operators.reverse()
  845. startSymbol : 'Root'