Introducing the notion of 'indebt' to mirror 'outdebt', but for suppressed indentation with trailing operators etc. Issue #639.

This commit is contained in:
Jeremy Ashkenas
2010-09-08 22:46:13 -04:00
parent 18cbddff6a
commit 9bd3cca7c4
3 changed files with 23 additions and 6 deletions

View File

@@ -26,6 +26,7 @@
this.i = 0; this.i = 0;
this.line = o.line || 0; this.line = o.line || 0;
this.indent = 0; this.indent = 0;
this.indebt = 0;
this.outdebt = 0; this.outdebt = 0;
this.indents = []; this.indents = [];
this.tokens = []; this.tokens = [];
@@ -245,20 +246,22 @@
size = indent.match(LAST_DENTS).reverse()[0].match(LAST_DENT)[1].length; size = indent.match(LAST_DENTS).reverse()[0].match(LAST_DENT)[1].length;
nextCharacter = this.match(NEXT_CHARACTER, 1); nextCharacter = this.match(NEXT_CHARACTER, 1);
noNewlines = nextCharacter === '.' || nextCharacter === ',' || this.unfinished(); noNewlines = nextCharacter === '.' || nextCharacter === ',' || this.unfinished();
if (size === this.indent) { if (size - this.indebt === this.indent) {
if (noNewlines) { if (noNewlines) {
return this.suppressNewlines(); return this.suppressNewlines();
} }
return this.newlineToken(indent); return this.newlineToken(indent);
} else if (size > this.indent) { } else if (size > this.indent) {
if (noNewlines) { if (noNewlines) {
this.indebt = size - this.indent;
return this.suppressNewlines(); return this.suppressNewlines();
} }
diff = size - this.indent + this.outdebt; diff = size - this.indent + this.outdebt;
this.token('INDENT', diff); this.token('INDENT', diff);
this.indents.push(diff); this.indents.push(diff);
this.outdebt = 0; this.outdebt = (this.indebt = 0);
} else { } else {
this.indebt = 0;
this.outdentToken(this.indent - size, noNewlines); this.outdentToken(this.indent - size, noNewlines);
} }
this.indent = size; this.indent = size;

View File

@@ -46,7 +46,8 @@ exports.Lexer = class Lexer
@i = 0 # Current character position we're parsing. @i = 0 # Current character position we're parsing.
@line = o.line or 0 # The current line. @line = o.line or 0 # The current line.
@indent = 0 # The current indentation level. @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. @indents = [] # The stack of all current indentation levels.
@tokens = [] # Stream of parsed tokens in the form ['TYPE', value, line] @tokens = [] # Stream of parsed tokens in the form ['TYPE', value, line]
while @i < @code.length while @i < @code.length
@@ -203,16 +204,19 @@ exports.Lexer = class Lexer
size = indent.match(LAST_DENTS).reverse()[0].match(LAST_DENT)[1].length size = indent.match(LAST_DENTS).reverse()[0].match(LAST_DENT)[1].length
nextCharacter = @match NEXT_CHARACTER, 1 nextCharacter = @match NEXT_CHARACTER, 1
noNewlines = nextCharacter is '.' or nextCharacter is ',' or @unfinished() noNewlines = nextCharacter is '.' or nextCharacter is ',' or @unfinished()
if size is @indent if size - @indebt is @indent
return @suppressNewlines() if noNewlines return @suppressNewlines() if noNewlines
return @newlineToken indent return @newlineToken indent
else if size > @indent else if size > @indent
return @suppressNewlines() if noNewlines if noNewlines
@indebt = size - @indent
return @suppressNewlines()
diff = size - @indent + @outdebt diff = size - @indent + @outdebt
@token 'INDENT', diff @token 'INDENT', diff
@indents.push diff @indents.push diff
@outdebt = 0 @outdebt = @indebt = 0
else else
@indebt = 0
@outdentToken @indent - size, noNewlines @outdentToken @indent - size, noNewlines
@indent = size @indent = size
true true

View File

@@ -118,3 +118,13 @@ isTrue = (x) -> x is true
if isTrue yes then i += 1 if isTrue yes then i += 1
ok i is 2 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