grasp-equery
Version:
grasp query using example code with wildcards
247 lines (246 loc) • 6.87 kB
JavaScript
// Generated by LiveScript 1.5.0
(function(){
var parser, ref$, aliasMap, matchesMap, matchesAliasMap, literalMap, getNodeAtPath, toString$ = {}.toString;
parser = require('flow-parser');
ref$ = require('grasp-syntax-javascript'), aliasMap = ref$.aliasMap, matchesMap = ref$.matchesMap, matchesAliasMap = ref$.matchesAliasMap, literalMap = ref$.literalMap;
getNodeAtPath = require('./common').getNodeAtPath;
function parse(selector){
var attempts, i$, len$, attempt, code, parserOptions, parsedSelector, path, e, selectorBody, extractedSelector, finalSelector, root;
attempts = [
{
code: selector,
path: []
}, {
code: "function f(){ " + selector + "; }",
path: ['body', 'body', 0]
}, {
code: "function* f(){ " + selector + "; }",
path: ['body', 'body', 0]
}, {
code: "(" + selector + ")",
path: []
}, {
code: "while (true) { " + selector + "; }",
path: ['body', 'body', 0]
}, {
code: "switch (x) { " + selector + " }",
path: ['cases', 0]
}, {
code: "try { } " + selector,
path: ['handlers', 0]
}
];
for (i$ = 0, len$ = attempts.length; i$ < len$; ++i$) {
attempt = attempts[i$], code = attempt.code;
try {
parserOptions = {
sourceType: 'module'
};
parsedSelector = parser.parse(code, parserOptions);
path = attempt.path;
break;
} catch (e$) {
e = e$;
continue;
}
}
if (!parsedSelector) {
throw new Error("Error processing selector '" + selector + "'.");
}
selectorBody = parsedSelector.body;
if (selectorBody.length > 1) {
throw new Error("Selector body can't be more than one statement");
}
extractedSelector = getNodeAtPath(selectorBody[0], path);
finalSelector = extractedSelector.type === 'ExpressionStatement' && !/;\s*$/.test(selector) ? extractedSelector.expression : extractedSelector;
root = {
type: 'Root',
value: finalSelector
};
processSelector(root);
return root.value;
}
function processSelector(ast){
var key, node, nodeType, i$, len$, i, n, that;
delete ast.loc;
delete ast.range;
for (key in ast) {
node = ast[key];
if (key !== 'type') {
nodeType = toString$.call(node).slice(8, -1);
if (nodeType === 'Array') {
for (i$ = 0, len$ = node.length; i$ < len$; ++i$) {
i = i$;
n = node[i$];
if (that = processNode(n)) {
node[i] = that;
} else {
processSelector(n);
}
}
} else if (nodeType === 'Object') {
if (that = processNode(node)) {
ast[key] = that;
} else {
processSelector(node);
}
}
}
}
}
function processNode(node){
var name, that, ident, attrs, n, processedAttrs, i$, len$, attr;
switch (node.type) {
case 'Identifier':
name = node.name;
if (name === '_') {
return null;
} else if (name === '__') {
return {
type: 'Grasp',
graspType: 'wildcard'
};
} else if (that = /^_\$(\w*)$/.exec(name)) {
return {
type: 'Grasp',
graspType: 'array-wildcard',
name: that[1]
};
} else if (that = /^\$(\w+)$/.exec(name)) {
return {
type: 'Grasp',
graspType: 'named-wildcard',
name: that[1]
};
} else if (that = /^_([_a-zA-Z]+)/.exec(name)) {
ident = that[1].replace(/_/, '-');
if (ident in matchesMap || ident in matchesAliasMap) {
return {
type: 'Grasp',
graspType: 'matches',
value: matchesMap[matchesAliasMap[ident] || ident]
};
} else if (ident in literalMap) {
return {
type: 'Grasp',
graspType: 'literal',
value: literalMap[ident]
};
} else {
return {
type: 'Grasp',
graspType: 'node-type',
value: aliasMap[ident] || ident
};
}
}
break;
case 'MemberExpression':
if (!node.computed) {
return;
}
attrs = [];
n = node;
while (n.type === 'MemberExpression') {
if (!n.computed) {
return;
}
attrs.unshift(n.property);
n = n.object;
}
if (n.type !== 'Identifier') {
return;
}
ident = processNode(n);
if (!ident) {
return;
}
processedAttrs = [];
for (i$ = 0, len$ = attrs.length; i$ < len$; ++i$) {
attr = attrs[i$];
if (that = processAttr(attr)) {
processedAttrs.push(that);
} else {
return;
}
}
return {
type: 'Grasp',
graspType: 'compound',
ident: ident,
attrs: processedAttrs
};
case 'ExpressionStatement':
return processNode(node.expression);
case 'Property':
if (!(node.key.type === 'Identifier' && node.value.type === 'Identifier')) {
return;
}
if (node.key.name === '_') {
if (node.value.name === '_') {
return {
type: 'Grasp',
graspType: 'wildcard'
};
} else if (/^\$/.test(node.value.name)) {
return {
type: 'Grasp',
graspType: 'array-wildcard',
name: /^\$(\w*)$/.exec(node.value.name)[1]
};
}
} else if (node.key.name === '$') {
return {
type: 'Grasp',
graspType: 'named-wildcard',
name: node.value.name
};
}
}
}
function processAttr(attr){
var attrType, path, ref$;
attrType = attr.type;
if (attrType === 'Identifier') {
if (processNode(attr)) {} else {
return {
path: [attr.name]
};
}
} else if (attrType === 'MemberExpression') {
path = getMemberPath(attr);
if (!path) {
return;
}
return {
path: path
};
} else if ((attrType === 'AssignmentExpression' || attrType === 'BinaryExpression') && ((ref$ = attr.operator) === '=' || ref$ === '!=')) {
path = getMemberPath(attr.left);
if (!path) {
return;
}
return {
path: path,
op: attr.operator,
value: attr.right
};
}
}
function getMemberPath(node){
var path;
path = [];
while (node.type === 'MemberExpression') {
if (node.computed) {
return;
}
path.unshift(node.property.name);
node = node.object;
}
path.unshift(node.name);
return path;
}
module.exports = {
parse: parse
};
}).call(this);