2015-09-03 16:37:36 +00:00
|
|
|
// Generated by CoffeeScript 1.10.0
|
2010-07-25 07:15:12 +00:00
|
|
|
(function() {
|
2010-12-14 02:24:32 +00:00
|
|
|
var Parser, alt, alternatives, grammar, name, o, operators, token, tokens, unwrap;
|
2011-09-18 22:16:39 +00:00
|
|
|
|
2010-02-11 04:24:05 +00:00
|
|
|
Parser = require('jison').Parser;
|
2011-09-18 22:16:39 +00:00
|
|
|
|
2010-10-20 00:42:12 +00:00
|
|
|
unwrap = /^function\s*\(\)\s*\{\s*return\s*([\s\S]*);\s*\}/;
|
2011-09-18 22:16:39 +00:00
|
|
|
|
2010-06-12 23:05:13 +00:00
|
|
|
o = function(patternString, action, options) {
|
2012-11-15 20:35:01 +00:00
|
|
|
var addLocationDataFn, match, patternCount;
|
2010-10-20 00:42:12 +00:00
|
|
|
patternString = patternString.replace(/\s{2,}/g, ' ');
|
2012-11-15 20:35:01 +00:00
|
|
|
patternCount = patternString.split(' ').length;
|
2012-04-10 18:57:45 +00:00
|
|
|
if (!action) {
|
|
|
|
return [patternString, '$$ = $1;', options];
|
|
|
|
}
|
2010-10-20 17:29:06 +00:00
|
|
|
action = (match = unwrap.exec(action)) ? match[1] : "(" + action + "())";
|
2010-10-20 00:42:12 +00:00
|
|
|
action = action.replace(/\bnew /g, '$&yy.');
|
2011-01-15 19:19:35 +00:00
|
|
|
action = action.replace(/\b(?:Block\.wrap|extend)\b/g, 'yy.$&');
|
2012-11-15 20:35:01 +00:00
|
|
|
addLocationDataFn = function(first, last) {
|
|
|
|
if (!last) {
|
|
|
|
return "yy.addLocationDataFn(@" + first + ")";
|
|
|
|
} else {
|
|
|
|
return "yy.addLocationDataFn(@" + first + ", @" + last + ")";
|
|
|
|
}
|
|
|
|
};
|
2013-02-25 04:51:05 +00:00
|
|
|
action = action.replace(/LOC\(([0-9]*)\)/g, addLocationDataFn('$1'));
|
|
|
|
action = action.replace(/LOC\(([0-9]*),\s*([0-9]*)\)/g, addLocationDataFn('$1', '$2'));
|
2013-02-06 15:40:48 +00:00
|
|
|
return [patternString, "$$ = " + (addLocationDataFn(1, patternCount)) + "(" + action + ");", options];
|
2010-02-11 04:24:05 +00:00
|
|
|
};
|
2011-09-18 22:16:39 +00:00
|
|
|
|
2010-02-11 04:24:05 +00:00
|
|
|
grammar = {
|
2010-04-27 03:46:35 +00:00
|
|
|
Root: [
|
2010-10-25 12:37:08 +00:00
|
|
|
o('', function() {
|
2011-01-15 19:19:35 +00:00
|
|
|
return new Block;
|
2013-06-13 22:21:47 +00:00
|
|
|
}), o('Body')
|
2010-02-11 04:24:05 +00:00
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
Body: [
|
2010-10-25 12:37:08 +00:00
|
|
|
o('Line', function() {
|
2011-01-15 19:19:35 +00:00
|
|
|
return Block.wrap([$1]);
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('Body TERMINATOR Line', function() {
|
2010-02-11 04:24:05 +00:00
|
|
|
return $1.push($3);
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('Body TERMINATOR')
|
2010-04-05 14:26:23 +00:00
|
|
|
],
|
2015-09-16 05:51:17 +00:00
|
|
|
Line: [o('Expression'), o('Statement'), o('YieldReturn')],
|
2010-04-27 03:46:35 +00:00
|
|
|
Statement: [
|
2011-11-24 14:36:16 +00:00
|
|
|
o('Return'), o('Comment'), o('STATEMENT', function() {
|
Refactor `Literal` into several subtypes
Previously, the parser created `Literal` nodes for many things. This resulted in
information loss. Instead of being able to check the node type, we had to use
regexes to tell the different types of `Literal`s apart. That was a bit like
parsing literals twice: Once in the lexer, and once (or more) in the compiler.
It also caused problems, such as `` `this` `` and `this` being indistinguishable
(fixes #2009).
Instead returning `new Literal` in the grammar, subtypes of it are now returned
instead, such as `NumberLiteral`, `StringLiteral` and `IdentifierLiteral`. `new
Literal` by itself is only used to represent code chunks that fit no category.
(While mentioning `NumberLiteral`, there's also `InfinityLiteral` now, which is
a subtype of `NumberLiteral`.)
`StringWithInterpolations` has been added as a subtype of `Parens`, and
`RegexWithInterpolations` as a subtype of `Call`. This makes it easier for other
programs to make use of CoffeeScript's "AST" (nodes). For example, it is now
possible to distinguish between `"a #{b} c"` and `"a " + b + " c"`. Fixes #4192.
`SuperCall` has been added as a subtype of `Call`.
Note, though, that some information is still lost, especially in the lexer. For
example, there is no way to distinguish a heredoc from a regular string, or a
heregex without interpolations from a regular regex. Binary and octal number
literals are indistinguishable from hexadecimal literals.
After the new subtypes were added, they were taken advantage of, removing most
regexes in nodes.coffee. `SIMPLENUM` (which matches non-hex integers) had to be
kept, though, because such numbers need special handling in JavaScript (for
example in `1..toString()`).
An especially nice hack to get rid of was using `new String()` for the token
value for reserved identifiers (to be able to set a property on them which could
survive through the parser). Now it's a good old regular string.
In range literals, slices, splices and for loop steps when number literals
are involved, CoffeeScript can do some optimizations, such as precomputing the
value of, say, `5 - 3` (outputting `2` instead of `5 - 3` literally). As a side
bonus, this now also works with hexadecimal number literals, such as `0x02`.
Finally, this also improves the output of `coffee --nodes`:
# Before:
$ bin/coffee -ne 'while true
"#{a}"
break'
Block
While
Value
Bool
Block
Value
Parens
Block
Op +
Value """"
Value
Parens
Block
Value "a" "break"
# After:
$ bin/coffee -ne 'while true
"#{a}"
break'
Block
While
Value BooleanLiteral: true
Block
Value
StringWithInterpolations
Block
Op +
Value StringLiteral: ""
Value
Parens
Block
Value IdentifierLiteral: a
StatementLiteral: break
2016-01-31 19:24:31 +00:00
|
|
|
return new StatementLiteral($1);
|
2010-11-14 20:15:13 +00:00
|
|
|
})
|
2010-02-11 04:24:05 +00:00
|
|
|
],
|
2015-09-13 10:30:59 +00:00
|
|
|
Expression: [o('Value'), o('Invocation'), o('Code'), o('Operation'), o('Assign'), o('If'), o('Try'), o('While'), o('For'), o('Switch'), o('Class'), o('Throw'), o('Yield')],
|
|
|
|
Yield: [
|
|
|
|
o('YIELD', function() {
|
|
|
|
return new Op($1, new Value(new Literal('')));
|
|
|
|
}), o('YIELD Expression', function() {
|
|
|
|
return new Op($1, $2);
|
|
|
|
}), o('YIELD FROM Expression', function() {
|
|
|
|
return new Op($1.concat($2), $3);
|
|
|
|
})
|
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
Block: [
|
2010-12-22 01:28:48 +00:00
|
|
|
o('INDENT OUTDENT', function() {
|
2011-01-15 19:19:35 +00:00
|
|
|
return new Block;
|
2010-12-24 16:59:30 +00:00
|
|
|
}), o('INDENT Body OUTDENT', function() {
|
2010-02-11 04:24:05 +00:00
|
|
|
return $2;
|
|
|
|
})
|
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
Identifier: [
|
2010-10-25 12:37:08 +00:00
|
|
|
o('IDENTIFIER', function() {
|
Refactor `Literal` into several subtypes
Previously, the parser created `Literal` nodes for many things. This resulted in
information loss. Instead of being able to check the node type, we had to use
regexes to tell the different types of `Literal`s apart. That was a bit like
parsing literals twice: Once in the lexer, and once (or more) in the compiler.
It also caused problems, such as `` `this` `` and `this` being indistinguishable
(fixes #2009).
Instead returning `new Literal` in the grammar, subtypes of it are now returned
instead, such as `NumberLiteral`, `StringLiteral` and `IdentifierLiteral`. `new
Literal` by itself is only used to represent code chunks that fit no category.
(While mentioning `NumberLiteral`, there's also `InfinityLiteral` now, which is
a subtype of `NumberLiteral`.)
`StringWithInterpolations` has been added as a subtype of `Parens`, and
`RegexWithInterpolations` as a subtype of `Call`. This makes it easier for other
programs to make use of CoffeeScript's "AST" (nodes). For example, it is now
possible to distinguish between `"a #{b} c"` and `"a " + b + " c"`. Fixes #4192.
`SuperCall` has been added as a subtype of `Call`.
Note, though, that some information is still lost, especially in the lexer. For
example, there is no way to distinguish a heredoc from a regular string, or a
heregex without interpolations from a regular regex. Binary and octal number
literals are indistinguishable from hexadecimal literals.
After the new subtypes were added, they were taken advantage of, removing most
regexes in nodes.coffee. `SIMPLENUM` (which matches non-hex integers) had to be
kept, though, because such numbers need special handling in JavaScript (for
example in `1..toString()`).
An especially nice hack to get rid of was using `new String()` for the token
value for reserved identifiers (to be able to set a property on them which could
survive through the parser). Now it's a good old regular string.
In range literals, slices, splices and for loop steps when number literals
are involved, CoffeeScript can do some optimizations, such as precomputing the
value of, say, `5 - 3` (outputting `2` instead of `5 - 3` literally). As a side
bonus, this now also works with hexadecimal number literals, such as `0x02`.
Finally, this also improves the output of `coffee --nodes`:
# Before:
$ bin/coffee -ne 'while true
"#{a}"
break'
Block
While
Value
Bool
Block
Value
Parens
Block
Op +
Value """"
Value
Parens
Block
Value "a" "break"
# After:
$ bin/coffee -ne 'while true
"#{a}"
break'
Block
While
Value BooleanLiteral: true
Block
Value
StringWithInterpolations
Block
Op +
Value StringLiteral: ""
Value
Parens
Block
Value IdentifierLiteral: a
StatementLiteral: break
2016-01-31 19:24:31 +00:00
|
|
|
return new IdentifierLiteral($1);
|
2010-02-11 04:24:05 +00:00
|
|
|
})
|
|
|
|
],
|
2016-03-05 16:41:15 +00:00
|
|
|
Property: [
|
|
|
|
o('PROPERTY', function() {
|
|
|
|
return new PropertyName($1);
|
|
|
|
})
|
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
AlphaNumeric: [
|
2010-10-25 12:37:08 +00:00
|
|
|
o('NUMBER', function() {
|
Refactor `Literal` into several subtypes
Previously, the parser created `Literal` nodes for many things. This resulted in
information loss. Instead of being able to check the node type, we had to use
regexes to tell the different types of `Literal`s apart. That was a bit like
parsing literals twice: Once in the lexer, and once (or more) in the compiler.
It also caused problems, such as `` `this` `` and `this` being indistinguishable
(fixes #2009).
Instead returning `new Literal` in the grammar, subtypes of it are now returned
instead, such as `NumberLiteral`, `StringLiteral` and `IdentifierLiteral`. `new
Literal` by itself is only used to represent code chunks that fit no category.
(While mentioning `NumberLiteral`, there's also `InfinityLiteral` now, which is
a subtype of `NumberLiteral`.)
`StringWithInterpolations` has been added as a subtype of `Parens`, and
`RegexWithInterpolations` as a subtype of `Call`. This makes it easier for other
programs to make use of CoffeeScript's "AST" (nodes). For example, it is now
possible to distinguish between `"a #{b} c"` and `"a " + b + " c"`. Fixes #4192.
`SuperCall` has been added as a subtype of `Call`.
Note, though, that some information is still lost, especially in the lexer. For
example, there is no way to distinguish a heredoc from a regular string, or a
heregex without interpolations from a regular regex. Binary and octal number
literals are indistinguishable from hexadecimal literals.
After the new subtypes were added, they were taken advantage of, removing most
regexes in nodes.coffee. `SIMPLENUM` (which matches non-hex integers) had to be
kept, though, because such numbers need special handling in JavaScript (for
example in `1..toString()`).
An especially nice hack to get rid of was using `new String()` for the token
value for reserved identifiers (to be able to set a property on them which could
survive through the parser). Now it's a good old regular string.
In range literals, slices, splices and for loop steps when number literals
are involved, CoffeeScript can do some optimizations, such as precomputing the
value of, say, `5 - 3` (outputting `2` instead of `5 - 3` literally). As a side
bonus, this now also works with hexadecimal number literals, such as `0x02`.
Finally, this also improves the output of `coffee --nodes`:
# Before:
$ bin/coffee -ne 'while true
"#{a}"
break'
Block
While
Value
Bool
Block
Value
Parens
Block
Op +
Value """"
Value
Parens
Block
Value "a" "break"
# After:
$ bin/coffee -ne 'while true
"#{a}"
break'
Block
While
Value BooleanLiteral: true
Block
Value
StringWithInterpolations
Block
Op +
Value StringLiteral: ""
Value
Parens
Block
Value IdentifierLiteral: a
StatementLiteral: break
2016-01-31 19:24:31 +00:00
|
|
|
return new NumberLiteral($1);
|
Fix #3597: Allow interpolations in object keys
The following is now allowed:
o =
a: 1
b: 2
"#{'c'}": 3
"#{'d'}": 4
e: 5
"#{'f'}": 6
g: 7
It compiles to:
o = (
obj = {
a: 1,
b: 2
},
obj["" + 'c'] = 3,
obj["" + 'd'] = 4,
obj.e = 5,
obj["" + 'f'] = 6,
obj.g = 7,
obj
);
- Closes #3039. Empty interpolations in object keys are now _supposed_ to be
allowed.
- Closes #1131. No need to improve error messages for attempted key
interpolation anymore.
- Implementing this required fixing the following bug: `("" + a): 1` used to
error out on the colon, saying "unexpected colon". But really, it is the
attempted object key that is unexpected. Now the error is on the opening
parenthesis instead.
- However, the above fix broke some error message tests for regexes. The easiest
way to fix this was to make a seemingly unrelated change: The error messages
for unexpected identifiers, numbers, strings and regexes now say for example
'unexpected string' instead of 'unexpected """some #{really long} string"""'.
In other words, the tag _name_ is used instead of the tag _value_.
This was way easier to implement, and is more helpful to the user. Using the
tag value is good for operators, reserved words and the like, but not for
tokens which can contain any text. For example, 'unexpected identifier' is
better than 'unexpected expected' (if a variable called 'expected' was used
erraneously).
- While writing tests for the above point I found a few minor bugs with string
locations which have been fixed.
2015-02-07 19:16:59 +00:00
|
|
|
}), o('String')
|
|
|
|
],
|
|
|
|
String: [
|
|
|
|
o('STRING', function() {
|
Refactor `Literal` into several subtypes
Previously, the parser created `Literal` nodes for many things. This resulted in
information loss. Instead of being able to check the node type, we had to use
regexes to tell the different types of `Literal`s apart. That was a bit like
parsing literals twice: Once in the lexer, and once (or more) in the compiler.
It also caused problems, such as `` `this` `` and `this` being indistinguishable
(fixes #2009).
Instead returning `new Literal` in the grammar, subtypes of it are now returned
instead, such as `NumberLiteral`, `StringLiteral` and `IdentifierLiteral`. `new
Literal` by itself is only used to represent code chunks that fit no category.
(While mentioning `NumberLiteral`, there's also `InfinityLiteral` now, which is
a subtype of `NumberLiteral`.)
`StringWithInterpolations` has been added as a subtype of `Parens`, and
`RegexWithInterpolations` as a subtype of `Call`. This makes it easier for other
programs to make use of CoffeeScript's "AST" (nodes). For example, it is now
possible to distinguish between `"a #{b} c"` and `"a " + b + " c"`. Fixes #4192.
`SuperCall` has been added as a subtype of `Call`.
Note, though, that some information is still lost, especially in the lexer. For
example, there is no way to distinguish a heredoc from a regular string, or a
heregex without interpolations from a regular regex. Binary and octal number
literals are indistinguishable from hexadecimal literals.
After the new subtypes were added, they were taken advantage of, removing most
regexes in nodes.coffee. `SIMPLENUM` (which matches non-hex integers) had to be
kept, though, because such numbers need special handling in JavaScript (for
example in `1..toString()`).
An especially nice hack to get rid of was using `new String()` for the token
value for reserved identifiers (to be able to set a property on them which could
survive through the parser). Now it's a good old regular string.
In range literals, slices, splices and for loop steps when number literals
are involved, CoffeeScript can do some optimizations, such as precomputing the
value of, say, `5 - 3` (outputting `2` instead of `5 - 3` literally). As a side
bonus, this now also works with hexadecimal number literals, such as `0x02`.
Finally, this also improves the output of `coffee --nodes`:
# Before:
$ bin/coffee -ne 'while true
"#{a}"
break'
Block
While
Value
Bool
Block
Value
Parens
Block
Op +
Value """"
Value
Parens
Block
Value "a" "break"
# After:
$ bin/coffee -ne 'while true
"#{a}"
break'
Block
While
Value BooleanLiteral: true
Block
Value
StringWithInterpolations
Block
Op +
Value StringLiteral: ""
Value
Parens
Block
Value IdentifierLiteral: a
StatementLiteral: break
2016-01-31 19:24:31 +00:00
|
|
|
return new StringLiteral($1);
|
Fix #3597: Allow interpolations in object keys
The following is now allowed:
o =
a: 1
b: 2
"#{'c'}": 3
"#{'d'}": 4
e: 5
"#{'f'}": 6
g: 7
It compiles to:
o = (
obj = {
a: 1,
b: 2
},
obj["" + 'c'] = 3,
obj["" + 'd'] = 4,
obj.e = 5,
obj["" + 'f'] = 6,
obj.g = 7,
obj
);
- Closes #3039. Empty interpolations in object keys are now _supposed_ to be
allowed.
- Closes #1131. No need to improve error messages for attempted key
interpolation anymore.
- Implementing this required fixing the following bug: `("" + a): 1` used to
error out on the colon, saying "unexpected colon". But really, it is the
attempted object key that is unexpected. Now the error is on the opening
parenthesis instead.
- However, the above fix broke some error message tests for regexes. The easiest
way to fix this was to make a seemingly unrelated change: The error messages
for unexpected identifiers, numbers, strings and regexes now say for example
'unexpected string' instead of 'unexpected """some #{really long} string"""'.
In other words, the tag _name_ is used instead of the tag _value_.
This was way easier to implement, and is more helpful to the user. Using the
tag value is good for operators, reserved words and the like, but not for
tokens which can contain any text. For example, 'unexpected identifier' is
better than 'unexpected expected' (if a variable called 'expected' was used
erraneously).
- While writing tests for the above point I found a few minor bugs with string
locations which have been fixed.
2015-02-07 19:16:59 +00:00
|
|
|
}), o('STRING_START Body STRING_END', function() {
|
Refactor `Literal` into several subtypes
Previously, the parser created `Literal` nodes for many things. This resulted in
information loss. Instead of being able to check the node type, we had to use
regexes to tell the different types of `Literal`s apart. That was a bit like
parsing literals twice: Once in the lexer, and once (or more) in the compiler.
It also caused problems, such as `` `this` `` and `this` being indistinguishable
(fixes #2009).
Instead returning `new Literal` in the grammar, subtypes of it are now returned
instead, such as `NumberLiteral`, `StringLiteral` and `IdentifierLiteral`. `new
Literal` by itself is only used to represent code chunks that fit no category.
(While mentioning `NumberLiteral`, there's also `InfinityLiteral` now, which is
a subtype of `NumberLiteral`.)
`StringWithInterpolations` has been added as a subtype of `Parens`, and
`RegexWithInterpolations` as a subtype of `Call`. This makes it easier for other
programs to make use of CoffeeScript's "AST" (nodes). For example, it is now
possible to distinguish between `"a #{b} c"` and `"a " + b + " c"`. Fixes #4192.
`SuperCall` has been added as a subtype of `Call`.
Note, though, that some information is still lost, especially in the lexer. For
example, there is no way to distinguish a heredoc from a regular string, or a
heregex without interpolations from a regular regex. Binary and octal number
literals are indistinguishable from hexadecimal literals.
After the new subtypes were added, they were taken advantage of, removing most
regexes in nodes.coffee. `SIMPLENUM` (which matches non-hex integers) had to be
kept, though, because such numbers need special handling in JavaScript (for
example in `1..toString()`).
An especially nice hack to get rid of was using `new String()` for the token
value for reserved identifiers (to be able to set a property on them which could
survive through the parser). Now it's a good old regular string.
In range literals, slices, splices and for loop steps when number literals
are involved, CoffeeScript can do some optimizations, such as precomputing the
value of, say, `5 - 3` (outputting `2` instead of `5 - 3` literally). As a side
bonus, this now also works with hexadecimal number literals, such as `0x02`.
Finally, this also improves the output of `coffee --nodes`:
# Before:
$ bin/coffee -ne 'while true
"#{a}"
break'
Block
While
Value
Bool
Block
Value
Parens
Block
Op +
Value """"
Value
Parens
Block
Value "a" "break"
# After:
$ bin/coffee -ne 'while true
"#{a}"
break'
Block
While
Value BooleanLiteral: true
Block
Value
StringWithInterpolations
Block
Op +
Value StringLiteral: ""
Value
Parens
Block
Value IdentifierLiteral: a
StatementLiteral: break
2016-01-31 19:24:31 +00:00
|
|
|
return new StringWithInterpolations($2);
|
Fix #3597: Allow interpolations in object keys
The following is now allowed:
o =
a: 1
b: 2
"#{'c'}": 3
"#{'d'}": 4
e: 5
"#{'f'}": 6
g: 7
It compiles to:
o = (
obj = {
a: 1,
b: 2
},
obj["" + 'c'] = 3,
obj["" + 'd'] = 4,
obj.e = 5,
obj["" + 'f'] = 6,
obj.g = 7,
obj
);
- Closes #3039. Empty interpolations in object keys are now _supposed_ to be
allowed.
- Closes #1131. No need to improve error messages for attempted key
interpolation anymore.
- Implementing this required fixing the following bug: `("" + a): 1` used to
error out on the colon, saying "unexpected colon". But really, it is the
attempted object key that is unexpected. Now the error is on the opening
parenthesis instead.
- However, the above fix broke some error message tests for regexes. The easiest
way to fix this was to make a seemingly unrelated change: The error messages
for unexpected identifiers, numbers, strings and regexes now say for example
'unexpected string' instead of 'unexpected """some #{really long} string"""'.
In other words, the tag _name_ is used instead of the tag _value_.
This was way easier to implement, and is more helpful to the user. Using the
tag value is good for operators, reserved words and the like, but not for
tokens which can contain any text. For example, 'unexpected identifier' is
better than 'unexpected expected' (if a variable called 'expected' was used
erraneously).
- While writing tests for the above point I found a few minor bugs with string
locations which have been fixed.
2015-02-07 19:16:59 +00:00
|
|
|
})
|
|
|
|
],
|
|
|
|
Regex: [
|
|
|
|
o('REGEX', function() {
|
Refactor `Literal` into several subtypes
Previously, the parser created `Literal` nodes for many things. This resulted in
information loss. Instead of being able to check the node type, we had to use
regexes to tell the different types of `Literal`s apart. That was a bit like
parsing literals twice: Once in the lexer, and once (or more) in the compiler.
It also caused problems, such as `` `this` `` and `this` being indistinguishable
(fixes #2009).
Instead returning `new Literal` in the grammar, subtypes of it are now returned
instead, such as `NumberLiteral`, `StringLiteral` and `IdentifierLiteral`. `new
Literal` by itself is only used to represent code chunks that fit no category.
(While mentioning `NumberLiteral`, there's also `InfinityLiteral` now, which is
a subtype of `NumberLiteral`.)
`StringWithInterpolations` has been added as a subtype of `Parens`, and
`RegexWithInterpolations` as a subtype of `Call`. This makes it easier for other
programs to make use of CoffeeScript's "AST" (nodes). For example, it is now
possible to distinguish between `"a #{b} c"` and `"a " + b + " c"`. Fixes #4192.
`SuperCall` has been added as a subtype of `Call`.
Note, though, that some information is still lost, especially in the lexer. For
example, there is no way to distinguish a heredoc from a regular string, or a
heregex without interpolations from a regular regex. Binary and octal number
literals are indistinguishable from hexadecimal literals.
After the new subtypes were added, they were taken advantage of, removing most
regexes in nodes.coffee. `SIMPLENUM` (which matches non-hex integers) had to be
kept, though, because such numbers need special handling in JavaScript (for
example in `1..toString()`).
An especially nice hack to get rid of was using `new String()` for the token
value for reserved identifiers (to be able to set a property on them which could
survive through the parser). Now it's a good old regular string.
In range literals, slices, splices and for loop steps when number literals
are involved, CoffeeScript can do some optimizations, such as precomputing the
value of, say, `5 - 3` (outputting `2` instead of `5 - 3` literally). As a side
bonus, this now also works with hexadecimal number literals, such as `0x02`.
Finally, this also improves the output of `coffee --nodes`:
# Before:
$ bin/coffee -ne 'while true
"#{a}"
break'
Block
While
Value
Bool
Block
Value
Parens
Block
Op +
Value """"
Value
Parens
Block
Value "a" "break"
# After:
$ bin/coffee -ne 'while true
"#{a}"
break'
Block
While
Value BooleanLiteral: true
Block
Value
StringWithInterpolations
Block
Op +
Value StringLiteral: ""
Value
Parens
Block
Value IdentifierLiteral: a
StatementLiteral: break
2016-01-31 19:24:31 +00:00
|
|
|
return new RegexLiteral($1);
|
Fix #3597: Allow interpolations in object keys
The following is now allowed:
o =
a: 1
b: 2
"#{'c'}": 3
"#{'d'}": 4
e: 5
"#{'f'}": 6
g: 7
It compiles to:
o = (
obj = {
a: 1,
b: 2
},
obj["" + 'c'] = 3,
obj["" + 'd'] = 4,
obj.e = 5,
obj["" + 'f'] = 6,
obj.g = 7,
obj
);
- Closes #3039. Empty interpolations in object keys are now _supposed_ to be
allowed.
- Closes #1131. No need to improve error messages for attempted key
interpolation anymore.
- Implementing this required fixing the following bug: `("" + a): 1` used to
error out on the colon, saying "unexpected colon". But really, it is the
attempted object key that is unexpected. Now the error is on the opening
parenthesis instead.
- However, the above fix broke some error message tests for regexes. The easiest
way to fix this was to make a seemingly unrelated change: The error messages
for unexpected identifiers, numbers, strings and regexes now say for example
'unexpected string' instead of 'unexpected """some #{really long} string"""'.
In other words, the tag _name_ is used instead of the tag _value_.
This was way easier to implement, and is more helpful to the user. Using the
tag value is good for operators, reserved words and the like, but not for
tokens which can contain any text. For example, 'unexpected identifier' is
better than 'unexpected expected' (if a variable called 'expected' was used
erraneously).
- While writing tests for the above point I found a few minor bugs with string
locations which have been fixed.
2015-02-07 19:16:59 +00:00
|
|
|
}), o('REGEX_START Invocation REGEX_END', function() {
|
Refactor `Literal` into several subtypes
Previously, the parser created `Literal` nodes for many things. This resulted in
information loss. Instead of being able to check the node type, we had to use
regexes to tell the different types of `Literal`s apart. That was a bit like
parsing literals twice: Once in the lexer, and once (or more) in the compiler.
It also caused problems, such as `` `this` `` and `this` being indistinguishable
(fixes #2009).
Instead returning `new Literal` in the grammar, subtypes of it are now returned
instead, such as `NumberLiteral`, `StringLiteral` and `IdentifierLiteral`. `new
Literal` by itself is only used to represent code chunks that fit no category.
(While mentioning `NumberLiteral`, there's also `InfinityLiteral` now, which is
a subtype of `NumberLiteral`.)
`StringWithInterpolations` has been added as a subtype of `Parens`, and
`RegexWithInterpolations` as a subtype of `Call`. This makes it easier for other
programs to make use of CoffeeScript's "AST" (nodes). For example, it is now
possible to distinguish between `"a #{b} c"` and `"a " + b + " c"`. Fixes #4192.
`SuperCall` has been added as a subtype of `Call`.
Note, though, that some information is still lost, especially in the lexer. For
example, there is no way to distinguish a heredoc from a regular string, or a
heregex without interpolations from a regular regex. Binary and octal number
literals are indistinguishable from hexadecimal literals.
After the new subtypes were added, they were taken advantage of, removing most
regexes in nodes.coffee. `SIMPLENUM` (which matches non-hex integers) had to be
kept, though, because such numbers need special handling in JavaScript (for
example in `1..toString()`).
An especially nice hack to get rid of was using `new String()` for the token
value for reserved identifiers (to be able to set a property on them which could
survive through the parser). Now it's a good old regular string.
In range literals, slices, splices and for loop steps when number literals
are involved, CoffeeScript can do some optimizations, such as precomputing the
value of, say, `5 - 3` (outputting `2` instead of `5 - 3` literally). As a side
bonus, this now also works with hexadecimal number literals, such as `0x02`.
Finally, this also improves the output of `coffee --nodes`:
# Before:
$ bin/coffee -ne 'while true
"#{a}"
break'
Block
While
Value
Bool
Block
Value
Parens
Block
Op +
Value """"
Value
Parens
Block
Value "a" "break"
# After:
$ bin/coffee -ne 'while true
"#{a}"
break'
Block
While
Value BooleanLiteral: true
Block
Value
StringWithInterpolations
Block
Op +
Value StringLiteral: ""
Value
Parens
Block
Value IdentifierLiteral: a
StatementLiteral: break
2016-01-31 19:24:31 +00:00
|
|
|
return new RegexWithInterpolations($2.args);
|
2010-02-11 04:24:05 +00:00
|
|
|
})
|
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
Literal: [
|
2010-10-25 12:37:08 +00:00
|
|
|
o('AlphaNumeric'), o('JS', function() {
|
Refactor `Literal` into several subtypes
Previously, the parser created `Literal` nodes for many things. This resulted in
information loss. Instead of being able to check the node type, we had to use
regexes to tell the different types of `Literal`s apart. That was a bit like
parsing literals twice: Once in the lexer, and once (or more) in the compiler.
It also caused problems, such as `` `this` `` and `this` being indistinguishable
(fixes #2009).
Instead returning `new Literal` in the grammar, subtypes of it are now returned
instead, such as `NumberLiteral`, `StringLiteral` and `IdentifierLiteral`. `new
Literal` by itself is only used to represent code chunks that fit no category.
(While mentioning `NumberLiteral`, there's also `InfinityLiteral` now, which is
a subtype of `NumberLiteral`.)
`StringWithInterpolations` has been added as a subtype of `Parens`, and
`RegexWithInterpolations` as a subtype of `Call`. This makes it easier for other
programs to make use of CoffeeScript's "AST" (nodes). For example, it is now
possible to distinguish between `"a #{b} c"` and `"a " + b + " c"`. Fixes #4192.
`SuperCall` has been added as a subtype of `Call`.
Note, though, that some information is still lost, especially in the lexer. For
example, there is no way to distinguish a heredoc from a regular string, or a
heregex without interpolations from a regular regex. Binary and octal number
literals are indistinguishable from hexadecimal literals.
After the new subtypes were added, they were taken advantage of, removing most
regexes in nodes.coffee. `SIMPLENUM` (which matches non-hex integers) had to be
kept, though, because such numbers need special handling in JavaScript (for
example in `1..toString()`).
An especially nice hack to get rid of was using `new String()` for the token
value for reserved identifiers (to be able to set a property on them which could
survive through the parser). Now it's a good old regular string.
In range literals, slices, splices and for loop steps when number literals
are involved, CoffeeScript can do some optimizations, such as precomputing the
value of, say, `5 - 3` (outputting `2` instead of `5 - 3` literally). As a side
bonus, this now also works with hexadecimal number literals, such as `0x02`.
Finally, this also improves the output of `coffee --nodes`:
# Before:
$ bin/coffee -ne 'while true
"#{a}"
break'
Block
While
Value
Bool
Block
Value
Parens
Block
Op +
Value """"
Value
Parens
Block
Value "a" "break"
# After:
$ bin/coffee -ne 'while true
"#{a}"
break'
Block
While
Value BooleanLiteral: true
Block
Value
StringWithInterpolations
Block
Op +
Value StringLiteral: ""
Value
Parens
Block
Value IdentifierLiteral: a
StatementLiteral: break
2016-01-31 19:24:31 +00:00
|
|
|
return new PassthroughLiteral($1);
|
|
|
|
}), o('Regex'), o('UNDEFINED', function() {
|
|
|
|
return new UndefinedLiteral;
|
2012-05-08 20:11:23 +00:00
|
|
|
}), o('NULL', function() {
|
Refactor `Literal` into several subtypes
Previously, the parser created `Literal` nodes for many things. This resulted in
information loss. Instead of being able to check the node type, we had to use
regexes to tell the different types of `Literal`s apart. That was a bit like
parsing literals twice: Once in the lexer, and once (or more) in the compiler.
It also caused problems, such as `` `this` `` and `this` being indistinguishable
(fixes #2009).
Instead returning `new Literal` in the grammar, subtypes of it are now returned
instead, such as `NumberLiteral`, `StringLiteral` and `IdentifierLiteral`. `new
Literal` by itself is only used to represent code chunks that fit no category.
(While mentioning `NumberLiteral`, there's also `InfinityLiteral` now, which is
a subtype of `NumberLiteral`.)
`StringWithInterpolations` has been added as a subtype of `Parens`, and
`RegexWithInterpolations` as a subtype of `Call`. This makes it easier for other
programs to make use of CoffeeScript's "AST" (nodes). For example, it is now
possible to distinguish between `"a #{b} c"` and `"a " + b + " c"`. Fixes #4192.
`SuperCall` has been added as a subtype of `Call`.
Note, though, that some information is still lost, especially in the lexer. For
example, there is no way to distinguish a heredoc from a regular string, or a
heregex without interpolations from a regular regex. Binary and octal number
literals are indistinguishable from hexadecimal literals.
After the new subtypes were added, they were taken advantage of, removing most
regexes in nodes.coffee. `SIMPLENUM` (which matches non-hex integers) had to be
kept, though, because such numbers need special handling in JavaScript (for
example in `1..toString()`).
An especially nice hack to get rid of was using `new String()` for the token
value for reserved identifiers (to be able to set a property on them which could
survive through the parser). Now it's a good old regular string.
In range literals, slices, splices and for loop steps when number literals
are involved, CoffeeScript can do some optimizations, such as precomputing the
value of, say, `5 - 3` (outputting `2` instead of `5 - 3` literally). As a side
bonus, this now also works with hexadecimal number literals, such as `0x02`.
Finally, this also improves the output of `coffee --nodes`:
# Before:
$ bin/coffee -ne 'while true
"#{a}"
break'
Block
While
Value
Bool
Block
Value
Parens
Block
Op +
Value """"
Value
Parens
Block
Value "a" "break"
# After:
$ bin/coffee -ne 'while true
"#{a}"
break'
Block
While
Value BooleanLiteral: true
Block
Value
StringWithInterpolations
Block
Op +
Value StringLiteral: ""
Value
Parens
Block
Value IdentifierLiteral: a
StatementLiteral: break
2016-01-31 19:24:31 +00:00
|
|
|
return new NullLiteral;
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('BOOL', function() {
|
Refactor `Literal` into several subtypes
Previously, the parser created `Literal` nodes for many things. This resulted in
information loss. Instead of being able to check the node type, we had to use
regexes to tell the different types of `Literal`s apart. That was a bit like
parsing literals twice: Once in the lexer, and once (or more) in the compiler.
It also caused problems, such as `` `this` `` and `this` being indistinguishable
(fixes #2009).
Instead returning `new Literal` in the grammar, subtypes of it are now returned
instead, such as `NumberLiteral`, `StringLiteral` and `IdentifierLiteral`. `new
Literal` by itself is only used to represent code chunks that fit no category.
(While mentioning `NumberLiteral`, there's also `InfinityLiteral` now, which is
a subtype of `NumberLiteral`.)
`StringWithInterpolations` has been added as a subtype of `Parens`, and
`RegexWithInterpolations` as a subtype of `Call`. This makes it easier for other
programs to make use of CoffeeScript's "AST" (nodes). For example, it is now
possible to distinguish between `"a #{b} c"` and `"a " + b + " c"`. Fixes #4192.
`SuperCall` has been added as a subtype of `Call`.
Note, though, that some information is still lost, especially in the lexer. For
example, there is no way to distinguish a heredoc from a regular string, or a
heregex without interpolations from a regular regex. Binary and octal number
literals are indistinguishable from hexadecimal literals.
After the new subtypes were added, they were taken advantage of, removing most
regexes in nodes.coffee. `SIMPLENUM` (which matches non-hex integers) had to be
kept, though, because such numbers need special handling in JavaScript (for
example in `1..toString()`).
An especially nice hack to get rid of was using `new String()` for the token
value for reserved identifiers (to be able to set a property on them which could
survive through the parser). Now it's a good old regular string.
In range literals, slices, splices and for loop steps when number literals
are involved, CoffeeScript can do some optimizations, such as precomputing the
value of, say, `5 - 3` (outputting `2` instead of `5 - 3` literally). As a side
bonus, this now also works with hexadecimal number literals, such as `0x02`.
Finally, this also improves the output of `coffee --nodes`:
# Before:
$ bin/coffee -ne 'while true
"#{a}"
break'
Block
While
Value
Bool
Block
Value
Parens
Block
Op +
Value """"
Value
Parens
Block
Value "a" "break"
# After:
$ bin/coffee -ne 'while true
"#{a}"
break'
Block
While
Value BooleanLiteral: true
Block
Value
StringWithInterpolations
Block
Op +
Value StringLiteral: ""
Value
Parens
Block
Value IdentifierLiteral: a
StatementLiteral: break
2016-01-31 19:24:31 +00:00
|
|
|
return new BooleanLiteral($1);
|
2016-03-05 20:32:20 +00:00
|
|
|
}), o('INFINITY', function() {
|
|
|
|
return new InfinityLiteral($1);
|
|
|
|
}), o('NAN', function() {
|
|
|
|
return new NaNLiteral;
|
2010-02-11 04:24:05 +00:00
|
|
|
})
|
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
Assign: [
|
2010-10-25 12:37:08 +00:00
|
|
|
o('Assignable = Expression', function() {
|
2010-10-07 02:44:32 +00:00
|
|
|
return new Assign($1, $3);
|
2011-12-14 23:31:20 +00:00
|
|
|
}), o('Assignable = TERMINATOR Expression', function() {
|
|
|
|
return new Assign($1, $4);
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('Assignable = INDENT Expression OUTDENT', function() {
|
2010-10-07 02:44:32 +00:00
|
|
|
return new Assign($1, $4);
|
2010-02-11 04:24:05 +00:00
|
|
|
})
|
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
AssignObj: [
|
2010-10-24 05:05:31 +00:00
|
|
|
o('ObjAssignable', function() {
|
2013-02-28 13:37:30 +00:00
|
|
|
return new Value($1);
|
2010-10-24 05:05:31 +00:00
|
|
|
}), o('ObjAssignable : Expression', function() {
|
2015-08-28 21:11:47 +00:00
|
|
|
return new Assign(LOC(1)(new Value($1)), $3, 'object', {
|
|
|
|
operatorToken: LOC(2)(new Literal($2))
|
|
|
|
});
|
2013-11-18 04:32:15 +00:00
|
|
|
}), o('ObjAssignable : INDENT Expression OUTDENT', function() {
|
2015-08-28 21:11:47 +00:00
|
|
|
return new Assign(LOC(1)(new Value($1)), $4, 'object', {
|
|
|
|
operatorToken: LOC(2)(new Literal($2))
|
|
|
|
});
|
2015-08-22 19:39:26 +00:00
|
|
|
}), o('SimpleObjAssignable = Expression', function() {
|
|
|
|
return new Assign(LOC(1)(new Value($1)), $3, null, {
|
|
|
|
operatorToken: LOC(2)(new Literal($2))
|
|
|
|
});
|
|
|
|
}), o('SimpleObjAssignable = INDENT Expression OUTDENT', function() {
|
|
|
|
return new Assign(LOC(1)(new Value($1)), $4, null, {
|
|
|
|
operatorToken: LOC(2)(new Literal($2))
|
|
|
|
});
|
2010-11-13 20:52:30 +00:00
|
|
|
}), o('Comment')
|
2010-02-11 04:24:05 +00:00
|
|
|
],
|
2016-03-05 16:41:15 +00:00
|
|
|
SimpleObjAssignable: [o('Identifier'), o('Property'), o('ThisProperty')],
|
2015-08-22 19:39:26 +00:00
|
|
|
ObjAssignable: [o('SimpleObjAssignable'), o('AlphaNumeric')],
|
2010-04-27 03:46:35 +00:00
|
|
|
Return: [
|
2010-10-25 12:37:08 +00:00
|
|
|
o('RETURN Expression', function() {
|
2010-10-07 02:44:32 +00:00
|
|
|
return new Return($2);
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('RETURN', function() {
|
2010-10-07 02:44:32 +00:00
|
|
|
return new Return;
|
2010-02-11 04:24:05 +00:00
|
|
|
})
|
|
|
|
],
|
2015-09-16 05:51:17 +00:00
|
|
|
YieldReturn: [
|
|
|
|
o('YIELD RETURN Expression', function() {
|
|
|
|
return new YieldReturn($3);
|
|
|
|
}), o('YIELD RETURN', function() {
|
|
|
|
return new YieldReturn;
|
|
|
|
})
|
|
|
|
],
|
2010-07-02 01:26:33 +00:00
|
|
|
Comment: [
|
2010-10-25 12:37:08 +00:00
|
|
|
o('HERECOMMENT', function() {
|
2010-10-07 02:44:32 +00:00
|
|
|
return new Comment($1);
|
2010-07-02 01:26:33 +00:00
|
|
|
})
|
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
Code: [
|
2010-10-25 12:37:08 +00:00
|
|
|
o('PARAM_START ParamList PARAM_END FuncGlyph Block', function() {
|
2010-10-07 02:44:32 +00:00
|
|
|
return new Code($2, $5, $4);
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('FuncGlyph Block', function() {
|
2010-10-07 02:44:32 +00:00
|
|
|
return new Code([], $2, $1);
|
2010-02-11 04:24:05 +00:00
|
|
|
})
|
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
FuncGlyph: [
|
2010-10-25 12:37:08 +00:00
|
|
|
o('->', function() {
|
2010-02-11 04:24:05 +00:00
|
|
|
return 'func';
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('=>', function() {
|
2010-02-11 04:24:05 +00:00
|
|
|
return 'boundfunc';
|
|
|
|
})
|
|
|
|
],
|
2010-04-26 01:17:46 +00:00
|
|
|
OptComma: [o(''), o(',')],
|
2010-04-27 03:46:35 +00:00
|
|
|
ParamList: [
|
2010-10-25 12:37:08 +00:00
|
|
|
o('', function() {
|
2010-02-15 23:03:00 +00:00
|
|
|
return [];
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('Param', function() {
|
2010-02-11 04:24:05 +00:00
|
|
|
return [$1];
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('ParamList , Param', function() {
|
2010-10-11 07:06:29 +00:00
|
|
|
return $1.concat($3);
|
2012-04-24 20:56:39 +00:00
|
|
|
}), o('ParamList OptComma TERMINATOR Param', function() {
|
|
|
|
return $1.concat($4);
|
|
|
|
}), o('ParamList OptComma INDENT ParamList OptComma OUTDENT', function() {
|
|
|
|
return $1.concat($4);
|
2010-02-11 04:24:05 +00:00
|
|
|
})
|
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
Param: [
|
2010-10-26 10:08:01 +00:00
|
|
|
o('ParamVar', function() {
|
2010-10-26 04:09:46 +00:00
|
|
|
return new Param($1);
|
2010-10-26 10:08:01 +00:00
|
|
|
}), o('ParamVar ...', function() {
|
2010-10-26 04:09:46 +00:00
|
|
|
return new Param($1, null, true);
|
2010-11-02 02:01:52 +00:00
|
|
|
}), o('ParamVar = Expression', function() {
|
2010-10-26 04:09:46 +00:00
|
|
|
return new Param($1, $3);
|
2014-01-24 16:00:34 +00:00
|
|
|
}), o('...', function() {
|
|
|
|
return new Expansion;
|
2010-02-11 04:24:05 +00:00
|
|
|
})
|
|
|
|
],
|
2010-10-26 19:46:03 +00:00
|
|
|
ParamVar: [o('Identifier'), o('ThisProperty'), o('Array'), o('Object')],
|
2010-04-27 03:46:35 +00:00
|
|
|
Splat: [
|
2010-10-25 12:37:08 +00:00
|
|
|
o('Expression ...', function() {
|
2010-10-07 02:44:32 +00:00
|
|
|
return new Splat($1);
|
2010-02-11 04:24:05 +00:00
|
|
|
})
|
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
SimpleAssignable: [
|
2010-10-25 12:37:08 +00:00
|
|
|
o('Identifier', function() {
|
2013-02-28 13:37:30 +00:00
|
|
|
return new Value($1);
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('Value Accessor', function() {
|
2011-08-12 17:38:34 +00:00
|
|
|
return $1.add($2);
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('Invocation Accessor', function() {
|
2013-02-28 13:37:30 +00:00
|
|
|
return new Value($1, [].concat($2));
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('ThisProperty')
|
2010-03-28 17:06:16 +00:00
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
Assignable: [
|
2010-10-24 05:05:31 +00:00
|
|
|
o('SimpleAssignable'), o('Array', function() {
|
2013-02-28 13:37:30 +00:00
|
|
|
return new Value($1);
|
2010-10-24 05:05:31 +00:00
|
|
|
}), o('Object', function() {
|
2013-02-28 13:37:30 +00:00
|
|
|
return new Value($1);
|
2010-03-28 17:14:35 +00:00
|
|
|
})
|
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
Value: [
|
2010-10-25 12:37:08 +00:00
|
|
|
o('Assignable'), o('Literal', function() {
|
2013-02-28 13:37:30 +00:00
|
|
|
return new Value($1);
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('Parenthetical', function() {
|
2013-02-28 13:37:30 +00:00
|
|
|
return new Value($1);
|
2010-11-20 21:25:22 +00:00
|
|
|
}), o('Range', function() {
|
2013-02-28 13:37:30 +00:00
|
|
|
return new Value($1);
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('This')
|
2010-02-11 04:24:05 +00:00
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
Accessor: [
|
2016-03-05 16:41:15 +00:00
|
|
|
o('. Property', function() {
|
2010-11-21 01:09:36 +00:00
|
|
|
return new Access($2);
|
2016-03-05 16:41:15 +00:00
|
|
|
}), o('?. Property', function() {
|
2010-11-21 01:09:36 +00:00
|
|
|
return new Access($2, 'soak');
|
2016-03-05 16:41:15 +00:00
|
|
|
}), o(':: Property', function() {
|
|
|
|
return [LOC(1)(new Access(new PropertyName('prototype'))), LOC(2)(new Access($2))];
|
|
|
|
}), o('?:: Property', function() {
|
|
|
|
return [LOC(1)(new Access(new PropertyName('prototype'), 'soak')), LOC(2)(new Access($2))];
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('::', function() {
|
2016-03-05 16:41:15 +00:00
|
|
|
return new Access(new PropertyName('prototype'));
|
2011-01-22 06:56:14 +00:00
|
|
|
}), o('Index')
|
2010-02-11 04:24:05 +00:00
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
Index: [
|
2011-01-22 06:56:14 +00:00
|
|
|
o('INDEX_START IndexValue INDEX_END', function() {
|
|
|
|
return $2;
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('INDEX_SOAK Index', function() {
|
2010-10-13 04:53:56 +00:00
|
|
|
return extend($2, {
|
2010-10-25 13:31:52 +00:00
|
|
|
soak: true
|
2010-10-13 04:53:56 +00:00
|
|
|
});
|
2010-02-11 04:24:05 +00:00
|
|
|
})
|
|
|
|
],
|
2011-01-22 06:56:14 +00:00
|
|
|
IndexValue: [
|
|
|
|
o('Expression', function() {
|
|
|
|
return new Index($1);
|
|
|
|
}), o('Slice', function() {
|
|
|
|
return new Slice($1);
|
|
|
|
})
|
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
Object: [
|
2010-10-25 12:37:08 +00:00
|
|
|
o('{ AssignList OptComma }', function() {
|
2010-11-13 17:17:09 +00:00
|
|
|
return new Obj($2, $1.generated);
|
2010-02-27 23:57:45 +00:00
|
|
|
})
|
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
AssignList: [
|
2010-10-25 12:37:08 +00:00
|
|
|
o('', function() {
|
2010-02-11 04:24:05 +00:00
|
|
|
return [];
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('AssignObj', function() {
|
2010-02-11 04:24:05 +00:00
|
|
|
return [$1];
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('AssignList , AssignObj', function() {
|
2010-10-11 07:06:29 +00:00
|
|
|
return $1.concat($3);
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('AssignList OptComma TERMINATOR AssignObj', function() {
|
2010-10-11 07:06:29 +00:00
|
|
|
return $1.concat($4);
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('AssignList OptComma INDENT AssignList OptComma OUTDENT', function() {
|
2010-05-12 22:28:40 +00:00
|
|
|
return $1.concat($4);
|
2010-02-11 04:24:05 +00:00
|
|
|
})
|
2010-04-03 16:18:29 +00:00
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
Class: [
|
2010-11-12 02:48:08 +00:00
|
|
|
o('CLASS', function() {
|
|
|
|
return new Class;
|
|
|
|
}), o('CLASS Block', function() {
|
|
|
|
return new Class(null, null, $2);
|
2011-08-07 09:02:01 +00:00
|
|
|
}), o('CLASS EXTENDS Expression', function() {
|
2010-11-12 02:48:08 +00:00
|
|
|
return new Class(null, $3);
|
2011-08-07 09:02:01 +00:00
|
|
|
}), o('CLASS EXTENDS Expression Block', function() {
|
2010-11-12 02:48:08 +00:00
|
|
|
return new Class(null, $3, $4);
|
|
|
|
}), o('CLASS SimpleAssignable', function() {
|
2010-10-07 02:44:32 +00:00
|
|
|
return new Class($2);
|
2010-11-12 02:48:08 +00:00
|
|
|
}), o('CLASS SimpleAssignable Block', function() {
|
|
|
|
return new Class($2, null, $3);
|
2011-08-07 09:02:01 +00:00
|
|
|
}), o('CLASS SimpleAssignable EXTENDS Expression', function() {
|
2010-10-07 02:44:32 +00:00
|
|
|
return new Class($2, $4);
|
2011-08-07 09:02:01 +00:00
|
|
|
}), o('CLASS SimpleAssignable EXTENDS Expression Block', function() {
|
2010-11-12 02:48:08 +00:00
|
|
|
return new Class($2, $4, $5);
|
2010-04-03 16:18:29 +00:00
|
|
|
})
|
2010-02-11 04:24:05 +00:00
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
Invocation: [
|
2010-10-25 12:37:08 +00:00
|
|
|
o('Value OptFuncExist Arguments', function() {
|
2010-10-07 02:44:32 +00:00
|
|
|
return new Call($1, $3, $2);
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('Invocation OptFuncExist Arguments', function() {
|
2010-10-07 02:44:32 +00:00
|
|
|
return new Call($1, $3, $2);
|
Refactor `Literal` into several subtypes
Previously, the parser created `Literal` nodes for many things. This resulted in
information loss. Instead of being able to check the node type, we had to use
regexes to tell the different types of `Literal`s apart. That was a bit like
parsing literals twice: Once in the lexer, and once (or more) in the compiler.
It also caused problems, such as `` `this` `` and `this` being indistinguishable
(fixes #2009).
Instead returning `new Literal` in the grammar, subtypes of it are now returned
instead, such as `NumberLiteral`, `StringLiteral` and `IdentifierLiteral`. `new
Literal` by itself is only used to represent code chunks that fit no category.
(While mentioning `NumberLiteral`, there's also `InfinityLiteral` now, which is
a subtype of `NumberLiteral`.)
`StringWithInterpolations` has been added as a subtype of `Parens`, and
`RegexWithInterpolations` as a subtype of `Call`. This makes it easier for other
programs to make use of CoffeeScript's "AST" (nodes). For example, it is now
possible to distinguish between `"a #{b} c"` and `"a " + b + " c"`. Fixes #4192.
`SuperCall` has been added as a subtype of `Call`.
Note, though, that some information is still lost, especially in the lexer. For
example, there is no way to distinguish a heredoc from a regular string, or a
heregex without interpolations from a regular regex. Binary and octal number
literals are indistinguishable from hexadecimal literals.
After the new subtypes were added, they were taken advantage of, removing most
regexes in nodes.coffee. `SIMPLENUM` (which matches non-hex integers) had to be
kept, though, because such numbers need special handling in JavaScript (for
example in `1..toString()`).
An especially nice hack to get rid of was using `new String()` for the token
value for reserved identifiers (to be able to set a property on them which could
survive through the parser). Now it's a good old regular string.
In range literals, slices, splices and for loop steps when number literals
are involved, CoffeeScript can do some optimizations, such as precomputing the
value of, say, `5 - 3` (outputting `2` instead of `5 - 3` literally). As a side
bonus, this now also works with hexadecimal number literals, such as `0x02`.
Finally, this also improves the output of `coffee --nodes`:
# Before:
$ bin/coffee -ne 'while true
"#{a}"
break'
Block
While
Value
Bool
Block
Value
Parens
Block
Op +
Value """"
Value
Parens
Block
Value "a" "break"
# After:
$ bin/coffee -ne 'while true
"#{a}"
break'
Block
While
Value BooleanLiteral: true
Block
Value
StringWithInterpolations
Block
Op +
Value StringLiteral: ""
Value
Parens
Block
Value IdentifierLiteral: a
StatementLiteral: break
2016-01-31 19:24:31 +00:00
|
|
|
}), o('Super')
|
|
|
|
],
|
|
|
|
Super: [
|
|
|
|
o('SUPER', function() {
|
|
|
|
return new SuperCall;
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('SUPER Arguments', function() {
|
Refactor `Literal` into several subtypes
Previously, the parser created `Literal` nodes for many things. This resulted in
information loss. Instead of being able to check the node type, we had to use
regexes to tell the different types of `Literal`s apart. That was a bit like
parsing literals twice: Once in the lexer, and once (or more) in the compiler.
It also caused problems, such as `` `this` `` and `this` being indistinguishable
(fixes #2009).
Instead returning `new Literal` in the grammar, subtypes of it are now returned
instead, such as `NumberLiteral`, `StringLiteral` and `IdentifierLiteral`. `new
Literal` by itself is only used to represent code chunks that fit no category.
(While mentioning `NumberLiteral`, there's also `InfinityLiteral` now, which is
a subtype of `NumberLiteral`.)
`StringWithInterpolations` has been added as a subtype of `Parens`, and
`RegexWithInterpolations` as a subtype of `Call`. This makes it easier for other
programs to make use of CoffeeScript's "AST" (nodes). For example, it is now
possible to distinguish between `"a #{b} c"` and `"a " + b + " c"`. Fixes #4192.
`SuperCall` has been added as a subtype of `Call`.
Note, though, that some information is still lost, especially in the lexer. For
example, there is no way to distinguish a heredoc from a regular string, or a
heregex without interpolations from a regular regex. Binary and octal number
literals are indistinguishable from hexadecimal literals.
After the new subtypes were added, they were taken advantage of, removing most
regexes in nodes.coffee. `SIMPLENUM` (which matches non-hex integers) had to be
kept, though, because such numbers need special handling in JavaScript (for
example in `1..toString()`).
An especially nice hack to get rid of was using `new String()` for the token
value for reserved identifiers (to be able to set a property on them which could
survive through the parser). Now it's a good old regular string.
In range literals, slices, splices and for loop steps when number literals
are involved, CoffeeScript can do some optimizations, such as precomputing the
value of, say, `5 - 3` (outputting `2` instead of `5 - 3` literally). As a side
bonus, this now also works with hexadecimal number literals, such as `0x02`.
Finally, this also improves the output of `coffee --nodes`:
# Before:
$ bin/coffee -ne 'while true
"#{a}"
break'
Block
While
Value
Bool
Block
Value
Parens
Block
Op +
Value """"
Value
Parens
Block
Value "a" "break"
# After:
$ bin/coffee -ne 'while true
"#{a}"
break'
Block
While
Value BooleanLiteral: true
Block
Value
StringWithInterpolations
Block
Op +
Value StringLiteral: ""
Value
Parens
Block
Value IdentifierLiteral: a
StatementLiteral: break
2016-01-31 19:24:31 +00:00
|
|
|
return new SuperCall($2);
|
2010-08-25 19:39:30 +00:00
|
|
|
})
|
|
|
|
],
|
|
|
|
OptFuncExist: [
|
2010-10-25 12:37:08 +00:00
|
|
|
o('', function() {
|
2010-08-25 19:39:30 +00:00
|
|
|
return false;
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('FUNC_EXIST', function() {
|
2010-08-25 19:39:30 +00:00
|
|
|
return true;
|
2010-02-11 04:24:05 +00:00
|
|
|
})
|
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
Arguments: [
|
2010-10-25 12:37:08 +00:00
|
|
|
o('CALL_START CALL_END', function() {
|
2010-09-09 01:39:51 +00:00
|
|
|
return [];
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('CALL_START ArgList OptComma CALL_END', function() {
|
2010-03-26 15:44:25 +00:00
|
|
|
return $2;
|
2010-02-11 04:24:05 +00:00
|
|
|
})
|
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
This: [
|
2010-10-25 12:37:08 +00:00
|
|
|
o('THIS', function() {
|
Refactor `Literal` into several subtypes
Previously, the parser created `Literal` nodes for many things. This resulted in
information loss. Instead of being able to check the node type, we had to use
regexes to tell the different types of `Literal`s apart. That was a bit like
parsing literals twice: Once in the lexer, and once (or more) in the compiler.
It also caused problems, such as `` `this` `` and `this` being indistinguishable
(fixes #2009).
Instead returning `new Literal` in the grammar, subtypes of it are now returned
instead, such as `NumberLiteral`, `StringLiteral` and `IdentifierLiteral`. `new
Literal` by itself is only used to represent code chunks that fit no category.
(While mentioning `NumberLiteral`, there's also `InfinityLiteral` now, which is
a subtype of `NumberLiteral`.)
`StringWithInterpolations` has been added as a subtype of `Parens`, and
`RegexWithInterpolations` as a subtype of `Call`. This makes it easier for other
programs to make use of CoffeeScript's "AST" (nodes). For example, it is now
possible to distinguish between `"a #{b} c"` and `"a " + b + " c"`. Fixes #4192.
`SuperCall` has been added as a subtype of `Call`.
Note, though, that some information is still lost, especially in the lexer. For
example, there is no way to distinguish a heredoc from a regular string, or a
heregex without interpolations from a regular regex. Binary and octal number
literals are indistinguishable from hexadecimal literals.
After the new subtypes were added, they were taken advantage of, removing most
regexes in nodes.coffee. `SIMPLENUM` (which matches non-hex integers) had to be
kept, though, because such numbers need special handling in JavaScript (for
example in `1..toString()`).
An especially nice hack to get rid of was using `new String()` for the token
value for reserved identifiers (to be able to set a property on them which could
survive through the parser). Now it's a good old regular string.
In range literals, slices, splices and for loop steps when number literals
are involved, CoffeeScript can do some optimizations, such as precomputing the
value of, say, `5 - 3` (outputting `2` instead of `5 - 3` literally). As a side
bonus, this now also works with hexadecimal number literals, such as `0x02`.
Finally, this also improves the output of `coffee --nodes`:
# Before:
$ bin/coffee -ne 'while true
"#{a}"
break'
Block
While
Value
Bool
Block
Value
Parens
Block
Op +
Value """"
Value
Parens
Block
Value "a" "break"
# After:
$ bin/coffee -ne 'while true
"#{a}"
break'
Block
While
Value BooleanLiteral: true
Block
Value
StringWithInterpolations
Block
Op +
Value StringLiteral: ""
Value
Parens
Block
Value IdentifierLiteral: a
StatementLiteral: break
2016-01-31 19:24:31 +00:00
|
|
|
return new Value(new ThisLiteral);
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('@', function() {
|
Refactor `Literal` into several subtypes
Previously, the parser created `Literal` nodes for many things. This resulted in
information loss. Instead of being able to check the node type, we had to use
regexes to tell the different types of `Literal`s apart. That was a bit like
parsing literals twice: Once in the lexer, and once (or more) in the compiler.
It also caused problems, such as `` `this` `` and `this` being indistinguishable
(fixes #2009).
Instead returning `new Literal` in the grammar, subtypes of it are now returned
instead, such as `NumberLiteral`, `StringLiteral` and `IdentifierLiteral`. `new
Literal` by itself is only used to represent code chunks that fit no category.
(While mentioning `NumberLiteral`, there's also `InfinityLiteral` now, which is
a subtype of `NumberLiteral`.)
`StringWithInterpolations` has been added as a subtype of `Parens`, and
`RegexWithInterpolations` as a subtype of `Call`. This makes it easier for other
programs to make use of CoffeeScript's "AST" (nodes). For example, it is now
possible to distinguish between `"a #{b} c"` and `"a " + b + " c"`. Fixes #4192.
`SuperCall` has been added as a subtype of `Call`.
Note, though, that some information is still lost, especially in the lexer. For
example, there is no way to distinguish a heredoc from a regular string, or a
heregex without interpolations from a regular regex. Binary and octal number
literals are indistinguishable from hexadecimal literals.
After the new subtypes were added, they were taken advantage of, removing most
regexes in nodes.coffee. `SIMPLENUM` (which matches non-hex integers) had to be
kept, though, because such numbers need special handling in JavaScript (for
example in `1..toString()`).
An especially nice hack to get rid of was using `new String()` for the token
value for reserved identifiers (to be able to set a property on them which could
survive through the parser). Now it's a good old regular string.
In range literals, slices, splices and for loop steps when number literals
are involved, CoffeeScript can do some optimizations, such as precomputing the
value of, say, `5 - 3` (outputting `2` instead of `5 - 3` literally). As a side
bonus, this now also works with hexadecimal number literals, such as `0x02`.
Finally, this also improves the output of `coffee --nodes`:
# Before:
$ bin/coffee -ne 'while true
"#{a}"
break'
Block
While
Value
Bool
Block
Value
Parens
Block
Op +
Value """"
Value
Parens
Block
Value "a" "break"
# After:
$ bin/coffee -ne 'while true
"#{a}"
break'
Block
While
Value BooleanLiteral: true
Block
Value
StringWithInterpolations
Block
Op +
Value StringLiteral: ""
Value
Parens
Block
Value IdentifierLiteral: a
StatementLiteral: break
2016-01-31 19:24:31 +00:00
|
|
|
return new Value(new ThisLiteral);
|
2010-03-28 17:06:16 +00:00
|
|
|
})
|
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
ThisProperty: [
|
2016-03-05 16:41:15 +00:00
|
|
|
o('@ Property', function() {
|
Refactor `Literal` into several subtypes
Previously, the parser created `Literal` nodes for many things. This resulted in
information loss. Instead of being able to check the node type, we had to use
regexes to tell the different types of `Literal`s apart. That was a bit like
parsing literals twice: Once in the lexer, and once (or more) in the compiler.
It also caused problems, such as `` `this` `` and `this` being indistinguishable
(fixes #2009).
Instead returning `new Literal` in the grammar, subtypes of it are now returned
instead, such as `NumberLiteral`, `StringLiteral` and `IdentifierLiteral`. `new
Literal` by itself is only used to represent code chunks that fit no category.
(While mentioning `NumberLiteral`, there's also `InfinityLiteral` now, which is
a subtype of `NumberLiteral`.)
`StringWithInterpolations` has been added as a subtype of `Parens`, and
`RegexWithInterpolations` as a subtype of `Call`. This makes it easier for other
programs to make use of CoffeeScript's "AST" (nodes). For example, it is now
possible to distinguish between `"a #{b} c"` and `"a " + b + " c"`. Fixes #4192.
`SuperCall` has been added as a subtype of `Call`.
Note, though, that some information is still lost, especially in the lexer. For
example, there is no way to distinguish a heredoc from a regular string, or a
heregex without interpolations from a regular regex. Binary and octal number
literals are indistinguishable from hexadecimal literals.
After the new subtypes were added, they were taken advantage of, removing most
regexes in nodes.coffee. `SIMPLENUM` (which matches non-hex integers) had to be
kept, though, because such numbers need special handling in JavaScript (for
example in `1..toString()`).
An especially nice hack to get rid of was using `new String()` for the token
value for reserved identifiers (to be able to set a property on them which could
survive through the parser). Now it's a good old regular string.
In range literals, slices, splices and for loop steps when number literals
are involved, CoffeeScript can do some optimizations, such as precomputing the
value of, say, `5 - 3` (outputting `2` instead of `5 - 3` literally). As a side
bonus, this now also works with hexadecimal number literals, such as `0x02`.
Finally, this also improves the output of `coffee --nodes`:
# Before:
$ bin/coffee -ne 'while true
"#{a}"
break'
Block
While
Value
Bool
Block
Value
Parens
Block
Op +
Value """"
Value
Parens
Block
Value "a" "break"
# After:
$ bin/coffee -ne 'while true
"#{a}"
break'
Block
While
Value BooleanLiteral: true
Block
Value
StringWithInterpolations
Block
Op +
Value StringLiteral: ""
Value
Parens
Block
Value IdentifierLiteral: a
StatementLiteral: break
2016-01-31 19:24:31 +00:00
|
|
|
return new Value(LOC(1)(new ThisLiteral), [LOC(2)(new Access($2))], 'this');
|
2010-02-11 04:24:05 +00:00
|
|
|
})
|
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
Array: [
|
2010-10-25 12:37:08 +00:00
|
|
|
o('[ ]', function() {
|
2010-10-24 15:35:47 +00:00
|
|
|
return new Arr([]);
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('[ ArgList OptComma ]', function() {
|
2010-10-24 15:35:47 +00:00
|
|
|
return new Arr($2);
|
2010-02-11 04:24:05 +00:00
|
|
|
})
|
|
|
|
],
|
2010-11-20 21:25:22 +00:00
|
|
|
RangeDots: [
|
|
|
|
o('..', function() {
|
|
|
|
return 'inclusive';
|
|
|
|
}), o('...', function() {
|
|
|
|
return 'exclusive';
|
|
|
|
})
|
|
|
|
],
|
|
|
|
Range: [
|
|
|
|
o('[ Expression RangeDots Expression ]', function() {
|
|
|
|
return new Range($2, $4, $3);
|
|
|
|
})
|
|
|
|
],
|
|
|
|
Slice: [
|
2011-01-22 06:56:14 +00:00
|
|
|
o('Expression RangeDots Expression', function() {
|
|
|
|
return new Range($1, $3, $2);
|
|
|
|
}), o('Expression RangeDots', function() {
|
|
|
|
return new Range($1, null, $2);
|
|
|
|
}), o('RangeDots Expression', function() {
|
|
|
|
return new Range(null, $2, $1);
|
2011-12-21 00:21:26 +00:00
|
|
|
}), o('RangeDots', function() {
|
|
|
|
return new Range(null, null, $1);
|
2010-11-20 21:25:22 +00:00
|
|
|
})
|
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
ArgList: [
|
2010-10-25 12:37:08 +00:00
|
|
|
o('Arg', function() {
|
2010-02-11 04:24:05 +00:00
|
|
|
return [$1];
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('ArgList , Arg', function() {
|
2010-10-11 07:06:29 +00:00
|
|
|
return $1.concat($3);
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('ArgList OptComma TERMINATOR Arg', function() {
|
2010-10-11 07:06:29 +00:00
|
|
|
return $1.concat($4);
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('INDENT ArgList OptComma OUTDENT', function() {
|
2010-09-09 01:39:51 +00:00
|
|
|
return $2;
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('ArgList OptComma INDENT ArgList OptComma OUTDENT', function() {
|
2010-06-09 04:37:23 +00:00
|
|
|
return $1.concat($4);
|
|
|
|
})
|
2010-02-11 04:24:05 +00:00
|
|
|
],
|
2014-01-24 16:00:34 +00:00
|
|
|
Arg: [
|
|
|
|
o('Expression'), o('Splat'), o('...', function() {
|
|
|
|
return new Expansion;
|
|
|
|
})
|
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
SimpleArgs: [
|
2010-10-25 12:37:08 +00:00
|
|
|
o('Expression'), o('SimpleArgs , Expression', function() {
|
2010-10-11 07:06:29 +00:00
|
|
|
return [].concat($1, $3);
|
2010-02-11 04:24:05 +00:00
|
|
|
})
|
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
Try: [
|
2010-10-25 12:37:08 +00:00
|
|
|
o('TRY Block', function() {
|
2010-10-07 02:44:32 +00:00
|
|
|
return new Try($2);
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('TRY Block Catch', function() {
|
2010-10-07 02:44:32 +00:00
|
|
|
return new Try($2, $3[0], $3[1]);
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('TRY Block FINALLY Block', function() {
|
2010-10-07 02:44:32 +00:00
|
|
|
return new Try($2, null, null, $4);
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('TRY Block Catch FINALLY Block', function() {
|
2010-10-07 02:44:32 +00:00
|
|
|
return new Try($2, $3[0], $3[1], $5);
|
2010-02-11 04:24:05 +00:00
|
|
|
})
|
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
Catch: [
|
2010-10-25 12:37:08 +00:00
|
|
|
o('CATCH Identifier Block', function() {
|
2010-02-11 04:24:05 +00:00
|
|
|
return [$2, $3];
|
2012-10-23 21:57:22 +00:00
|
|
|
}), o('CATCH Object Block', function() {
|
2013-02-28 13:37:30 +00:00
|
|
|
return [LOC(2)(new Value($2)), $3];
|
2013-04-11 18:42:38 +00:00
|
|
|
}), o('CATCH Block', function() {
|
|
|
|
return [null, $2];
|
2010-02-11 04:24:05 +00:00
|
|
|
})
|
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
Throw: [
|
2010-10-25 12:37:08 +00:00
|
|
|
o('THROW Expression', function() {
|
2010-10-07 02:44:32 +00:00
|
|
|
return new Throw($2);
|
2010-02-11 04:24:05 +00:00
|
|
|
})
|
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
Parenthetical: [
|
2010-11-21 01:22:05 +00:00
|
|
|
o('( Body )', function() {
|
2010-10-07 03:53:26 +00:00
|
|
|
return new Parens($2);
|
2010-11-21 01:47:43 +00:00
|
|
|
}), o('( INDENT Body OUTDENT )', function() {
|
|
|
|
return new Parens($3);
|
2010-02-11 04:24:05 +00:00
|
|
|
})
|
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
WhileSource: [
|
2010-10-25 12:37:08 +00:00
|
|
|
o('WHILE Expression', function() {
|
2010-10-07 02:44:32 +00:00
|
|
|
return new While($2);
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('WHILE Expression WHEN Expression', function() {
|
2010-10-07 02:44:32 +00:00
|
|
|
return new While($2, {
|
2010-04-29 01:46:47 +00:00
|
|
|
guard: $4
|
2010-02-24 03:53:43 +00:00
|
|
|
});
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('UNTIL Expression', function() {
|
2010-10-07 02:44:32 +00:00
|
|
|
return new While($2, {
|
2010-04-29 02:08:00 +00:00
|
|
|
invert: true
|
|
|
|
});
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('UNTIL Expression WHEN Expression', function() {
|
2010-10-07 02:44:32 +00:00
|
|
|
return new While($2, {
|
2010-04-29 02:08:00 +00:00
|
|
|
invert: true,
|
|
|
|
guard: $4
|
|
|
|
});
|
2010-02-24 03:53:43 +00:00
|
|
|
})
|
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
While: [
|
2010-10-25 12:37:08 +00:00
|
|
|
o('WhileSource Block', function() {
|
2010-06-12 23:05:13 +00:00
|
|
|
return $1.addBody($2);
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('Statement WhileSource', function() {
|
2013-02-25 04:51:05 +00:00
|
|
|
return $2.addBody(LOC(1)(Block.wrap([$1])));
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('Expression WhileSource', function() {
|
2013-02-25 04:51:05 +00:00
|
|
|
return $2.addBody(LOC(1)(Block.wrap([$1])));
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('Loop', function() {
|
2010-06-12 16:15:53 +00:00
|
|
|
return $1;
|
|
|
|
})
|
|
|
|
],
|
|
|
|
Loop: [
|
2010-10-25 12:37:08 +00:00
|
|
|
o('LOOP Block', function() {
|
Refactor `Literal` into several subtypes
Previously, the parser created `Literal` nodes for many things. This resulted in
information loss. Instead of being able to check the node type, we had to use
regexes to tell the different types of `Literal`s apart. That was a bit like
parsing literals twice: Once in the lexer, and once (or more) in the compiler.
It also caused problems, such as `` `this` `` and `this` being indistinguishable
(fixes #2009).
Instead returning `new Literal` in the grammar, subtypes of it are now returned
instead, such as `NumberLiteral`, `StringLiteral` and `IdentifierLiteral`. `new
Literal` by itself is only used to represent code chunks that fit no category.
(While mentioning `NumberLiteral`, there's also `InfinityLiteral` now, which is
a subtype of `NumberLiteral`.)
`StringWithInterpolations` has been added as a subtype of `Parens`, and
`RegexWithInterpolations` as a subtype of `Call`. This makes it easier for other
programs to make use of CoffeeScript's "AST" (nodes). For example, it is now
possible to distinguish between `"a #{b} c"` and `"a " + b + " c"`. Fixes #4192.
`SuperCall` has been added as a subtype of `Call`.
Note, though, that some information is still lost, especially in the lexer. For
example, there is no way to distinguish a heredoc from a regular string, or a
heregex without interpolations from a regular regex. Binary and octal number
literals are indistinguishable from hexadecimal literals.
After the new subtypes were added, they were taken advantage of, removing most
regexes in nodes.coffee. `SIMPLENUM` (which matches non-hex integers) had to be
kept, though, because such numbers need special handling in JavaScript (for
example in `1..toString()`).
An especially nice hack to get rid of was using `new String()` for the token
value for reserved identifiers (to be able to set a property on them which could
survive through the parser). Now it's a good old regular string.
In range literals, slices, splices and for loop steps when number literals
are involved, CoffeeScript can do some optimizations, such as precomputing the
value of, say, `5 - 3` (outputting `2` instead of `5 - 3` literally). As a side
bonus, this now also works with hexadecimal number literals, such as `0x02`.
Finally, this also improves the output of `coffee --nodes`:
# Before:
$ bin/coffee -ne 'while true
"#{a}"
break'
Block
While
Value
Bool
Block
Value
Parens
Block
Op +
Value """"
Value
Parens
Block
Value "a" "break"
# After:
$ bin/coffee -ne 'while true
"#{a}"
break'
Block
While
Value BooleanLiteral: true
Block
Value
StringWithInterpolations
Block
Op +
Value StringLiteral: ""
Value
Parens
Block
Value IdentifierLiteral: a
StatementLiteral: break
2016-01-31 19:24:31 +00:00
|
|
|
return new While(LOC(1)(new BooleanLiteral('true'))).addBody($2);
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('LOOP Expression', function() {
|
Refactor `Literal` into several subtypes
Previously, the parser created `Literal` nodes for many things. This resulted in
information loss. Instead of being able to check the node type, we had to use
regexes to tell the different types of `Literal`s apart. That was a bit like
parsing literals twice: Once in the lexer, and once (or more) in the compiler.
It also caused problems, such as `` `this` `` and `this` being indistinguishable
(fixes #2009).
Instead returning `new Literal` in the grammar, subtypes of it are now returned
instead, such as `NumberLiteral`, `StringLiteral` and `IdentifierLiteral`. `new
Literal` by itself is only used to represent code chunks that fit no category.
(While mentioning `NumberLiteral`, there's also `InfinityLiteral` now, which is
a subtype of `NumberLiteral`.)
`StringWithInterpolations` has been added as a subtype of `Parens`, and
`RegexWithInterpolations` as a subtype of `Call`. This makes it easier for other
programs to make use of CoffeeScript's "AST" (nodes). For example, it is now
possible to distinguish between `"a #{b} c"` and `"a " + b + " c"`. Fixes #4192.
`SuperCall` has been added as a subtype of `Call`.
Note, though, that some information is still lost, especially in the lexer. For
example, there is no way to distinguish a heredoc from a regular string, or a
heregex without interpolations from a regular regex. Binary and octal number
literals are indistinguishable from hexadecimal literals.
After the new subtypes were added, they were taken advantage of, removing most
regexes in nodes.coffee. `SIMPLENUM` (which matches non-hex integers) had to be
kept, though, because such numbers need special handling in JavaScript (for
example in `1..toString()`).
An especially nice hack to get rid of was using `new String()` for the token
value for reserved identifiers (to be able to set a property on them which could
survive through the parser). Now it's a good old regular string.
In range literals, slices, splices and for loop steps when number literals
are involved, CoffeeScript can do some optimizations, such as precomputing the
value of, say, `5 - 3` (outputting `2` instead of `5 - 3` literally). As a side
bonus, this now also works with hexadecimal number literals, such as `0x02`.
Finally, this also improves the output of `coffee --nodes`:
# Before:
$ bin/coffee -ne 'while true
"#{a}"
break'
Block
While
Value
Bool
Block
Value
Parens
Block
Op +
Value """"
Value
Parens
Block
Value "a" "break"
# After:
$ bin/coffee -ne 'while true
"#{a}"
break'
Block
While
Value BooleanLiteral: true
Block
Value
StringWithInterpolations
Block
Op +
Value StringLiteral: ""
Value
Parens
Block
Value IdentifierLiteral: a
StatementLiteral: break
2016-01-31 19:24:31 +00:00
|
|
|
return new While(LOC(1)(new BooleanLiteral('true'))).addBody(LOC(2)(Block.wrap([$2])));
|
2010-02-11 04:24:05 +00:00
|
|
|
})
|
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
For: [
|
2010-10-13 04:53:56 +00:00
|
|
|
o('Statement ForBody', function() {
|
2010-12-21 23:54:36 +00:00
|
|
|
return new For($1, $2);
|
2010-10-13 04:53:56 +00:00
|
|
|
}), o('Expression ForBody', function() {
|
2010-12-21 23:54:36 +00:00
|
|
|
return new For($1, $2);
|
2010-10-13 04:53:56 +00:00
|
|
|
}), o('ForBody Block', function() {
|
2010-12-21 23:54:36 +00:00
|
|
|
return new For($2, $1);
|
2010-11-20 21:25:22 +00:00
|
|
|
})
|
|
|
|
],
|
|
|
|
ForBody: [
|
|
|
|
o('FOR Range', function() {
|
|
|
|
return {
|
2013-02-28 13:37:30 +00:00
|
|
|
source: LOC(2)(new Value($2))
|
2010-11-20 21:25:22 +00:00
|
|
|
};
|
2015-01-10 01:31:56 +00:00
|
|
|
}), o('FOR Range BY Expression', function() {
|
|
|
|
return {
|
|
|
|
source: LOC(2)(new Value($2)),
|
|
|
|
step: $4
|
|
|
|
};
|
2010-11-20 21:25:22 +00:00
|
|
|
}), o('ForStart ForSource', function() {
|
2010-11-28 23:33:43 +00:00
|
|
|
$2.own = $1.own;
|
2010-12-21 23:54:36 +00:00
|
|
|
$2.name = $1[0];
|
|
|
|
$2.index = $1[1];
|
2010-11-20 21:25:22 +00:00
|
|
|
return $2;
|
|
|
|
})
|
|
|
|
],
|
|
|
|
ForStart: [
|
|
|
|
o('FOR ForVariables', function() {
|
|
|
|
return $2;
|
2010-11-28 23:33:43 +00:00
|
|
|
}), o('FOR OWN ForVariables', function() {
|
|
|
|
$3.own = true;
|
2010-11-20 21:25:22 +00:00
|
|
|
return $3;
|
2010-02-11 04:24:05 +00:00
|
|
|
})
|
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
ForValue: [
|
2012-04-24 16:21:47 +00:00
|
|
|
o('Identifier'), o('ThisProperty'), o('Array', function() {
|
2013-02-28 13:37:30 +00:00
|
|
|
return new Value($1);
|
2010-10-13 04:53:56 +00:00
|
|
|
}), o('Object', function() {
|
2013-02-28 13:37:30 +00:00
|
|
|
return new Value($1);
|
2010-04-26 18:35:35 +00:00
|
|
|
})
|
|
|
|
],
|
2010-11-20 21:25:22 +00:00
|
|
|
ForVariables: [
|
|
|
|
o('ForValue', function() {
|
|
|
|
return [$1];
|
|
|
|
}), o('ForValue , ForValue', function() {
|
|
|
|
return [$1, $3];
|
|
|
|
})
|
|
|
|
],
|
|
|
|
ForSource: [
|
2010-10-13 04:53:56 +00:00
|
|
|
o('FORIN Expression', function() {
|
2010-02-11 04:24:05 +00:00
|
|
|
return {
|
|
|
|
source: $2
|
|
|
|
};
|
2010-11-20 21:25:22 +00:00
|
|
|
}), o('FOROF Expression', function() {
|
2010-02-11 04:24:05 +00:00
|
|
|
return {
|
|
|
|
source: $2,
|
2010-11-20 21:25:22 +00:00
|
|
|
object: true
|
2010-02-11 04:24:05 +00:00
|
|
|
};
|
2010-11-20 21:25:22 +00:00
|
|
|
}), o('FORIN Expression WHEN Expression', function() {
|
2010-03-28 18:32:01 +00:00
|
|
|
return {
|
|
|
|
source: $2,
|
2010-11-20 21:25:22 +00:00
|
|
|
guard: $4
|
2010-03-28 18:32:01 +00:00
|
|
|
};
|
2010-10-13 04:53:56 +00:00
|
|
|
}), o('FOROF Expression WHEN Expression', function() {
|
2010-03-28 18:32:01 +00:00
|
|
|
return {
|
|
|
|
source: $2,
|
2010-11-20 21:25:22 +00:00
|
|
|
guard: $4,
|
|
|
|
object: true
|
2010-03-28 18:32:01 +00:00
|
|
|
};
|
2010-11-20 21:25:22 +00:00
|
|
|
}), o('FORIN Expression BY Expression', function() {
|
2010-10-13 04:53:56 +00:00
|
|
|
return {
|
2010-11-20 21:25:22 +00:00
|
|
|
source: $2,
|
|
|
|
step: $4
|
2010-10-13 04:53:56 +00:00
|
|
|
};
|
2010-11-20 21:25:22 +00:00
|
|
|
}), o('FORIN Expression WHEN Expression BY Expression', function() {
|
2010-10-13 04:53:56 +00:00
|
|
|
return {
|
2010-11-20 21:25:22 +00:00
|
|
|
source: $2,
|
|
|
|
guard: $4,
|
|
|
|
step: $6
|
2010-10-13 04:53:56 +00:00
|
|
|
};
|
2010-11-20 21:25:22 +00:00
|
|
|
}), o('FORIN Expression BY Expression WHEN Expression', function() {
|
2010-10-13 04:53:56 +00:00
|
|
|
return {
|
2010-11-20 21:25:22 +00:00
|
|
|
source: $2,
|
2010-03-28 18:32:01 +00:00
|
|
|
step: $4,
|
2010-04-29 01:46:47 +00:00
|
|
|
guard: $6
|
2010-03-28 18:32:01 +00:00
|
|
|
};
|
2010-02-11 04:24:05 +00:00
|
|
|
})
|
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
Switch: [
|
2010-10-25 12:37:08 +00:00
|
|
|
o('SWITCH Expression INDENT Whens OUTDENT', function() {
|
2010-10-07 02:44:32 +00:00
|
|
|
return new Switch($2, $4);
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('SWITCH Expression INDENT Whens ELSE Block OUTDENT', function() {
|
2010-10-07 02:44:32 +00:00
|
|
|
return new Switch($2, $4, $6);
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('SWITCH INDENT Whens OUTDENT', function() {
|
2010-10-07 02:44:32 +00:00
|
|
|
return new Switch(null, $3);
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('SWITCH INDENT Whens ELSE Block OUTDENT', function() {
|
2010-10-07 02:44:32 +00:00
|
|
|
return new Switch(null, $3, $5);
|
2010-02-11 04:24:05 +00:00
|
|
|
})
|
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
Whens: [
|
2010-10-25 12:37:08 +00:00
|
|
|
o('When'), o('Whens When', function() {
|
2010-09-16 03:46:01 +00:00
|
|
|
return $1.concat($2);
|
2010-02-11 04:24:05 +00:00
|
|
|
})
|
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
When: [
|
2010-10-25 12:37:08 +00:00
|
|
|
o('LEADING_WHEN SimpleArgs Block', function() {
|
2010-09-16 03:46:01 +00:00
|
|
|
return [[$2, $3]];
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('LEADING_WHEN SimpleArgs Block TERMINATOR', function() {
|
2010-09-16 03:46:01 +00:00
|
|
|
return [[$2, $3]];
|
2010-02-11 04:24:05 +00:00
|
|
|
})
|
|
|
|
],
|
2010-06-27 15:46:30 +00:00
|
|
|
IfBlock: [
|
2013-03-09 07:44:45 +00:00
|
|
|
o('IF Expression Block', function() {
|
2010-10-07 02:44:32 +00:00
|
|
|
return new If($2, $3, {
|
2010-12-21 03:50:49 +00:00
|
|
|
type: $1
|
2010-04-27 23:35:15 +00:00
|
|
|
});
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('IfBlock ELSE IF Expression Block', function() {
|
2013-06-21 00:47:29 +00:00
|
|
|
return $1.addElse(LOC(3, 5)(new If($4, $5, {
|
2010-12-21 03:50:49 +00:00
|
|
|
type: $3
|
2013-06-21 00:47:29 +00:00
|
|
|
})));
|
2013-03-09 02:40:37 +00:00
|
|
|
})
|
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
If: [
|
2011-01-11 04:19:31 +00:00
|
|
|
o('IfBlock'), o('IfBlock ELSE Block', function() {
|
|
|
|
return $1.addElse($3);
|
|
|
|
}), o('Statement POST_IF Expression', function() {
|
2013-02-25 04:51:05 +00:00
|
|
|
return new If($3, LOC(1)(Block.wrap([$1])), {
|
2010-12-21 03:50:49 +00:00
|
|
|
type: $2,
|
2010-04-05 14:26:23 +00:00
|
|
|
statement: true
|
|
|
|
});
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('Expression POST_IF Expression', function() {
|
2013-02-25 04:51:05 +00:00
|
|
|
return new If($3, LOC(1)(Block.wrap([$1])), {
|
2010-12-21 03:50:49 +00:00
|
|
|
type: $2,
|
2010-02-11 04:24:05 +00:00
|
|
|
statement: true
|
|
|
|
});
|
|
|
|
})
|
2010-03-07 16:41:56 +00:00
|
|
|
],
|
2010-04-27 03:46:35 +00:00
|
|
|
Operation: [
|
2010-10-21 00:16:17 +00:00
|
|
|
o('UNARY Expression', function() {
|
2013-02-28 13:37:30 +00:00
|
|
|
return new Op($1, $2);
|
2013-03-25 03:05:04 +00:00
|
|
|
}), o('UNARY_MATH Expression', function() {
|
|
|
|
return new Op($1, $2);
|
2010-10-23 01:44:03 +00:00
|
|
|
}), o('- Expression', (function() {
|
2013-02-28 13:37:30 +00:00
|
|
|
return new Op('-', $2);
|
2010-10-23 01:44:03 +00:00
|
|
|
}), {
|
2013-03-25 03:05:04 +00:00
|
|
|
prec: 'UNARY_MATH'
|
2010-10-23 01:44:03 +00:00
|
|
|
}), o('+ Expression', (function() {
|
2013-02-28 13:37:30 +00:00
|
|
|
return new Op('+', $2);
|
2010-10-23 01:44:03 +00:00
|
|
|
}), {
|
2013-03-25 03:05:04 +00:00
|
|
|
prec: 'UNARY_MATH'
|
2010-10-21 00:16:17 +00:00
|
|
|
}), o('-- SimpleAssignable', function() {
|
2013-02-28 13:37:30 +00:00
|
|
|
return new Op('--', $2);
|
2010-10-21 00:16:17 +00:00
|
|
|
}), o('++ SimpleAssignable', function() {
|
2013-02-28 13:37:30 +00:00
|
|
|
return new Op('++', $2);
|
2010-10-21 00:16:17 +00:00
|
|
|
}), o('SimpleAssignable --', function() {
|
2013-02-28 13:37:30 +00:00
|
|
|
return new Op('--', $1, null, true);
|
2010-10-21 00:16:17 +00:00
|
|
|
}), o('SimpleAssignable ++', function() {
|
2013-02-28 13:37:30 +00:00
|
|
|
return new Op('++', $1, null, true);
|
2010-10-25 12:37:08 +00:00
|
|
|
}), o('Expression ?', function() {
|
|
|
|
return new Existence($1);
|
2010-10-21 00:16:17 +00:00
|
|
|
}), o('Expression + Expression', function() {
|
2013-02-28 13:37:30 +00:00
|
|
|
return new Op('+', $1, $3);
|
2010-10-21 00:16:17 +00:00
|
|
|
}), o('Expression - Expression', function() {
|
2013-02-28 13:37:30 +00:00
|
|
|
return new Op('-', $1, $3);
|
2010-10-21 00:16:17 +00:00
|
|
|
}), o('Expression MATH Expression', function() {
|
2013-02-28 13:37:30 +00:00
|
|
|
return new Op($2, $1, $3);
|
2013-03-25 01:47:46 +00:00
|
|
|
}), o('Expression ** Expression', function() {
|
|
|
|
return new Op($2, $1, $3);
|
2010-10-21 00:16:17 +00:00
|
|
|
}), o('Expression SHIFT Expression', function() {
|
2013-02-28 13:37:30 +00:00
|
|
|
return new Op($2, $1, $3);
|
2010-10-21 00:16:17 +00:00
|
|
|
}), o('Expression COMPARE Expression', function() {
|
2013-02-28 13:37:30 +00:00
|
|
|
return new Op($2, $1, $3);
|
2010-10-21 00:16:17 +00:00
|
|
|
}), o('Expression LOGIC Expression', function() {
|
2013-02-28 13:37:30 +00:00
|
|
|
return new Op($2, $1, $3);
|
2010-10-21 00:16:17 +00:00
|
|
|
}), o('Expression RELATION Expression', function() {
|
2010-11-09 04:07:51 +00:00
|
|
|
if ($2.charAt(0) === '!') {
|
2013-02-28 13:37:30 +00:00
|
|
|
return new Op($2.slice(1), $1, $3).invert();
|
2010-11-09 04:07:51 +00:00
|
|
|
} else {
|
2013-02-28 13:37:30 +00:00
|
|
|
return new Op($2, $1, $3);
|
2010-11-09 04:07:51 +00:00
|
|
|
}
|
2013-11-18 04:32:15 +00:00
|
|
|
}), o('SimpleAssignable COMPOUND_ASSIGN Expression', function() {
|
2010-10-20 00:42:12 +00:00
|
|
|
return new Assign($1, $3, $2);
|
2013-11-18 04:32:15 +00:00
|
|
|
}), o('SimpleAssignable COMPOUND_ASSIGN INDENT Expression OUTDENT', function() {
|
2010-10-20 00:42:12 +00:00
|
|
|
return new Assign($1, $4, $2);
|
2013-11-18 04:32:15 +00:00
|
|
|
}), o('SimpleAssignable COMPOUND_ASSIGN TERMINATOR Expression', function() {
|
2012-11-28 01:11:01 +00:00
|
|
|
return new Assign($1, $4, $2);
|
2010-11-09 05:26:31 +00:00
|
|
|
}), o('SimpleAssignable EXTENDS Expression', function() {
|
|
|
|
return new Extends($1, $3);
|
2010-03-07 16:41:56 +00:00
|
|
|
})
|
2010-02-11 04:24:05 +00:00
|
|
|
]
|
|
|
|
};
|
2011-09-18 22:16:39 +00:00
|
|
|
|
2014-10-13 01:32:02 +00:00
|
|
|
operators = [['left', '.', '?.', '::', '?::'], ['left', 'CALL_START', 'CALL_END'], ['nonassoc', '++', '--'], ['left', '?'], ['right', 'UNARY'], ['right', '**'], ['right', 'UNARY_MATH'], ['left', 'MATH'], ['left', '+', '-'], ['left', 'SHIFT'], ['left', 'RELATION'], ['left', 'COMPARE'], ['left', 'LOGIC'], ['nonassoc', 'INDENT', 'OUTDENT'], ['right', 'YIELD'], ['right', '=', ':', 'COMPOUND_ASSIGN', 'RETURN', 'THROW', 'EXTENDS'], ['right', 'FORIN', 'FOROF', 'BY', 'WHEN'], ['right', 'IF', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS'], ['left', 'POST_IF']];
|
2011-09-18 22:16:39 +00:00
|
|
|
|
2010-02-11 04:24:05 +00:00
|
|
|
tokens = [];
|
2011-09-18 22:16:39 +00:00
|
|
|
|
2010-10-01 22:26:37 +00:00
|
|
|
for (name in grammar) {
|
|
|
|
alternatives = grammar[name];
|
2010-12-23 18:50:52 +00:00
|
|
|
grammar[name] = (function() {
|
2015-01-30 19:33:03 +00:00
|
|
|
var i, j, len, len1, ref, results;
|
|
|
|
results = [];
|
|
|
|
for (i = 0, len = alternatives.length; i < len; i++) {
|
|
|
|
alt = alternatives[i];
|
|
|
|
ref = alt[0].split(' ');
|
|
|
|
for (j = 0, len1 = ref.length; j < len1; j++) {
|
|
|
|
token = ref[j];
|
2012-04-10 18:57:45 +00:00
|
|
|
if (!grammar[token]) {
|
|
|
|
tokens.push(token);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (name === 'Root') {
|
|
|
|
alt[1] = "return " + alt[1];
|
2010-10-24 05:36:23 +00:00
|
|
|
}
|
2015-01-30 19:33:03 +00:00
|
|
|
results.push(alt);
|
2010-02-14 22:35:14 +00:00
|
|
|
}
|
2015-01-30 19:33:03 +00:00
|
|
|
return results;
|
2010-12-23 18:50:52 +00:00
|
|
|
})();
|
2010-07-17 02:31:36 +00:00
|
|
|
}
|
2011-09-18 22:16:39 +00:00
|
|
|
|
2010-02-16 06:04:48 +00:00
|
|
|
exports.parser = new Parser({
|
2010-03-07 16:41:56 +00:00
|
|
|
tokens: tokens.join(' '),
|
|
|
|
bnf: grammar,
|
2010-02-12 04:29:12 +00:00
|
|
|
operators: operators.reverse(),
|
2010-02-11 04:24:05 +00:00
|
|
|
startSymbol: 'Root'
|
|
|
|
});
|
2011-12-14 15:39:20 +00:00
|
|
|
|
2010-09-21 07:53:58 +00:00
|
|
|
}).call(this);
|