making the lexer more sophisticated about incorrect outdents ... a little safer for everyone.
This commit is contained in:
parent
1fbb6e8734
commit
61d9bd7e5e
17
lib/lexer.js
17
lib/lexer.js
|
@ -54,6 +54,8 @@
|
|||
// The current line.
|
||||
this.indent = 0;
|
||||
// The current indentation level.
|
||||
this.outdebt = 0;
|
||||
// The under-outdentation of the last outdent.
|
||||
this.indents = [];
|
||||
// The stack of all current indentation levels.
|
||||
this.tokens = [];
|
||||
|
@ -321,10 +323,17 @@
|
|||
// inwards past several recorded indents.
|
||||
Lexer.prototype.outdent_token = function(move_out, no_newlines) {
|
||||
var last_indent;
|
||||
while (move_out > 0 && this.indents.length) {
|
||||
last_indent = this.indents.pop();
|
||||
this.token('OUTDENT', last_indent);
|
||||
move_out -= last_indent;
|
||||
if (move_out > -this.outdebt) {
|
||||
while (move_out > 0 && this.indents.length) {
|
||||
last_indent = this.indents.pop();
|
||||
this.token('OUTDENT', last_indent);
|
||||
move_out -= last_indent;
|
||||
}
|
||||
} else {
|
||||
this.outdebt += move_out;
|
||||
}
|
||||
if (!(no_newlines)) {
|
||||
this.outdebt = move_out;
|
||||
}
|
||||
if (!(this.tag() === 'TERMINATOR' || no_newlines)) {
|
||||
this.token('TERMINATOR', "\n");
|
||||
|
|
|
@ -46,6 +46,7 @@ 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.
|
||||
@indents : [] # The stack of all current indentation levels.
|
||||
@tokens : [] # Stream of parsed tokens in the form ['TYPE', value, line]
|
||||
while @i < @code.length
|
||||
|
@ -218,10 +219,14 @@ exports.Lexer: class Lexer
|
|||
# Record an outdent token or multiple tokens, if we happen to be moving back
|
||||
# inwards past several recorded indents.
|
||||
outdent_token: (move_out, no_newlines) ->
|
||||
while move_out > 0 and @indents.length
|
||||
last_indent: @indents.pop()
|
||||
@token 'OUTDENT', last_indent
|
||||
move_out: - last_indent
|
||||
if move_out > -@outdebt
|
||||
while move_out > 0 and @indents.length
|
||||
last_indent: @indents.pop()
|
||||
@token 'OUTDENT', last_indent
|
||||
move_out: - last_indent
|
||||
else
|
||||
@outdebt: + move_out
|
||||
@outdebt: move_out unless no_newlines
|
||||
@token 'TERMINATOR', "\n" unless @tag() is 'TERMINATOR' or no_newlines
|
||||
true
|
||||
|
||||
|
|
|
@ -22,4 +22,14 @@ counter
|
|||
.tick ->
|
||||
1
|
||||
|
||||
ok results.join(' ') is '3 2 1'
|
||||
ok results.join(' ') is '3 2 1'
|
||||
|
||||
|
||||
# Make incorrect indentation safe.
|
||||
func: ->
|
||||
obj: {
|
||||
key: 10
|
||||
}
|
||||
obj.key - 5
|
||||
|
||||
ok func() is 5
|
Loading…
Reference in New Issue