coffee-script 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README +3 -0
- data/coffee-script.gemspec +2 -2
- data/examples/code.coffee +3 -3
- data/examples/poignant.coffee +3 -3
- data/examples/underscore.coffee +16 -15
- data/lib/coffee-script.rb +1 -1
- data/lib/coffee_script/CoffeeScript.tmbundle/Syntaxes/CoffeeScript.tmLanguage +9 -5
- data/lib/coffee_script/command_line.rb +12 -2
- data/lib/coffee_script/grammar.y +30 -19
- data/lib/coffee_script/lexer.rb +11 -9
- data/lib/coffee_script/narwhal/coffee-script.coffee +5 -5
- data/lib/coffee_script/narwhal/lib/coffee-script.js +15 -15
- data/lib/coffee_script/narwhal/lib/coffee-script/loader.js +2 -2
- data/lib/coffee_script/nodes.rb +114 -72
- data/lib/coffee_script/parser.rb +1128 -1063
- data/lib/coffee_script/rewriter.rb +4 -0
- data/lib/coffee_script/value.rb +1 -1
- data/package.json +1 -1
- metadata +2 -3
- data/lib/coffee_script/parser.output +0 -11407
data/README
CHANGED
data/coffee-script.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'coffee-script'
|
3
|
-
s.version = '0.2.
|
4
|
-
s.date = '2010-1-
|
3
|
+
s.version = '0.2.2' # Keep version in sync with coffee-script.rb
|
4
|
+
s.date = '2010-1-10'
|
5
5
|
|
6
6
|
s.homepage = "http://jashkenas.github.com/coffee-script/"
|
7
7
|
s.summary = "The CoffeeScript Compiler"
|
data/examples/code.coffee
CHANGED
@@ -141,18 +141,18 @@ aliquam erat volutpat. Ut wisi enim ad."
|
|
141
141
|
|
142
142
|
# Inheritance and calling super.
|
143
143
|
Animal: =>
|
144
|
-
Animal
|
144
|
+
Animal::move: meters =>
|
145
145
|
alert(this.name + " moved " + meters + "m.")
|
146
146
|
|
147
147
|
Snake: name => this.name: name
|
148
148
|
Snake extends Animal
|
149
|
-
Snake
|
149
|
+
Snake::move: =>
|
150
150
|
alert('Slithering...')
|
151
151
|
super(5)
|
152
152
|
|
153
153
|
Horse: name => this.name: name
|
154
154
|
Horse extends Animal
|
155
|
-
Horse
|
155
|
+
Horse::move: =>
|
156
156
|
alert('Galloping...')
|
157
157
|
super(45)
|
158
158
|
|
data/examples/poignant.coffee
CHANGED
@@ -14,9 +14,9 @@
|
|
14
14
|
# end
|
15
15
|
|
16
16
|
LotteryTicket: {
|
17
|
-
get_picks:
|
18
|
-
set_picks:
|
19
|
-
get_purchase:
|
17
|
+
get_picks: => this.picks
|
18
|
+
set_picks: nums => this.picks: nums
|
19
|
+
get_purchase: => this.purchase
|
20
20
|
set_purchase: amount => this.purchase: amount
|
21
21
|
}
|
22
22
|
|
data/examples/underscore.coffee
CHANGED
@@ -30,7 +30,7 @@
|
|
30
30
|
breaker: if typeof(StopIteration) is 'undefined' then '__break__' else StopIteration
|
31
31
|
|
32
32
|
|
33
|
-
# Create a safe reference to the Underscore object
|
33
|
+
# Create a safe reference to the Underscore object forreference below.
|
34
34
|
_: root._: obj => new wrapper(obj)
|
35
35
|
|
36
36
|
|
@@ -39,15 +39,15 @@
|
|
39
39
|
|
40
40
|
|
41
41
|
# Create quick reference variables for speed access to core prototypes.
|
42
|
-
slice: Array
|
43
|
-
unshift: Array
|
44
|
-
toString: Object
|
45
|
-
hasOwnProperty: Object
|
46
|
-
propertyIsEnumerable: Object
|
42
|
+
slice: Array::slice
|
43
|
+
unshift: Array::unshift
|
44
|
+
toString: Object::toString
|
45
|
+
hasOwnProperty: Object::hasOwnProperty
|
46
|
+
propertyIsEnumerable: Object::propertyIsEnumerable
|
47
47
|
|
48
48
|
|
49
49
|
# Current version.
|
50
|
-
_.VERSION: '0.5.
|
50
|
+
_.VERSION: '0.5.5'
|
51
51
|
|
52
52
|
|
53
53
|
# ------------------------ Collection Functions: ---------------------------
|
@@ -60,7 +60,7 @@
|
|
60
60
|
return obj.forEach(iterator, context) if obj.forEach
|
61
61
|
if _.isArray(obj) or _.isArguments(obj)
|
62
62
|
return iterator.call(context, obj[i], i, obj) for i in [0...obj.length]
|
63
|
-
iterator.call(context, val, key, obj) for
|
63
|
+
iterator.call(context, val, key, obj) for key, val ino obj
|
64
64
|
catch e
|
65
65
|
throw e if e isnt breaker
|
66
66
|
obj
|
@@ -148,7 +148,7 @@
|
|
148
148
|
# based on '==='.
|
149
149
|
_.include: obj, target =>
|
150
150
|
return _.indexOf(obj, target) isnt -1 if _.isArray(obj)
|
151
|
-
for val
|
151
|
+
for key, val ino obj
|
152
152
|
return true if val is target
|
153
153
|
false
|
154
154
|
|
@@ -380,7 +380,7 @@
|
|
380
380
|
# Retrieve the names of an object's properties.
|
381
381
|
_.keys: obj =>
|
382
382
|
return _.range(0, obj.length) if _.isArray(obj)
|
383
|
-
key for
|
383
|
+
key for key, val ino obj
|
384
384
|
|
385
385
|
|
386
386
|
# Retrieve the values of an object's properties.
|
@@ -395,7 +395,7 @@
|
|
395
395
|
|
396
396
|
# Extend a given object with all of the properties in a source object.
|
397
397
|
_.extend: destination, source =>
|
398
|
-
for
|
398
|
+
for key, val ino source
|
399
399
|
destination[key]: val
|
400
400
|
destination
|
401
401
|
|
@@ -564,8 +564,9 @@
|
|
564
564
|
_.each(_.functions(_)) name =>
|
565
565
|
method: _[name]
|
566
566
|
wrapper.prototype[name]: =>
|
567
|
-
|
568
|
-
|
567
|
+
args: _.toArray(arguments)
|
568
|
+
unshift.call(args, this._wrapped)
|
569
|
+
result(method.apply(_, args), this._chain)
|
569
570
|
|
570
571
|
|
571
572
|
# Add all mutator Array functions to the wrapper.
|
@@ -584,10 +585,10 @@
|
|
584
585
|
|
585
586
|
|
586
587
|
# Start chaining a wrapped Underscore object.
|
587
|
-
wrapper
|
588
|
+
wrapper::chain: =>
|
588
589
|
this._chain: true
|
589
590
|
this
|
590
591
|
|
591
592
|
|
592
593
|
# Extracts the result from a wrapped and chained object.
|
593
|
-
wrapper
|
594
|
+
wrapper::value: => this._wrapped
|
data/lib/coffee-script.rb
CHANGED
@@ -10,7 +10,7 @@ require "coffee_script/parse_error"
|
|
10
10
|
# Namespace for all CoffeeScript internal classes.
|
11
11
|
module CoffeeScript
|
12
12
|
|
13
|
-
VERSION = '0.2.
|
13
|
+
VERSION = '0.2.2' # Keep in sync with the gemspec.
|
14
14
|
|
15
15
|
# Compile a script (String or IO) to JavaScript.
|
16
16
|
def self.compile(script, options={})
|
@@ -10,6 +10,10 @@
|
|
10
10
|
</array>
|
11
11
|
<key>name</key>
|
12
12
|
<string>CoffeeScript</string>
|
13
|
+
<key>foldingStartMarker</key>
|
14
|
+
<string>^.*[:=] \{[^\}]*$</string>
|
15
|
+
<key>foldingStopMarker</key>
|
16
|
+
<string>\s*\}</string>
|
13
17
|
<key>patterns</key>
|
14
18
|
<array>
|
15
19
|
<dict>
|
@@ -39,7 +43,7 @@
|
|
39
43
|
<key>comment</key>
|
40
44
|
<string>match stuff like: funcName: => … </string>
|
41
45
|
<key>match</key>
|
42
|
-
<string>([a-zA-Z0-9_
|
46
|
+
<string>([a-zA-Z0-9_?.$:*]*)\s*(=|:)\s*([\w,\s]*?)\s*(=>)</string>
|
43
47
|
<key>name</key>
|
44
48
|
<string>meta.function.coffee</string>
|
45
49
|
</dict>
|
@@ -60,7 +64,7 @@
|
|
60
64
|
<key>comment</key>
|
61
65
|
<string>match stuff like: a => … </string>
|
62
66
|
<key>match</key>
|
63
|
-
<string>([a-zA-Z0-9_?.,
|
67
|
+
<string>([a-zA-Z0-9_?., $:*]*)\s*(=>)</string>
|
64
68
|
<key>name</key>
|
65
69
|
<string>meta.inline.function.coffee</string>
|
66
70
|
</dict>
|
@@ -210,7 +214,7 @@
|
|
210
214
|
</dict>
|
211
215
|
<dict>
|
212
216
|
<key>match</key>
|
213
|
-
<string>\b([a-zA-Z$_]\w*)(\:)\s</string>
|
217
|
+
<string>\b([a-zA-Z$_](\w|\$|:)*)(\:)\s</string>
|
214
218
|
<key>name</key>
|
215
219
|
<string>variable.assignment.coffee</string>
|
216
220
|
<key>captures</key>
|
@@ -220,7 +224,7 @@
|
|
220
224
|
<key>name</key>
|
221
225
|
<string>entity.name.function.coffee</string>
|
222
226
|
</dict>
|
223
|
-
<key>
|
227
|
+
<key>3</key>
|
224
228
|
<dict>
|
225
229
|
<key>name</key>
|
226
230
|
<string>keyword.operator.coffee</string>
|
@@ -259,7 +263,7 @@
|
|
259
263
|
</dict>
|
260
264
|
<dict>
|
261
265
|
<key>match</key>
|
262
|
-
<string
|
266
|
+
<string>!|%|&|\*|\/|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\?|\|\||\:|\*=|(?<!\()/=|%=|\+=|\-=|&=|\^=|\b(in|ino|instanceof|new|delete|typeof|and|or|is|isnt|not)\b</string>
|
263
267
|
<key>name</key>
|
264
268
|
<string>keyword.operator.coffee</string>
|
265
269
|
</dict>
|
@@ -1,7 +1,13 @@
|
|
1
1
|
require 'optparse'
|
2
2
|
require 'fileutils'
|
3
3
|
require 'open3'
|
4
|
-
|
4
|
+
begin
|
5
|
+
require File.expand_path(File.dirname(__FILE__) + '/../coffee-script')
|
6
|
+
rescue LoadError => e
|
7
|
+
puts(e.message)
|
8
|
+
puts("use \"rake build:parser\" to regenerate parser.rb")
|
9
|
+
exit(1)
|
10
|
+
end
|
5
11
|
|
6
12
|
module CoffeeScript
|
7
13
|
|
@@ -133,6 +139,7 @@ Usage:
|
|
133
139
|
begin
|
134
140
|
options = {}
|
135
141
|
options[:no_wrap] = true if @options[:no_wrap]
|
142
|
+
options[:globals] = true if @options[:globals]
|
136
143
|
CoffeeScript.compile(script, options)
|
137
144
|
rescue CoffeeScript::ParseError, SyntaxError => e
|
138
145
|
STDERR.puts "#{source}: #{e.message}"
|
@@ -187,9 +194,12 @@ Usage:
|
|
187
194
|
opts.on('-v', '--verbose', 'print at every step of code generation') do |v|
|
188
195
|
ENV['VERBOSE'] = 'true'
|
189
196
|
end
|
190
|
-
opts.on('-n', '--no-wrap', 'raw output, no safety wrapper
|
197
|
+
opts.on('-n', '--no-wrap', 'raw output, no function safety wrapper') do |n|
|
191
198
|
@options[:no_wrap] = true
|
192
199
|
end
|
200
|
+
opts.on('-g', '--globals', 'attach all top-level variable as globals') do |n|
|
201
|
+
@options[:globals] = true
|
202
|
+
end
|
193
203
|
opts.on_tail('--install-bundle', 'install the CoffeeScript TextMate bundle') do |i|
|
194
204
|
install_bundle
|
195
205
|
exit
|
data/lib/coffee_script/grammar.y
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
class Parser
|
2
2
|
|
3
|
-
# Declare tokens produced by the lexer
|
3
|
+
# Declare terminal tokens produced by the lexer.
|
4
4
|
token IF ELSE UNLESS
|
5
5
|
token NUMBER STRING REGEX
|
6
6
|
token TRUE FALSE YES NO ON OFF
|
7
|
-
token IDENTIFIER PROPERTY_ACCESS
|
8
|
-
token CODE PARAM
|
7
|
+
token IDENTIFIER PROPERTY_ACCESS PROTOTYPE_ACCESS
|
8
|
+
token CODE PARAM NEW RETURN
|
9
9
|
token TRY CATCH FINALLY THROW
|
10
10
|
token BREAK CONTINUE
|
11
|
-
token FOR IN BY WHEN WHILE
|
11
|
+
token FOR IN INO BY WHEN WHILE
|
12
12
|
token SWITCH LEADING_WHEN
|
13
13
|
token DELETE INSTANCEOF TYPEOF
|
14
14
|
token SUPER EXTENDS
|
@@ -21,7 +21,7 @@ token INDENT OUTDENT
|
|
21
21
|
# Declare order of operations.
|
22
22
|
prechigh
|
23
23
|
left '?'
|
24
|
-
nonassoc UMINUS
|
24
|
+
nonassoc UMINUS NOT '!' '!!' '~' '++' '--'
|
25
25
|
left '*' '/' '%'
|
26
26
|
left '+' '-'
|
27
27
|
left '<<' '>>' '>>>'
|
@@ -34,11 +34,12 @@ prechigh
|
|
34
34
|
left '.'
|
35
35
|
right INDENT
|
36
36
|
left OUTDENT
|
37
|
-
right WHEN LEADING_WHEN IN BY
|
37
|
+
right WHEN LEADING_WHEN IN INO BY
|
38
38
|
right THROW FOR NEW SUPER
|
39
39
|
left EXTENDS
|
40
40
|
left ASSIGN '||=' '&&='
|
41
|
-
right RETURN
|
41
|
+
right RETURN
|
42
|
+
right '=>' UNLESS IF ELSE WHILE
|
42
43
|
preclow
|
43
44
|
|
44
45
|
rule
|
@@ -58,13 +59,13 @@ rule
|
|
58
59
|
| Expressions Terminator { result = val[0] }
|
59
60
|
;
|
60
61
|
|
61
|
-
# All types of expressions in our language.
|
62
|
+
# All types of expressions in our language. The basic unit of CoffeeScript
|
63
|
+
# is the expression.
|
62
64
|
Expression:
|
63
65
|
Value
|
64
66
|
| Call
|
65
67
|
| Code
|
66
68
|
| Operation
|
67
|
-
| Range
|
68
69
|
| Assign
|
69
70
|
| If
|
70
71
|
| Try
|
@@ -79,18 +80,20 @@ rule
|
|
79
80
|
| Comment
|
80
81
|
;
|
81
82
|
|
83
|
+
# A block of expressions. Note that the Rewriter will convert some postfix
|
84
|
+
# forms into blocks for us, by altering the token stream.
|
82
85
|
Block:
|
83
86
|
INDENT Expressions OUTDENT { result = val[1] }
|
84
87
|
| INDENT OUTDENT { result = Expressions.new }
|
85
88
|
;
|
86
89
|
|
87
|
-
#
|
90
|
+
# Tokens that can terminate an expression.
|
88
91
|
Terminator:
|
89
92
|
"\n"
|
90
93
|
| ";"
|
91
94
|
;
|
92
95
|
|
93
|
-
# All hard-coded values.
|
96
|
+
# All hard-coded values. These can be printed straight to JavaScript.
|
94
97
|
Literal:
|
95
98
|
NUMBER { result = LiteralNode.new(val[0]) }
|
96
99
|
| STRING { result = LiteralNode.new(val[0]) }
|
@@ -107,12 +110,12 @@ rule
|
|
107
110
|
| OFF { result = LiteralNode.new(false) }
|
108
111
|
;
|
109
112
|
|
110
|
-
# Assignment to a variable.
|
113
|
+
# Assignment to a variable (or index).
|
111
114
|
Assign:
|
112
115
|
Value ASSIGN Expression { result = AssignNode.new(val[0], val[2]) }
|
113
116
|
;
|
114
117
|
|
115
|
-
# Assignment within an object literal.
|
118
|
+
# Assignment within an object literal (can be quoted).
|
116
119
|
AssignObj:
|
117
120
|
IDENTIFIER ASSIGN Expression { result = AssignNode.new(ValueNode.new(val[0]), val[2], :object) }
|
118
121
|
| STRING ASSIGN Expression { result = AssignNode.new(ValueNode.new(LiteralNode.new(val[0])), val[2], :object) }
|
@@ -122,6 +125,7 @@ rule
|
|
122
125
|
# A return statement.
|
123
126
|
Return:
|
124
127
|
RETURN Expression { result = ReturnNode.new(val[1]) }
|
128
|
+
| RETURN { result = ReturnNode.new(ValueNode.new(Value.new('null'))) }
|
125
129
|
;
|
126
130
|
|
127
131
|
# A comment.
|
@@ -184,8 +188,10 @@ rule
|
|
184
188
|
| Expression '&&=' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
185
189
|
|
186
190
|
| Expression INSTANCEOF Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
191
|
+
| Expression IN Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
187
192
|
;
|
188
193
|
|
194
|
+
# The existence operator.
|
189
195
|
Existence:
|
190
196
|
Expression '?' { result = ExistenceNode.new(val[0]) }
|
191
197
|
;
|
@@ -202,13 +208,15 @@ rule
|
|
202
208
|
| ParamList "," Param { result = val[0] << val[2] }
|
203
209
|
;
|
204
210
|
|
211
|
+
# A Parameter (or ParamSplat) in a function definition.
|
205
212
|
Param:
|
206
213
|
PARAM
|
207
|
-
|
|
214
|
+
| PARAM "." "." "." { result = ParamSplatNode.new(val[0]) }
|
208
215
|
;
|
209
216
|
|
217
|
+
# A regular splat.
|
210
218
|
Splat:
|
211
|
-
|
219
|
+
Expression "." "." "." { result = ArgSplatNode.new(val[0])}
|
212
220
|
;
|
213
221
|
|
214
222
|
# Expressions that can be treated as values.
|
@@ -218,6 +226,7 @@ rule
|
|
218
226
|
| Array { result = ValueNode.new(val[0]) }
|
219
227
|
| Object { result = ValueNode.new(val[0]) }
|
220
228
|
| Parenthetical { result = ValueNode.new(val[0]) }
|
229
|
+
| Range { result = ValueNode.new(val[0]) }
|
221
230
|
| Value Accessor { result = val[0] << val[1] }
|
222
231
|
| Invocation Accessor { result = ValueNode.new(val[0], [val[1]]) }
|
223
232
|
;
|
@@ -225,6 +234,7 @@ rule
|
|
225
234
|
# Accessing into an object or array, through dot or index notation.
|
226
235
|
Accessor:
|
227
236
|
PROPERTY_ACCESS IDENTIFIER { result = AccessorNode.new(val[1]) }
|
237
|
+
| PROTOTYPE_ACCESS IDENTIFIER { result = AccessorNode.new(val[1], true) }
|
228
238
|
| Index { result = val[0] }
|
229
239
|
| Range { result = SliceNode.new(val[0]) }
|
230
240
|
;
|
@@ -269,6 +279,7 @@ rule
|
|
269
279
|
# | Invocation Code { result = val[0] << val[1] }
|
270
280
|
;
|
271
281
|
|
282
|
+
# The list of arguments to a function invocation.
|
272
283
|
Arguments:
|
273
284
|
"(" ArgList ")" { result = val[1] }
|
274
285
|
| "(" ArgList ")" Code { result = val[1] << val[3] }
|
@@ -330,6 +341,7 @@ rule
|
|
330
341
|
# The while loop. (there is no do..while).
|
331
342
|
While:
|
332
343
|
WHILE Expression Block { result = WhileNode.new(val[1], val[2]) }
|
344
|
+
| WHILE Expression { result = WhileNode.new(val[1], nil) }
|
333
345
|
;
|
334
346
|
|
335
347
|
# Array comprehensions, including guard and current index.
|
@@ -349,6 +361,7 @@ rule
|
|
349
361
|
# The source of the array comprehension can optionally be filtered.
|
350
362
|
ForSource:
|
351
363
|
IN Expression { result = {:source => val[1]} }
|
364
|
+
| INO Expression { result = {:source => val[1], :object => true} }
|
352
365
|
| ForSource
|
353
366
|
WHEN Expression { result = val[0].merge(:filter => val[2]) }
|
354
367
|
| ForSource
|
@@ -374,12 +387,10 @@ rule
|
|
374
387
|
LEADING_WHEN Expression Block { result = IfNode.new(val[1], val[2], nil, {:statement => true}) }
|
375
388
|
| LEADING_WHEN Expression Block
|
376
389
|
Terminator { result = IfNode.new(val[1], val[2], nil, {:statement => true}) }
|
377
|
-
| Comment
|
390
|
+
| Comment Terminator When { result = val[2].add_comment(val[0]) }
|
378
391
|
;
|
379
392
|
|
380
|
-
#
|
381
|
-
# grammar expand unambiguously.
|
382
|
-
|
393
|
+
# The most basic form of "if".
|
383
394
|
IfBlock:
|
384
395
|
IF Expression Block { result = IfNode.new(val[1], val[2]) }
|
385
396
|
;
|
data/lib/coffee_script/lexer.rb
CHANGED
@@ -12,23 +12,23 @@ module CoffeeScript
|
|
12
12
|
"new", "return",
|
13
13
|
"try", "catch", "finally", "throw",
|
14
14
|
"break", "continue",
|
15
|
-
"for", "in", "by", "where", "while",
|
15
|
+
"for", "in", "ino", "by", "where", "while",
|
16
16
|
"switch", "when",
|
17
17
|
"super", "extends",
|
18
18
|
"arguments",
|
19
19
|
"delete", "instanceof", "typeof"]
|
20
20
|
|
21
21
|
# Token matching regexes.
|
22
|
-
IDENTIFIER = /\A([a-zA-Z$_]\w*)/
|
22
|
+
IDENTIFIER = /\A([a-zA-Z$_](\w|\$)*)/
|
23
23
|
NUMBER = /\A(\b((0(x|X)[0-9a-fA-F]+)|([0-9]+(\.[0-9]+)?(e[+\-]?[0-9]+)?)))\b/i
|
24
|
-
STRING = /\A(""|''|"(.*?)[^\\]"|'(.*?)[^\\]')/m
|
25
|
-
JS = /\A(``|`(.*?)[^\\]`)/m
|
24
|
+
STRING = /\A(""|''|"(.*?)([^\\]|\\\\)"|'(.*?)([^\\]|\\\\)')/m
|
25
|
+
JS = /\A(``|`(.*?)([^\\]|\\\\)`)/m
|
26
26
|
OPERATOR = /\A([+\*&|\/\-%=<>:!]+)/
|
27
27
|
WHITESPACE = /\A([ \t]+)/
|
28
28
|
COMMENT = /\A(((\n?[ \t]*)?#.*$)+)/
|
29
29
|
CODE = /\A(=>)/
|
30
|
-
REGEX = /\A(\/(.*?)[^\\]\/[imgy]{0,4})/
|
31
|
-
MULTI_DENT = /\A((\n([ \t]*)
|
30
|
+
REGEX = /\A(\/(.*?)([^\\]|\\\\)\/[imgy]{0,4})/
|
31
|
+
MULTI_DENT = /\A((\n([ \t]*))+)(\.)?/
|
32
32
|
LAST_DENT = /\n([ \t]*)/
|
33
33
|
ASSIGNMENT = /\A(:|=)\Z/
|
34
34
|
|
@@ -88,6 +88,7 @@ module CoffeeScript
|
|
88
88
|
tag = KEYWORDS.include?(identifier) ? identifier.upcase.to_sym : :IDENTIFIER
|
89
89
|
tag = :LEADING_WHEN if tag == :WHEN && [:OUTDENT, :INDENT, "\n"].include?(last_tag)
|
90
90
|
@tokens[-1][0] = :PROPERTY_ACCESS if tag == :IDENTIFIER && last_value == '.' && !(@tokens[-2][1] == '.')
|
91
|
+
@tokens[-1][0] = :PROTOTYPE_ACCESS if tag == :IDENTIFIER && last_value == '::'
|
91
92
|
token(tag, identifier)
|
92
93
|
@i += identifier.length
|
93
94
|
end
|
@@ -139,7 +140,9 @@ module CoffeeScript
|
|
139
140
|
return false unless indent = @chunk[MULTI_DENT, 1]
|
140
141
|
@line += indent.scan(MULTILINER).size
|
141
142
|
@i += indent.size
|
142
|
-
|
143
|
+
next_character = @chunk[MULTI_DENT, 4]
|
144
|
+
no_newlines = next_character == '.' || (last_value.to_s.match(NO_NEWLINE) && last_value != "=>")
|
145
|
+
return suppress_newlines(indent) if no_newlines
|
143
146
|
size = indent.scan(LAST_DENT).last.last.length
|
144
147
|
return newline_token(indent) if size == @indent
|
145
148
|
if size > @indent
|
@@ -221,8 +224,7 @@ module CoffeeScript
|
|
221
224
|
i -= 1
|
222
225
|
tok = @tokens[i]
|
223
226
|
return if !tok
|
224
|
-
next if
|
225
|
-
next tok[0] = :PARAM_SPLAT if tok[0] == '*'
|
227
|
+
next if ['.', ','].include?(tok[0])
|
226
228
|
return if tok[0] != :IDENTIFIER
|
227
229
|
tok[0] = :PARAM
|
228
230
|
end
|