finally, think we have this if/else/if/else/else thing licke
This commit is contained in:
parent
0f26072ad0
commit
3dc456572b
|
@ -16,7 +16,7 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// Precedence ===========================================================
|
// Precedence ===========================================================
|
||||||
operators = [["left", '?'], ["nonassoc", 'UMINUS', 'UPLUS', 'NOT', '!', '!!', '~', '++', '--'], ["left", '*', '/', '%'], ["left", '+', '-'], ["left", '<<', '>>', '>>>'], ["left", '&', '|', '^'], ["left", '<=', '<', '>', '>='], ["right", 'DELETE', 'INSTANCEOF', 'TYPEOF'], ["right", '==', '!=', 'IS', 'ISNT'], ["left", '&&', '||', 'AND', 'OR'], ["right", '-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?='], ["left", '.'], ["right", 'INDENT'], ["left", 'OUTDENT'], ["right", 'WHEN', 'LEADING_WHEN', 'IN', 'OF', 'BY'], ["right", 'THROW', 'FOR', 'NEW', 'SUPER'], ["left", 'EXTENDS'], ["right", 'ASSIGN', 'RETURN'], ["right", '->', '=>', 'UNLESS', 'IF', 'ELSE', 'ELSIF', 'WHILE']];
|
operators = [["left", '?'], ["nonassoc", 'UMINUS', 'UPLUS', 'NOT', '!', '!!', '~', '++', '--'], ["left", '*', '/', '%'], ["left", '+', '-'], ["left", '<<', '>>', '>>>'], ["left", '&', '|', '^'], ["left", '<=', '<', '>', '>='], ["right", 'DELETE', 'INSTANCEOF', 'TYPEOF'], ["right", '==', '!=', 'IS', 'ISNT'], ["left", '&&', '||', 'AND', 'OR'], ["right", '-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?='], ["left", '.'], ["right", 'INDENT'], ["left", 'OUTDENT'], ["right", 'WHEN', 'LEADING_WHEN', 'IN', 'OF', 'BY'], ["right", 'THROW', 'FOR', 'NEW', 'SUPER'], ["left", 'EXTENDS'], ["right", 'ASSIGN', 'RETURN'], ["right", '->', '=>', 'UNLESS', 'IF', 'ELSE', 'WHILE']];
|
||||||
// Grammar ==============================================================
|
// Grammar ==============================================================
|
||||||
grammar = {
|
grammar = {
|
||||||
// All parsing will end in this rule, being the trunk of the AST.
|
// All parsing will end in this rule, being the trunk of the AST.
|
||||||
|
@ -483,19 +483,21 @@
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
// The most basic form of "if".
|
// The most basic form of "if".
|
||||||
IfBlock: [o("IF Expression Block", function() {
|
IfStart: [o("IF Expression Block", function() {
|
||||||
return new IfNode($2, $3);
|
return new IfNode($2, $3);
|
||||||
}), o("IF Expression Block ElsIfs", function() {
|
}), o("IfStart ElsIfs", function() {
|
||||||
return (new IfNode($2, $3)).add_else($4);
|
return $1.add_else($2);
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
ElsIf: [o("ELSEIF Expression Block", function() {
|
IfBlock: [o("IfStart", function() {
|
||||||
return new IfNode($2, $3);
|
return $1;
|
||||||
|
}), o("IfStart ELSE Block", function() {
|
||||||
|
return $1.add_else($3);
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
// Multiple elsifs can be chained together.
|
// Multiple elsifs can be chained together.
|
||||||
ElsIfs: [o("ElsIf", function() {
|
ElsIfs: [o("ELSE IF Expression Block", function() {
|
||||||
return $1.force_statement();
|
return (new IfNode($3, $4)).force_statement();
|
||||||
}), o("ElsIfs ElsIf", function() {
|
}), o("ElsIfs ElsIf", function() {
|
||||||
return $1.add_else($2);
|
return $1.add_else($2);
|
||||||
})
|
})
|
||||||
|
@ -503,8 +505,6 @@
|
||||||
// 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("IfBlock", function() {
|
||||||
return $1;
|
return $1;
|
||||||
}), o("IfBlock ELSE Block", function() {
|
|
||||||
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, {
|
||||||
statement: true
|
statement: true
|
||||||
|
|
|
@ -117,7 +117,7 @@
|
||||||
this.tag(1, 'PROPERTY_ACCESS');
|
this.tag(1, 'PROPERTY_ACCESS');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tag === 'IF' && this.tag() === 'ELSE' ? this.tag(1, 'ELSIF') : this.token(tag, id);
|
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
|
@ -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', 'ELSIF', 'FINALLY'].concat(EXPRESSION_TAIL);
|
EXPRESSION_CLOSE = ['CATCH', 'WHEN', 'ELSE', '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', 'ELSIF', 'OUTDENT', 'LEADING_WHEN', 'PARAM_START'];
|
SINGLE_CLOSERS = ['TERMINATOR', 'CATCH', 'FINALLY', 'ELSE', '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')) {
|
if (!(SINGLE_LINERS.indexOf(token[0]) >= 0 && post[0] !== 'INDENT' && !(token[0] === 'ELSE' && post[0] === 'IF'))) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
starter = token[0];
|
starter = token[0];
|
||||||
|
|
|
@ -34,7 +34,7 @@ operators: [
|
||||||
["right", 'THROW', 'FOR', 'NEW', 'SUPER']
|
["right", 'THROW', 'FOR', 'NEW', 'SUPER']
|
||||||
["left", 'EXTENDS']
|
["left", 'EXTENDS']
|
||||||
["right", 'ASSIGN', 'RETURN']
|
["right", 'ASSIGN', 'RETURN']
|
||||||
["right", '->', '=>', 'UNLESS', 'IF', 'ELSE', 'ELSIF', 'WHILE']
|
["right", '->', '=>', 'UNLESS', 'IF', 'ELSE', 'WHILE']
|
||||||
]
|
]
|
||||||
|
|
||||||
# Grammar ==============================================================
|
# Grammar ==============================================================
|
||||||
|
@ -410,25 +410,25 @@ grammar: {
|
||||||
]
|
]
|
||||||
|
|
||||||
# The most basic form of "if".
|
# The most basic form of "if".
|
||||||
IfBlock: [
|
IfStart: [
|
||||||
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)
|
o "IfStart ElsIfs", -> $1.add_else($2)
|
||||||
]
|
]
|
||||||
|
|
||||||
ElsIf: [
|
IfBlock: [
|
||||||
o "ELSEIF Expression Block", -> new IfNode($2, $3)
|
o "IfStart", -> $1
|
||||||
|
o "IfStart ELSE Block", -> $1.add_else($3)
|
||||||
]
|
]
|
||||||
|
|
||||||
# Multiple elsifs can be chained together.
|
# Multiple elsifs can be chained together.
|
||||||
ElsIfs: [
|
ElsIfs: [
|
||||||
o "ElsIf", -> $1.force_statement()
|
o "ELSE IF Expression Block", -> (new IfNode($3, $4)).force_statement()
|
||||||
o "ElsIfs ElsIf", -> $1.add_else($2)
|
o "ElsIfs ElsIf", -> $1.add_else($2)
|
||||||
]
|
]
|
||||||
|
|
||||||
# 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 "IfBlock", -> $1
|
||||||
o "IfBlock 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})
|
||||||
]
|
]
|
||||||
|
|
|
@ -105,10 +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 'IF' and @tag() is 'ELSE'
|
@token(tag, id)
|
||||||
@tag(1, 'ELSIF')
|
|
||||||
else
|
|
||||||
@token(tag, id)
|
|
||||||
@i += id.length
|
@i += id.length
|
||||||
true
|
true
|
||||||
|
|
||||||
|
|
|
@ -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', 'ELSIF', 'FINALLY'].concat(EXPRESSION_TAIL)
|
EXPRESSION_CLOSE: ['CATCH', 'WHEN', 'ELSE', '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', 'ELSIF', 'OUTDENT', 'LEADING_WHEN', 'PARAM_START']
|
SINGLE_CLOSERS: ['TERMINATOR', 'CATCH', 'FINALLY', 'ELSE', '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,7 +160,8 @@ 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'
|
return 1 unless SINGLE_LINERS.indexOf(token[0]) >= 0 and post[0] isnt 'INDENT' and
|
||||||
|
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
|
||||||
|
|
Loading…
Reference in New Issue