one more bit to pass -- futzing with the if/else chains

This commit is contained in:
Jeremy Ashkenas
2010-02-12 23:35:03 -05:00
parent ee1c9b284a
commit 066ee52615
7 changed files with 36 additions and 27 deletions

View File

@@ -485,8 +485,12 @@
// The most basic form of "if". // The most basic form of "if".
IfBlock: [o("IF Expression Block", function() { IfBlock: [o("IF Expression Block", function() {
return new IfNode($2, $3); return new IfNode($2, $3);
}), o("IF Expression Block ElsIfs", function() { })
return (new IfNode($2, $3)).add_else($4); ],
IfChain: [o("IfBlock", function() {
return $1;
}), o("IfBlock ElsIfs", function() {
return $1.add_else($2);
}) })
], ],
ElsIf: [o("ELSEIF Expression Block", function() { ElsIf: [o("ELSEIF Expression Block", function() {
@@ -501,9 +505,9 @@
}) })
], ],
// The full complement of if blocks, including postfix one-liner ifs and unlesses. // The full complement of if blocks, including postfix one-liner ifs and unlesses.
If: [o("IfBlock", function() { If: [o("IfChain", function() {
return $1; return $1;
}), o("IfBlock ELSE Block", function() { }), o("IfChain ELSE Block", function() {
return $1.add_else($3); return $1.add_else($3);
}), o("Expression IF Expression", function() { }), o("Expression IF Expression", function() {
return new IfNode($3, Expressions.wrap([$1]), null, { return new IfNode($3, Expressions.wrap([$1]), null, {

View File

@@ -117,7 +117,7 @@
this.tag(1, 'PROPERTY_ACCESS'); this.tag(1, 'PROPERTY_ACCESS');
} }
} }
tag === 'ELSE' && this.tag() === 'IF' ? this.tag(1, 'ELSIF') : this.token(tag, id); tag === 'IF' && this.tag() === 'ELSE' ? this.tag(1, 'ELSIF') : this.token(tag, id);
this.i += id.length; this.i += id.length;
return true; return true;
}; };

File diff suppressed because one or more lines are too long

View File

@@ -26,7 +26,7 @@
return __d; return __d;
}).call(this); }).call(this);
// Tokens that indicate the close of a clause of an expression. // Tokens that indicate the close of a clause of an expression.
EXPRESSION_CLOSE = ['CATCH', 'WHEN', 'ELSE', 'FINALLY'].concat(EXPRESSION_TAIL); EXPRESSION_CLOSE = ['CATCH', 'WHEN', 'ELSE', 'ELSIF', 'FINALLY'].concat(EXPRESSION_TAIL);
// Tokens pairs that, in immediate succession, indicate an implicit call. // Tokens pairs that, in immediate succession, indicate an implicit call.
IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END']; IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END'];
IMPLICIT_END = ['IF', 'UNLESS', 'FOR', 'WHILE', 'TERMINATOR', 'OUTDENT']; IMPLICIT_END = ['IF', 'UNLESS', 'FOR', 'WHILE', 'TERMINATOR', 'OUTDENT'];
@@ -43,7 +43,7 @@
// Single-line flavors of block expressions that have unclosed endings. // Single-line flavors of block expressions that have unclosed endings.
// The grammar can't disambiguate them, so we insert the implicit indentation. // The grammar can't disambiguate them, so we insert the implicit indentation.
SINGLE_LINERS = ['ELSE', "->", "=>", 'TRY', 'FINALLY', 'THEN']; SINGLE_LINERS = ['ELSE', "->", "=>", 'TRY', 'FINALLY', 'THEN'];
SINGLE_CLOSERS = ['TERMINATOR', 'CATCH', 'FINALLY', 'ELSE', 'OUTDENT', 'LEADING_WHEN', 'PARAM_START']; SINGLE_CLOSERS = ['TERMINATOR', 'CATCH', 'FINALLY', 'ELSE', 'ELSIF', 'OUTDENT', 'LEADING_WHEN', 'PARAM_START'];
// Rewrite the token stream in multiple passes, one logical filter at // Rewrite the token stream in multiple passes, one logical filter at
// a time. This could certainly be changed into a single pass through the // a time. This could certainly be changed into a single pass through the
// stream, with a big ol' efficient switch, but it's much nicer like this. // stream, with a big ol' efficient switch, but it's much nicer like this.
@@ -229,7 +229,7 @@
return this.scan_tokens((function(__this) { return this.scan_tokens((function(__this) {
var __func = function(prev, token, post, i) { var __func = function(prev, token, post, i) {
var idx, insertion, parens, starter, tok; var idx, insertion, parens, starter, tok;
if (!(SINGLE_LINERS.indexOf(token[0]) >= 0 && post[0] !== 'INDENT' && !(token[0] === 'ELSE' && post[0] === 'IF'))) { if (!(SINGLE_LINERS.indexOf(token[0]) >= 0 && post[0] !== 'INDENT')) {
return 1; return 1;
} }
starter = token[0]; starter = token[0];

View File

@@ -412,7 +412,11 @@ grammar: {
# The most basic form of "if". # The most basic form of "if".
IfBlock: [ IfBlock: [
o "IF Expression Block", -> new IfNode($2, $3) o "IF Expression Block", -> new IfNode($2, $3)
o "IF Expression Block ElsIfs", -> (new IfNode($2, $3)).add_else($4) ]
IfChain: [
o "IfBlock", -> $1
o "IfBlock ElsIfs", -> $1.add_else($2)
] ]
ElsIf: [ ElsIf: [
@@ -427,8 +431,8 @@ grammar: {
# The full complement of if blocks, including postfix one-liner ifs and unlesses. # The full complement of if blocks, including postfix one-liner ifs and unlesses.
If: [ If: [
o "IfBlock", -> $1 o "IfChain", -> $1
o "IfBlock ELSE Block", -> $1.add_else($3) o "IfChain ELSE Block", -> $1.add_else($3)
o "Expression IF Expression", -> new IfNode($3, Expressions.wrap([$1]), null, {statement: true}) o "Expression IF Expression", -> new IfNode($3, Expressions.wrap([$1]), null, {statement: true})
o "Expression UNLESS Expression", -> new IfNode($3, Expressions.wrap([$1]), null, {statement: true, invert: true}) o "Expression UNLESS Expression", -> new IfNode($3, Expressions.wrap([$1]), null, {statement: true, invert: true})
] ]

View File

@@ -105,7 +105,7 @@ lex::identifier_token: ->
@tokens.splice(-2, 1) @tokens.splice(-2, 1)
else else
@tag(1, 'PROPERTY_ACCESS') @tag(1, 'PROPERTY_ACCESS')
if tag is 'ELSE' and @tag() is 'IF' if tag is 'IF' and @tag() is 'ELSE'
@tag(1, 'ELSIF') @tag(1, 'ELSIF')
else else
@token(tag, id) @token(tag, id)

View File

@@ -14,7 +14,7 @@ EXPRESSION_START: pair[0] for pair in BALANCED_PAIRS
EXPRESSION_TAIL: pair[1] for pair in BALANCED_PAIRS EXPRESSION_TAIL: pair[1] for pair in BALANCED_PAIRS
# Tokens that indicate the close of a clause of an expression. # Tokens that indicate the close of a clause of an expression.
EXPRESSION_CLOSE: ['CATCH', 'WHEN', 'ELSE', 'FINALLY'].concat(EXPRESSION_TAIL) EXPRESSION_CLOSE: ['CATCH', 'WHEN', 'ELSE', 'ELSIF', 'FINALLY'].concat(EXPRESSION_TAIL)
# Tokens pairs that, in immediate succession, indicate an implicit call. # Tokens pairs that, in immediate succession, indicate an implicit call.
IMPLICIT_FUNC: ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END'] IMPLICIT_FUNC: ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END']
@@ -33,7 +33,7 @@ for pair in BALANCED_PAIRS
# Single-line flavors of block expressions that have unclosed endings. # Single-line flavors of block expressions that have unclosed endings.
# The grammar can't disambiguate them, so we insert the implicit indentation. # The grammar can't disambiguate them, so we insert the implicit indentation.
SINGLE_LINERS: ['ELSE', "->", "=>", 'TRY', 'FINALLY', 'THEN'] SINGLE_LINERS: ['ELSE', "->", "=>", 'TRY', 'FINALLY', 'THEN']
SINGLE_CLOSERS: ['TERMINATOR', 'CATCH', 'FINALLY', 'ELSE', 'OUTDENT', 'LEADING_WHEN', 'PARAM_START'] SINGLE_CLOSERS: ['TERMINATOR', 'CATCH', 'FINALLY', 'ELSE', 'ELSIF', 'OUTDENT', 'LEADING_WHEN', 'PARAM_START']
# Rewrite the token stream in multiple passes, one logical filter at # Rewrite the token stream in multiple passes, one logical filter at
# a time. This could certainly be changed into a single pass through the # a time. This could certainly be changed into a single pass through the
@@ -160,8 +160,7 @@ re::add_implicit_parentheses: ->
# ')' can close a single-line block, but we need to make sure it's balanced. # ')' can close a single-line block, but we need to make sure it's balanced.
re::add_implicit_indentation: -> re::add_implicit_indentation: ->
this.scan_tokens (prev, token, post, i) => this.scan_tokens (prev, token, post, i) =>
return 1 unless SINGLE_LINERS.indexOf(token[0]) >= 0 and post[0] isnt 'INDENT' and return 1 unless SINGLE_LINERS.indexOf(token[0]) >= 0 and post[0] isnt 'INDENT'
not (token[0] is 'ELSE' and post[0] is 'IF')
starter: token[0] starter: token[0]
this.tokens.splice(i + 1, 0, ['INDENT', 2, token[2]]) this.tokens.splice(i + 1, 0, ['INDENT', 2, token[2]])
idx: i + 1 idx: i + 1