adding until loops as the inverse of while loops
This commit is contained in:
parent
17ba44056e
commit
adbcd320b2
|
@ -470,6 +470,15 @@
|
|||
return new WhileNode($2, {
|
||||
guard: $4
|
||||
});
|
||||
}), o("UNTIL Expression", function() {
|
||||
return new WhileNode($2, {
|
||||
invert: true
|
||||
});
|
||||
}), o("UNTIL Expression WHEN Expression", function() {
|
||||
return new WhileNode($2, {
|
||||
invert: true,
|
||||
guard: $4
|
||||
});
|
||||
})
|
||||
],
|
||||
// The while loop can either be normal, with a block of expressions to execute,
|
||||
|
@ -740,7 +749,7 @@
|
|||
// 2 + (3 * 4)
|
||||
// And not:
|
||||
// (2 + 3) * 4
|
||||
operators = [["left", '?'], ["nonassoc", 'UMINUS', 'UPLUS', '!', '!!', '~', '++', '--'], ["left", '*', '/', '%'], ["left", '+', '-'], ["left", '<<', '>>', '>>>'], ["left", '&', '|', '^'], ["left", '<=', '<', '>', '>='], ["right", 'DELETE', 'INSTANCEOF', 'TYPEOF'], ["left", '==', '!='], ["left", '&&', '||'], ["right", '-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?='], ["left", '.'], ["right", 'INDENT'], ["left", 'OUTDENT'], ["right", 'WHEN', 'LEADING_WHEN', 'IN', 'OF', 'BY', 'THROW'], ["right", 'FOR', 'NEW', 'SUPER', 'CLASS'], ["left", 'EXTENDS'], ["right", 'ASSIGN', 'RETURN'], ["right", '->', '=>', '<-', 'UNLESS', 'IF', 'ELSE', 'WHILE']];
|
||||
operators = [["left", '?'], ["nonassoc", 'UMINUS', 'UPLUS', '!', '!!', '~', '++', '--'], ["left", '*', '/', '%'], ["left", '+', '-'], ["left", '<<', '>>', '>>>'], ["left", '&', '|', '^'], ["left", '<=', '<', '>', '>='], ["right", 'DELETE', 'INSTANCEOF', 'TYPEOF'], ["left", '==', '!='], ["left", '&&', '||'], ["right", '-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?='], ["left", '.'], ["right", 'INDENT'], ["left", 'OUTDENT'], ["right", 'WHEN', 'LEADING_WHEN', 'IN', 'OF', 'BY', 'THROW'], ["right", 'FOR', 'NEW', 'SUPER', 'CLASS'], ["left", 'EXTENDS'], ["right", 'ASSIGN', 'RETURN'], ["right", '->', '=>', '<-', 'UNLESS', 'IF', 'ELSE', 'WHILE', 'UNTIL']];
|
||||
// Wrapping Up
|
||||
// -----------
|
||||
// Finally, now what we have our **grammar** and our **operators**, we can create
|
||||
|
|
|
@ -615,7 +615,7 @@
|
|||
// CoffeeScript-only keywords, which we're more relaxed about allowing. They can't
|
||||
// be used standalone, but you can reference them as an attached property.
|
||||
COFFEE_ALIASES = ["and", "or", "is", "isnt", "not"];
|
||||
COFFEE_KEYWORDS = COFFEE_ALIASES.concat(["then", "unless", "yes", "no", "on", "off", "of", "by", "where", "when"]);
|
||||
COFFEE_KEYWORDS = COFFEE_ALIASES.concat(["then", "unless", "until", "yes", "no", "on", "off", "of", "by", "where", "when"]);
|
||||
// The combined list of keywords is the superset that gets passed verbatim to
|
||||
// the parser.
|
||||
KEYWORDS = JS_KEYWORDS.concat(COFFEE_KEYWORDS);
|
||||
|
|
|
@ -1176,6 +1176,9 @@
|
|||
// flexibility or more speed than a comprehension can provide.
|
||||
exports.WhileNode = (function() {
|
||||
WhileNode = function WhileNode(condition, opts) {
|
||||
if (opts && opts.invert) {
|
||||
condition = new OpNode('!', condition);
|
||||
}
|
||||
this.children = [(this.condition = condition)];
|
||||
this.guard = opts && opts.guard;
|
||||
return this;
|
||||
|
|
199
lib/parser.js
199
lib/parser.js
File diff suppressed because one or more lines are too long
|
@ -375,7 +375,7 @@
|
|||
// Tokens indicating that the implicit call must enclose a block of expressions.
|
||||
IMPLICIT_BLOCK = ['->', '=>', '{', '[', ','];
|
||||
// Tokens that always mark the end of an implicit call for single-liners.
|
||||
IMPLICIT_END = ['IF', 'UNLESS', 'FOR', 'WHILE', 'TERMINATOR', 'INDENT'].concat(EXPRESSION_END);
|
||||
IMPLICIT_END = ['IF', 'UNLESS', 'FOR', 'WHILE', 'UNTIL', 'TERMINATOR', 'INDENT'].concat(EXPRESSION_END);
|
||||
// Single-line flavors of block expressions that have unclosed endings.
|
||||
// The grammar can't disambiguate them, so we insert the implicit indentation.
|
||||
SINGLE_LINERS = ['ELSE', "->", "=>", 'TRY', 'FINALLY', 'THEN'];
|
||||
|
|
|
@ -414,6 +414,8 @@ grammar: {
|
|||
WhileSource: [
|
||||
o "WHILE Expression", -> new WhileNode $2
|
||||
o "WHILE Expression WHEN Expression", -> new WhileNode $2, {guard : $4}
|
||||
o "UNTIL Expression", -> new WhileNode $2, {invert: true}
|
||||
o "UNTIL Expression WHEN Expression", -> new WhileNode $2, {invert: true, guard: $4}
|
||||
]
|
||||
|
||||
# The while loop can either be normal, with a block of expressions to execute,
|
||||
|
@ -603,7 +605,7 @@ operators: [
|
|||
["right", 'FOR', 'NEW', 'SUPER', 'CLASS']
|
||||
["left", 'EXTENDS']
|
||||
["right", 'ASSIGN', 'RETURN']
|
||||
["right", '->', '=>', '<-', 'UNLESS', 'IF', 'ELSE', 'WHILE']
|
||||
["right", '->', '=>', '<-', 'UNLESS', 'IF', 'ELSE', 'WHILE', 'UNTIL']
|
||||
]
|
||||
|
||||
# Wrapping Up
|
||||
|
|
|
@ -449,7 +449,7 @@ JS_KEYWORDS: [
|
|||
# be used standalone, but you can reference them as an attached property.
|
||||
COFFEE_ALIASES: ["and", "or", "is", "isnt", "not"]
|
||||
COFFEE_KEYWORDS: COFFEE_ALIASES.concat [
|
||||
"then", "unless",
|
||||
"then", "unless", "until",
|
||||
"yes", "no", "on", "off",
|
||||
"of", "by", "where", "when"
|
||||
]
|
||||
|
|
|
@ -855,6 +855,7 @@ exports.SplatNode: class SplatNode extends BaseNode
|
|||
exports.WhileNode: class WhileNode extends BaseNode
|
||||
|
||||
constructor: (condition, opts) ->
|
||||
condition: new OpNode('!', condition) if opts and opts.invert
|
||||
@children:[@condition: condition]
|
||||
@guard: opts and opts.guard
|
||||
|
||||
|
|
|
@ -283,7 +283,7 @@ IMPLICIT_CALL: ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_
|
|||
IMPLICIT_BLOCK: ['->', '=>', '{', '[', ',']
|
||||
|
||||
# Tokens that always mark the end of an implicit call for single-liners.
|
||||
IMPLICIT_END: ['IF', 'UNLESS', 'FOR', 'WHILE', 'TERMINATOR', 'INDENT'].concat EXPRESSION_END
|
||||
IMPLICIT_END: ['IF', 'UNLESS', 'FOR', 'WHILE', 'UNTIL', 'TERMINATOR', 'INDENT'].concat EXPRESSION_END
|
||||
|
||||
# Single-line flavors of block expressions that have unclosed endings.
|
||||
# The grammar can't disambiguate them, so we insert the implicit indentation.
|
||||
|
|
|
@ -28,3 +28,11 @@ results: while i -= 1 when i % 2 is 0
|
|||
|
||||
ok results.join(' ') is '16 12 8 4'
|
||||
|
||||
|
||||
value: false
|
||||
i: 0
|
||||
results: until value
|
||||
value: true if i is 5
|
||||
i += 1
|
||||
|
||||
ok i is 6
|
||||
|
|
Loading…
Reference in New Issue