UNPKG

molstar

Version:

A comprehensive macromolecular library.

164 lines 6.47 kB
/** * Copyright (c) 2018 Mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author David Sehnal <david.sehnal@gmail.com> */ import { MonadicParser as P } from '../../mol-util/monadic-parser'; import { Expression } from './expression'; import { MolScriptBuilder as B } from './builder'; export function parseMolScript(input) { return Language.parse(input); } var Language; (function (Language) { var ASTNode; (function (ASTNode) { function str(value) { return { kind: 'string', value: value }; } ASTNode.str = str; function symb(value) { return { kind: 'symbol', value: value }; } ASTNode.symb = symb; function list(bracket, nodes) { return { kind: 'list', bracket: bracket, nodes: nodes }; } ASTNode.list = list; function comment(value) { return { kind: 'comment', value: value }; } ASTNode.comment = comment; })(ASTNode || (ASTNode = {})); var ws = P.regexp(/[\n\r\s]*/); var Expr = P.lazy(function () { return (P.alt(Str, List, Symb, Comment).trim(ws)); }); var Str = P.takeWhile(function (c) { return c !== '`'; }).trim('`').map(ASTNode.str); var Symb = P.regexp(/[^()\[\]{};`,\n\r\s]+/).map(ASTNode.symb); var Comment = P.regexp(/\s*;+([^\n\r]*)\n/, 1).map(ASTNode.comment); var Args = Expr.many(); var List1 = Args.wrap('(', ')').map(function (args) { return ASTNode.list('(', args); }); var List2 = Args.wrap('[', ']').map(function (args) { return ASTNode.list('[', args); }); var List3 = Args.wrap('{', '}').map(function (args) { return ASTNode.list('{', args); }); var List = P.alt(List1, List2, List3); var Expressions = Expr.many(); function getAST(input) { return Expressions.tryParse(input); } function visitExpr(expr) { switch (expr.kind) { case 'string': return expr.value; case 'symbol': { var value = expr.value; if (value.length > 1) { var fst = value.charAt(0); switch (fst) { case '.': return B.atomName(value.substr(1)); case '_': return B.struct.type.elementSymbol([value.substr(1)]); } } if (value === 'true') return true; if (value === 'false') return false; if (isNumber(value)) return +value; return Expression.Symbol(value); } case 'list': { switch (expr.bracket) { case '[': return B.core.type.list(withoutComments(expr.nodes).map(visitExpr)); case '{': return B.core.type.set(withoutComments(expr.nodes).map(visitExpr)); case '(': { var head = visitExpr(expr.nodes[0]); return Expression.Apply(head, getArgs(expr.nodes)); } } return 0; } default: { throw new Error('should not happen'); } } } function getArgs(nodes) { if (nodes.length <= 1) return void 0; if (!hasNamedArgs(nodes)) { var args_1 = []; for (var i = 1, _i = nodes.length; i < _i; i++) { var n = nodes[i]; if (n.kind === 'comment') continue; args_1[args_1.length] = visitExpr(n); } return args_1; } var args = {}; var allNumeric = true; var pos = 0; for (var i = 1, _i = nodes.length; i < _i; i++) { var n = nodes[i]; if (n.kind === 'comment') continue; if (n.kind === 'symbol' && n.value.length > 1 && n.value.charAt(0) === ':') { var name_1 = n.value.substr(1); ++i; while (i < _i && nodes[i].kind === 'comment') { i++; } if (i >= _i) throw new Error("There must be a value foolowed a named arg ':" + name_1 + "'."); args[name_1] = visitExpr(nodes[i]); if (isNaN(+name_1)) allNumeric = false; } else { args[pos++] = visitExpr(n); } } if (allNumeric) { var keys = Object.keys(args).map(function (a) { return +a; }).sort(function (a, b) { return a - b; }); var isArray = true; for (var i = 0, _i = keys.length; i < _i; i++) { if (keys[i] !== i) { isArray = false; break; } } if (isArray) { var arrayArgs = []; for (var i = 0, _i = keys.length; i < _i; i++) { arrayArgs[i] = args[i]; } return arrayArgs; } } return args; } function hasNamedArgs(nodes) { for (var i = 1, _i = nodes.length; i < _i; i++) { var n = nodes[i]; if (n.kind === 'symbol' && n.value.length > 1 && n.value.charAt(0) === ':') return true; } return false; } function withoutComments(nodes) { var hasComment = false; for (var i = 0, _i = nodes.length; i < _i; i++) { if (nodes[i].kind === 'comment') { hasComment = true; break; } } if (!hasComment) return nodes; return nodes.filter(function (n) { return n.kind !== 'comment'; }); } function isNumber(value) { return /-?(0|[1-9][0-9]*)([.][0-9]+)?([eE][+-]?[0-9]+)?/.test(value) && !isNaN(+value); } function parse(input) { var ast = getAST(input); var ret = []; for (var _a = 0, ast_1 = ast; _a < ast_1.length; _a++) { var expr = ast_1[_a]; if (expr.kind === 'comment') continue; ret[ret.length] = visitExpr(expr); } return ret; } Language.parse = parse; })(Language || (Language = {})); //# sourceMappingURL=parser.js.map