molstar
Version:
A comprehensive macromolecular library.
216 lines (215 loc) • 9.27 kB
JavaScript
/**
* Copyright (c) 2017-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
* @author Panagiotis Tourlas <panagiot_tourlov@hotmail.com>
* @author Koya Sakuma <koya.sakuma.work@gmail.com>
*
* Adapted from MolQL project
*/
import * as P from '../../../mol-util/monadic-parser';
import * as h from '../helper';
import { MolScriptBuilder } from '../../../mol-script/language/builder';
var B = MolScriptBuilder;
import { sstrucMap, sstrucDict, properties } from './properties';
import { operators } from './operators';
import { keywords } from './keywords';
import { functions } from './functions';
// <, <=, = or ==, >=, >, and !=
// lt, le, eq, ge, gt, and ne, =~
var valueOperators = [
{
'@desc': 'multiplication, division',
'@examples': [],
name: 'mul-div',
type: h.binaryLeft,
rule: P.MonadicParser.regexp(/\s*(\*|\/)\s*/, 1),
map: function (op, e1, e2) {
switch (op) {
case '*': return B.core.math.mult([e1, e2]);
case '/': return B.core.math.div([e1, e2]);
default: throw new Error("value operator '".concat(op, "' not supported"));
}
}
},
{
'@desc': 'addition, substraction',
'@examples': [],
name: 'add-sub',
type: h.binaryLeft,
rule: P.MonadicParser.regexp(/\s*(-|\+)\s*/, 1),
map: function (op, e1, e2) {
switch (op) {
case '-': return B.core.math.sub([e1, e2]);
case '+': return B.core.math.add([e1, e2]);
default: throw new Error("value operator '".concat(op, "' not supported"));
}
}
},
{
'@desc': 'value comparisons',
'@examples': [],
name: 'comparison',
type: h.binaryLeft,
rule: P.MonadicParser.alt(P.MonadicParser.regexp(/\s*(=~|==|>=|<=|=|!=|>|<)\s*/, 1), P.MonadicParser.whitespace.result('=')),
map: function (op, e1, e2) {
var expr;
if (e1.head !== undefined) {
if (e1.head.name === 'structure-query.atom-property.macromolecular.secondary-structure-flags') {
expr = B.core.flags.hasAny([e1, sstrucMap(e2)]);
}
if (e1.head.name === 'core.type.regex') {
expr = B.core.str.match([e1, B.core.type.str([e2])]);
}
}
else if (e2.head !== undefined) {
if (e2.head.name === 'structure-query.atom-property.macromolecular.secondary-structure-flags') {
expr = B.core.flags.hasAny([e2, sstrucMap(e1)]);
}
if (e2.head.name === 'core.type.regex') {
expr = B.core.str.match([e2, B.core.type.str([e1])]);
}
}
else if (op === '=~') {
if (e1.head) {
expr = B.core.str.match([
B.core.type.regex(["^".concat(e2, "$"), 'i']),
B.core.type.str([e1])
]);
}
else {
expr = B.core.str.match([
B.core.type.regex(["^".concat(e1, "$"), 'i']),
B.core.type.str([e2])
]);
}
}
if (!expr) {
if (e1.head)
e2 = h.wrapValue(e1, e2);
if (e2.head)
e1 = h.wrapValue(e2, e1);
switch (op) {
case '=':
case '==':
expr = B.core.rel.eq([e1, e2]);
break;
case '!=':
expr = B.core.rel.neq([e1, e2]);
break;
case '>':
expr = B.core.rel.gr([e1, e2]);
break;
case '<':
expr = B.core.rel.lt([e1, e2]);
break;
case '>=':
expr = B.core.rel.gre([e1, e2]);
break;
case '<=':
expr = B.core.rel.lte([e1, e2]);
break;
default: throw new Error("value operator '".concat(op, "' not supported"));
}
}
return B.struct.generator.atomGroups({ 'atom-test': expr });
}
}
];
var lang = P.MonadicParser.createLanguage({
Parens: function (r) {
return P.MonadicParser.alt(r.Parens, r.Operator, r.Expression).wrap(P.MonadicParser.string('('), P.MonadicParser.string(')'));
},
Expression: function (r) {
return P.MonadicParser.alt(r.RangeListProperty,
// r.NamedAtomProperties,
r.ValueQuery, r.Keywords);
},
NamedAtomProperties: function () {
var _a;
return (_a = P.MonadicParser).alt.apply(_a, h.getNamedPropertyRules(properties));
},
Keywords: function () {
var _a;
return (_a = P.MonadicParser).alt.apply(_a, h.getKeywordRules(keywords));
},
ValueRange: function (r) {
return P.MonadicParser.seq(r.Value
.skip(P.MonadicParser.regexp(/\s+TO\s+/i)), r.Value).map(function (x) { return ({ range: x }); });
},
RangeListProperty: function (r) {
var _a;
return P.MonadicParser.seq((_a = P.MonadicParser).alt.apply(_a, h.getPropertyNameRules(properties, /\s/)).skip(P.MonadicParser.whitespace), P.MonadicParser.alt(r.ValueRange, r.Value).sepBy1(P.MonadicParser.whitespace)).map(function (x) {
var _a;
var property = x[0], values = x[1];
var listValues = [];
var rangeValues = [];
values.forEach(function (v) {
if (v.range) {
rangeValues.push(B.core.rel.inRange([property, v.range[0], v.range[1]]));
}
else {
listValues.push(h.wrapValue(property, v, sstrucDict));
}
});
var rangeTest = h.orExpr(rangeValues);
var listTest = h.valuesTest(property, listValues);
var test;
if (rangeTest && listTest) {
test = B.core.logic.or([rangeTest, listTest]);
}
else {
test = rangeTest ? rangeTest : listTest;
}
return B.struct.generator.atomGroups((_a = {}, _a[h.testLevel(property)] = test, _a));
});
},
Operator: function (r) {
return h.combineOperators(operators, P.MonadicParser.alt(r.Parens, r.Expression, r.ValueQuery));
},
Query: function (r) {
return P.MonadicParser.alt(r.Operator, r.Parens, r.Expression).trim(P.MonadicParser.optWhitespace);
},
Number: function () {
return P.MonadicParser.regexp(/-?(0|[1-9][0-9]*)([.][0-9]+)?([eE][+-]?[0-9]+)?/)
.map(Number)
.desc('number');
},
String: function () {
var w = h.getReservedWords(properties, keywords, operators)
.sort(h.strLenSortFn).map(h.escapeRegExp).join('|');
return P.MonadicParser.alt(P.MonadicParser.regexp(new RegExp("(?!(".concat(w, "))[A-Z0-9_]+"), 'i')), P.MonadicParser.regexp(/'((?:[^"\\]|\\.)*)'/, 1), P.MonadicParser.regexp(/"((?:[^"\\]|\\.)*)"/, 1).map(function (x) { return B.core.type.regex(["^".concat(x, "$"), 'i']); })).desc('string');
},
Value: function (r) {
return P.MonadicParser.alt(r.Number, r.String);
},
ValueParens: function (r) {
return P.MonadicParser.alt(r.ValueParens, r.ValueOperator, r.ValueExpressions).wrap(P.MonadicParser.string('('), P.MonadicParser.string(')'));
},
ValuePropertyNames: function () {
var _a;
return (_a = P.MonadicParser).alt.apply(_a, h.getPropertyNameRules(properties, /=~|==|>=|<=|=|!=|>|<|\)|\s|\+|-|\*|\//i));
},
ValueOperator: function (r) {
return h.combineOperators(valueOperators, P.MonadicParser.alt(r.ValueParens, r.ValueExpressions));
},
ValueExpressions: function (r) {
return P.MonadicParser.alt(r.ValueFunctions, r.Value, r.ValuePropertyNames);
},
ValueFunctions: function (r) {
var _a;
return (_a = P.MonadicParser).alt.apply(_a, h.getFunctionRules(functions, r.ValueOperator));
},
ValueQuery: function (r) {
return P.MonadicParser.alt(r.ValueOperator.map(function (x) {
// if (!x.head || x.head.startsWith('core.math') || x.head.startsWith('structure-query.atom-property')) {
if (!x.head.name || !x.head.name.startsWith('structure-query.generator')) {
throw new Error("values must be part of an comparison, value '".concat(x, "'"));
}
else {
return x;
}
}));
}
});
export var transpiler = function (str) { return lang.Query.tryParse(str); };