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