forked from zaach/reflect.js
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit e4490a8
Showing
14 changed files
with
3,773 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,13 @@ | |||
all: build test | |||
|
|||
build: move | |||
jison lib/grammar.y lib/lexer.l | |||
mv grammar.js dist/parser.js | |||
|
|||
move: lib | |||
cp lib/*.js dist/ | |||
|
|||
|
|||
test: move dist | |||
node test/reflect-parse.js | |||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,14 @@ | |||
![Reflect.js](reflectjs.png "Reflect.js") | |||
|
|||
Reflect.js is a pure JavaScript implementation of [Mozilla's Parser API](https://developer.mozilla.org/en/SpiderMonkey/Parser_API). It does not currently support Mozilla specific extentions such as `let`, generators, list comprehensions, patterns, E4X, etc. but may eventually support ones that are/become Harmony proposals. *I'll probably add patterns next because those are pretty sweet.* | |||
|
|||
Builders are also supported. | |||
|
|||
Parsing large files can be slow, for reasons [articulated](http://www.andychu.net/ecmascript/RegExp-Enhancements.html) by Andy Chu. | |||
|
|||
Install | |||
======= | |||
|
|||
npm install reflect | |||
|
|||
MIT X Licensed. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1 @@ | |||
*.js |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,234 @@ | |||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ | |||
/* | |||
* Any copyright is dedicated to the Public Domain. | |||
* http://creativecommons.org/licenses/publicdomain/ | |||
*/ | |||
|
|||
var Reflect = require('reflect').Reflect; | |||
|
|||
// A simple proof-of-concept that the builder API can be used to generate other | |||
// formats, such as JsonMLAst: | |||
// | |||
// http://code.google.com/p/es-lab/wiki/JsonMLASTFormat | |||
// | |||
// It's incomplete (e.g., it doesn't convert source-location information and | |||
// doesn't use all the direct-eval rules), but I think it proves the point. | |||
|
|||
var JsonMLAst = (function() { | |||
function reject() { | |||
throw new SyntaxError("node type not supported"); | |||
} | |||
|
|||
function isDirectEval(expr) { | |||
// an approximation to the actual rules. you get the idea | |||
return (expr[0] === "IdExpr" && expr[1].name === "eval"); | |||
} | |||
|
|||
function functionNode(type) { | |||
return function(id, args, body, isGenerator, isExpression) { | |||
if (isExpression) | |||
body = ["ReturnStmt", {}, body]; | |||
|
|||
if (!id) | |||
id = ["Empty"]; | |||
|
|||
// Patch up the argument node types: s/IdExpr/IdPatt/g | |||
for (var i = 0; i < args.length; i++) { | |||
args[i][0] = "IdPatt"; | |||
} | |||
|
|||
args.unshift("ParamDecl", {}); | |||
|
|||
return [type, {}, id, args, body]; | |||
} | |||
} | |||
|
|||
return { | |||
program: function(stmts) { | |||
stmts.unshift("Program", {}); | |||
return stmts; | |||
}, | |||
identifier: function(name) { | |||
return ["IdExpr", { name: name }]; | |||
}, | |||
literal: function(val) { | |||
return ["LiteralExpr", { value: val }]; | |||
}, | |||
expressionStatement: function(expr) {return expr}, | |||
conditionalExpression: function(test, cons, alt) { | |||
return ["ConditionalExpr", {}, test, cons, alt]; | |||
}, | |||
unaryExpression: function(op, expr) { | |||
return ["UnaryExpr", {op: op}, expr]; | |||
}, | |||
binaryExpression: function(op, left, right) { | |||
return ["BinaryExpr", {op: op}, left, right]; | |||
}, | |||
property: function(kind, key, val) { | |||
return [kind === "init" | |||
? "DataProp" | |||
: kind === "get" | |||
? "GetterProp" | |||
: "SetterProp", | |||
{name: key[1].name}, val]; | |||
}, | |||
functionDeclaration: functionNode("FunctionDecl"), | |||
variableDeclaration: function(kind, elts) { | |||
if (kind === "let" || kind === "const") | |||
throw new SyntaxError("let and const not supported"); | |||
elts.unshift("VarDecl", {}); | |||
return elts; | |||
}, | |||
variableDeclarator: function(id, init) { | |||
id[0] = "IdPatt"; | |||
if (!init) | |||
return id; | |||
return ["InitPatt", {}, id, init]; | |||
}, | |||
sequenceExpression: function(exprs) { | |||
var length = exprs.length; | |||
var result = ["BinaryExpr", {op:","}, exprs[exprs.length - 2], exprs[exprs.length - 1]]; | |||
for (var i = exprs.length - 3; i >= 0; i--) { | |||
result = ["BinaryExpr", {op:","}, exprs[i], result]; | |||
} | |||
return result; | |||
}, | |||
assignmentExpression: function(op, lhs, expr) { | |||
return ["AssignExpr", {op: op}, lhs, expr]; | |||
}, | |||
logicalExpression: function(op, left, right) { | |||
return [op === "&&" ? "LogicalAndExpr" : "LogicalOrExpr", {}, left, right]; | |||
}, | |||
updateExpression: function(expr, op, isPrefix) { | |||
return ["CountExpr", {isPrefix:isPrefix, op:op}, expr]; | |||
}, | |||
newExpression: function(callee, args) { | |||
args.unshift("NewExpr", {}, callee); | |||
return args; | |||
}, | |||
callExpression: function(callee, args) { | |||
args.unshift(isDirectEval(callee) ? "EvalExpr" : "CallExpr", {}, callee); | |||
return args; | |||
}, | |||
memberExpression: function(isComputed, expr, member) { | |||
return ["MemberExpr", {}, expr, isComputed ? member : ["LiteralExpr", {type: "string", value: member[1].name}]]; | |||
}, | |||
functionExpression: functionNode("FunctionExpr"), | |||
arrayExpression: function(elts) { | |||
for (var i = 0; i < elts.length; i++) { | |||
if (!elts[i]) | |||
elts[i] = ["Empty"]; | |||
} | |||
elts.unshift("ArrayExpr", {}); | |||
return elts; | |||
}, | |||
objectExpression: function(props) { | |||
props.unshift("ObjectExpr", {}); | |||
return props; | |||
}, | |||
thisExpression: function() { | |||
return ["ThisExpr", {}]; | |||
}, | |||
|
|||
graphExpression: reject, | |||
graphIndexExpression: reject, | |||
comprehensionExpression: reject, | |||
generatorExpression: reject, | |||
yieldExpression: reject, | |||
letExpression: reject, | |||
|
|||
emptyStatement: function() {return ["EmptyStmt", {}] }, | |||
blockStatement: function(stmts) { | |||
stmts.unshift("BlockStmt", {}); | |||
return stmts; | |||
}, | |||
labeledStatement: function(lab, stmt) { | |||
return ["LabelledStmt", {label: lab}, stmt]; | |||
}, | |||
ifStatement: function(test, cons, alt) { | |||
return ["IfStmt", {}, test, cons, alt || ["EmptyStmt", {}]]; | |||
}, | |||
switchStatement: function(test, clauses, isLexical) { | |||
clauses.unshift("SwitchStmt", {}, test); | |||
return clauses; | |||
}, | |||
whileStatement: function(expr, stmt) { | |||
return ["WhileStmt", {}, expr, stmt]; | |||
}, | |||
doWhileStatement: function(stmt, expr) { | |||
return ["DoWhileStmt", {}, stmt, expr]; | |||
}, | |||
forStatement: function(init, test, update, body) { | |||
return ["ForStmt", {}, init || ["Empty"], test || ["Empty"], update || ["Empty"], body]; | |||
}, | |||
forInStatement: function(lhs, rhs, body) { | |||
return ["ForInStmt", {}, lhs, rhs, body]; | |||
}, | |||
breakStatement: function(lab) { | |||
return lab ? ["BreakStmt", {}, lab] : ["BreakStmt", {}]; | |||
}, | |||
continueStatement: function(lab) { | |||
return lab ? ["ContinueStmt", {}, lab] : ["ContinueStmt", {}]; | |||
}, | |||
withStatement: function(expr, stmt) { | |||
return ["WithStmt", {}, expr, stmt]; | |||
}, | |||
returnStatement: function(expr) { | |||
return expr ? ["ReturnStmt", {}, expr] : ["ReturnStmt", {}]; | |||
}, | |||
tryStatement: function(body, catches, fin) { | |||
if (catches.length > 1) | |||
throw new SyntaxError("multiple catch clauses not supported"); | |||
var node = ["TryStmt", body, catches[0] || ["Empty"]]; | |||
if (fin) | |||
node.push(fin); | |||
return node; | |||
}, | |||
throwStatement: function(expr) { | |||
return ["ThrowStmt", {}, expr]; | |||
}, | |||
debuggerStatement: function(){ return ["DebuggerStmt", {}] }, | |||
letStatement: reject, | |||
switchCase: function(expr, stmts) { | |||
if (expr) | |||
stmts.unshift("SwitchCase", {}, expr); | |||
else | |||
stmts.unshift("DefaultCase", {}); | |||
return stmts; | |||
}, | |||
catchClause: function(param, guard, body) { | |||
if (guard) | |||
throw new SyntaxError("catch guards not supported"); | |||
param[0] = "IdPatt"; | |||
return ["CatchClause", {}, param, body]; | |||
}, | |||
comprehensionBlock: reject, | |||
|
|||
arrayPattern: reject, | |||
objectPattern: reject, | |||
propertyPattern: reject, | |||
|
|||
xmlAnyName: reject, | |||
xmlAttributeSelector: reject, | |||
xmlEscape: reject, | |||
xmlFilterExpression: reject, | |||
xmlDefaultDeclaration: reject, | |||
xmlQualifiedIdentifier: reject, | |||
xmlFunctionQualifiedIdentifier: reject, | |||
xmlElement: reject, | |||
xmlText: reject, | |||
xmlList: reject, | |||
xmlStartTag: reject, | |||
xmlEndTag: reject, | |||
xmlPointTag: reject, | |||
xmlName: reject, | |||
xmlAttribute: reject, | |||
xmlCdata: reject, | |||
xmlComment: reject, | |||
xmlProcessingInstruction: reject | |||
}; | |||
})(); | |||
|
|||
console.log(JSON.stringify(Reflect.parse("2 + (-x * y)", {loc: false, builder: JsonMLAst}),null," ")); | |||
|
|||
|
Oops, something went wrong.