Skip to content

Commit

Permalink
Stab at jashkenas#1275, and associates
Browse files Browse the repository at this point in the history
  • Loading branch information
troels committed Feb 28, 2013
1 parent 1666716 commit 5514831
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 42 deletions.
59 changes: 37 additions & 22 deletions lib/coffee-script/lexer.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

58 changes: 38 additions & 20 deletions src/lexer.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ exports.Lexer = class Lexer
@indebt = 0 # The over-indentation at the current level.
@outdebt = 0 # The under-outdentation at the current level.
@indents = [] # The stack of all current indentation levels.
@oldDebts = [] # Stack of old indebts and outdebts, to go with indents
@ends = [] # The stack for pairing up tokens.
@tokens = [] # Stream of parsed tokens in the form `['TYPE', value, line]`.

Expand Down Expand Up @@ -316,7 +317,13 @@ exports.Lexer = class Lexer
@seenFor = no
size = indent.length - 1 - indent.lastIndexOf '\n'
noNewlines = @unfinished()
if size - @indebt is @indent
#console.log size, @indent, @indents, @indebt, @outdebt, noNewlines

if size - @indebt is @indent or size + @outdebt is @indent
if size - @indebt is @indent
@outdebt = 0
if size + @outdebt is @indent
@indebt = 0
if noNewlines then @suppressNewlines() else @newlineToken 0
return indent.length

Expand All @@ -325,39 +332,50 @@ exports.Lexer = class Lexer
@indebt = size - @indent
@suppressNewlines()
return indent.length
diff = size - @indent + @outdebt
diff = size - @indent
@token 'INDENT', diff, 0, indent.length

# Keep track of old debts, so that we can get back on track later.

if @indebt
@oldDebts.push @indebt
else if @outdebt
@oldDebts.push -@outdebt
else
@oldDebts.push 0

@indents.push diff
@ends.push 'OUTDENT'
@outdebt = @indebt = 0
@indent = size
else
@indebt = 0
@outdentToken @indent - size, noNewlines, indent.length
@indent = size
indent.length

# Record an outdent token or multiple tokens, if we happen to be moving back
# inwards past several recorded indents.
outdentToken: (moveOut, noNewlines, outdentLength) ->
while moveOut > 0
len = @indents.length - 1
if @indents[len] is undefined
indent = last @indents
oldDebt = last @oldDebts

break if not indent?
break if indent > moveOut and (not (oldDebt > 0) or indent - moveOut != oldDebt)

@indents.pop()
@oldDebts.pop()
moveOut -= indent
@indent -= indent
@pair 'OUTDENT'
@token 'OUTDENT', indent, 0, outdentLength

if oldDebt > 0 and indent + moveOut is oldDebt
@indebt = oldDebt
moveOut = 0
else if @indents[len] is @outdebt
moveOut -= @outdebt
@outdebt = 0
else if @indents[len] < @outdebt
@outdebt -= @indents[len]
moveOut -= @indents[len]
else
dent = @indents.pop() + @outdebt
moveOut -= dent
@outdebt = 0
@pair 'OUTDENT'
@token 'OUTDENT', dent, 0, outdentLength
@outdebt -= moveOut if dent
break
@outdebt = moveOut
@tokens.pop() while @value() is ';'

@token 'TERMINATOR', '\n', outdentLength, 0 unless @tag() is 'TERMINATOR' or noNewlines
this

Expand Down Expand Up @@ -605,7 +623,7 @@ exports.Lexer = class Lexer
# el.click((event) ->
# el.hide())
#
@indent -= size = last @indents
size = last @indents
@outdentToken size, true
return @pair tag
@ends.pop()
Expand Down
35 changes: 35 additions & 0 deletions test/functions.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -225,3 +225,38 @@ test "#1435 Indented property access", ->
rec.rec()
.rec()
1

test "#1275, Sub-block terminator can cause parent block termination", ->
first = (x) -> x

rec = (x, y) -> if not y then rec: rec else y()

foo = rec()
.rec "test", ->
rec("asdads").rec( ->
false
)
1
eq foo, 1

bar = rec()
.rec "test", ->
rec("asdads").rec( ->
false
)
1
eq bar, 1

baz = ->
(
1
)
2
eq baz(), 2

qux = ->
(
1
)
2
eq qux(), 2

0 comments on commit 5514831

Please # to comment.