Skip to content

Instantly share code, notes, and snippets.

@Constellation
Created August 2, 2010 16:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Constellation/504910 to your computer and use it in GitHub Desktop.
Save Constellation/504910 to your computer and use it in GitHub Desktop.
--- ../misc/ivjs.js 2010-07-19 03:21:40.000000000 +0900
+++ ivjs.js 2010-08-03 03:45:05.000000000 +0900
@@ -24,6 +24,7 @@
(function() {
var IDENT = new Object(), EOS = 0, ILLEGAL = 1, NOTFOUND = 2,
EXP = "EXP", STMT = "STMT", DECL = "DECL",
+ NOTFOUNDEXP = new Error("NOTFOUNDEXP"),
IdentifyReservedWords = 1, IgnoreReservedWords = 2,
IgnoreReservedWordsAndIdentifyGetterOrSetter = 3;
@@ -43,6 +44,7 @@
"super": IDENT, "while": IDENT,
"throw": IDENT, "class": IDENT,
"const": IDENT, "false": IDENT,
+ "yield": IDENT,
"delete": IDENT, "export": IDENT, "import": IDENT,
"public": IDENT, "return": IDENT, "static": IDENT,
"switch": IDENT, "typeof": IDENT,
@@ -218,10 +220,11 @@
Parser = function Parser(source) {
this.lexer = new Lexer(source);
+ this.currentFunction = null;
this.next();
};
Parser.prototype.parse = function() {
- var global = {
+ var global = this.currentFunction = {
type : "global",
body : []
};
@@ -559,6 +562,10 @@
};
Parser.prototype.parseReturnStatement = function() {
this.next();
+ if (this.currentFunction.ret === "yield") {
+ throw new Error("ILLEGAL");
+ }
+ this.currentFunction.ret = "return";
if (this.lexer.hasLineTerminatorBeforeNext ||
this.token === OP[";"] ||
this.token === OP["}"] ||
@@ -706,6 +713,9 @@
var result = this.parseAssignmentExpression(containsIn);
while (this.token === OP[","]) {
this.next();
+ if (result.type === "YieldExpression" && !result.paren) {
+ throw new Error("ILLEGAL");
+ }
var right = this.parseAssignmentExpression(containsIn);
result = {
type: "BinaryExpression",
@@ -717,22 +727,57 @@
return result;
};
Parser.prototype.parseAssignmentExpression = function(containsIn) {
- var result = this.parseConditionalExpression(containsIn);
- if (!isAssignOp(this.token)) {
- return result;
- }
- if (result.type !== "Identifier" && result.type !== "PropertyAccess") {
- throw new Error("ILLEGAL");
+ if (this.token === OP["yield"]) {
+ if (this.currentFunction.ret === "return") {
+ throw new Error("ILLEGAL");
+ }
+ this.currentFunction.ret = "yield";
+ this.next();
+ if (this.lexer.hasLineTerminatorBeforeNext ||
+ this.token === OP[";"] ||
+ this.token === OP["}"] ||
+ this.token === EOS ||
+ this.token === OP["yield"] ||
+ this.token === OP["]"] ||
+ this.token === OP[")"] ||
+ this.token === OP[":"] ||
+ this.token === OP[","]) {
+ return {
+ type: "YieldExpression",
+ expr: { type: "Undefined" }
+ };
+ }
+ try {
+ var expr = this.parseAssignmentExpression(true);
+ } catch(e) {
+ if (e === NOTFOUNDEXP) {
+ expr = { type: "Undefined" };
+ } else {
+ throw e;
+ }
+ }
+ return {
+ type: "YieldExpression",
+ expr: expr
+ };
+ } else {
+ var result = this.parseConditionalExpression(containsIn);
+ if (!isAssignOp(this.token)) {
+ return result;
+ }
+ if (result.type !== "Identifier" && result.type !== "PropertyAccess") {
+ throw new Error("ILLEGAL");
+ }
+ var op = Lexer.opToString(this.token);
+ this.next();
+ var right = this.parseAssignmentExpression(containsIn);
+ return {
+ type: "Assignment",
+ op: op,
+ left: result,
+ right: right
+ };
}
- var op = Lexer.opToString(this.token);
- this.next();
- var right = this.parseAssignmentExpression(containsIn);
- return {
- type: "Assignment",
- op: op,
- left: result,
- right: right
- };
};
Parser.prototype.parseConditionalExpression = function(containsIn) {
var result = this.parseBinaryExpression(containsIn, 9);
@@ -1029,17 +1074,27 @@
case OP["("]:
this.next();
var result = this.parseExpression(true);
+ if (result.paren) {
+ ++result.paren;
+ } else {
+ result.paren = 1;
+ }
this.expect(OP[")"]);
return result;
default:
- throw new Error("ILLEGAL");
+ throw NOTFOUNDEXP;
}
};
Parser.prototype.parseArguments = function(func) {
this.next();
while (this.token !== OP[")"]) {
var expr = this.parseAssignmentExpression(true);
+ if (expr.type === "YieldExpression" &&
+ !expr.paren &&
+ this.token === OP[","]) {
+ throw new Error("ILLEGAL");
+ }
func.args.push(expr);
if (this.token !== OP[")"]) {
this.expect(OP[","]);
@@ -1154,7 +1209,8 @@
type: "Function",
kind: kind,
params: [],
- body: []
+ body: [],
+ ret: null
};
if (allowIdentifier && this.token === OP["IDENTIFIER"]) {
literal.name = this.lexer.value;
@@ -1177,8 +1233,11 @@
this.next();
this.expect(OP["{"]);
+ var prev = this.currentFunction;
+ this.currentFunction = literal;
this.parseSourceElements(OP["}"], literal);
this.next();
+ this.currentFunction = prev;
return literal;
};
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment