From 9bd3cca7c4bc241bb7144d7c836dcb164c153491 Mon Sep 17 00:00:00 2001 From: Jeremy Ashkenas Date: Wed, 8 Sep 2010 22:46:13 -0400 Subject: [PATCH] Introducing the notion of 'indebt' to mirror 'outdebt', but for suppressed indentation with trailing operators etc. Issue #639. --- lib/lexer.js | 7 +++++-- src/lexer.coffee | 12 ++++++++---- test/test_if.coffee | 10 ++++++++++ 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/lib/lexer.js b/lib/lexer.js index 3949d0ea..7095ed3d 100644 --- a/lib/lexer.js +++ b/lib/lexer.js @@ -26,6 +26,7 @@ this.i = 0; this.line = o.line || 0; this.indent = 0; + this.indebt = 0; this.outdebt = 0; this.indents = []; this.tokens = []; @@ -245,20 +246,22 @@ size = indent.match(LAST_DENTS).reverse()[0].match(LAST_DENT)[1].length; nextCharacter = this.match(NEXT_CHARACTER, 1); noNewlines = nextCharacter === '.' || nextCharacter === ',' || this.unfinished(); - if (size === this.indent) { + if (size - this.indebt === this.indent) { if (noNewlines) { return this.suppressNewlines(); } return this.newlineToken(indent); } else if (size > this.indent) { if (noNewlines) { + this.indebt = size - this.indent; return this.suppressNewlines(); } diff = size - this.indent + this.outdebt; this.token('INDENT', diff); this.indents.push(diff); - this.outdebt = 0; + this.outdebt = (this.indebt = 0); } else { + this.indebt = 0; this.outdentToken(this.indent - size, noNewlines); } this.indent = size; diff --git a/src/lexer.coffee b/src/lexer.coffee index eec263a0..9344bffa 100644 --- a/src/lexer.coffee +++ b/src/lexer.coffee @@ -46,7 +46,8 @@ exports.Lexer = class Lexer @i = 0 # Current character position we're parsing. @line = o.line or 0 # The current line. @indent = 0 # The current indentation level. - @outdebt = 0 # The under-outdentation of the last outdent. + @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. @tokens = [] # Stream of parsed tokens in the form ['TYPE', value, line] while @i < @code.length @@ -203,16 +204,19 @@ exports.Lexer = class Lexer size = indent.match(LAST_DENTS).reverse()[0].match(LAST_DENT)[1].length nextCharacter = @match NEXT_CHARACTER, 1 noNewlines = nextCharacter is '.' or nextCharacter is ',' or @unfinished() - if size is @indent + if size - @indebt is @indent return @suppressNewlines() if noNewlines return @newlineToken indent else if size > @indent - return @suppressNewlines() if noNewlines + if noNewlines + @indebt = size - @indent + return @suppressNewlines() diff = size - @indent + @outdebt @token 'INDENT', diff @indents.push diff - @outdebt = 0 + @outdebt = @indebt = 0 else + @indebt = 0 @outdentToken @indent - size, noNewlines @indent = size true diff --git a/test/test_if.coffee b/test/test_if.coffee index e22c5584..e00582e9 100644 --- a/test/test_if.coffee +++ b/test/test_if.coffee @@ -118,3 +118,13 @@ isTrue = (x) -> x is true if isTrue yes then i += 1 ok i is 2 + +# If/else with a suppressed indentation via assignment. +result = + if false then 10 + else if no then 20 + else if 0 then 30 + else if NaN then 40 + else 50 + +ok result is 50