-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSmidge.js
27 lines (26 loc) · 13.4 KB
/
Smidge.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* Smidge: A SMILES Parser for JavaScript
* (C) 2013 by Metamolecular, LLC
* http://metamolecular.com
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
Parser=function(){function l(l){return'"'+l.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\x08/g,"\\b").replace(/\t/g,"\\t").replace(/\n/g,"\\n").replace(/\f/g,"\\f").replace(/\r/g,"\\r").replace(/[\x00-\x07\x0B\x0E-\x1F\x80-\uFFFF]/g,escape)+'"'}var n={parse:function(n,u){function r(l){I>x||(x>I&&(I=x,k=[]),k.push(l))}function t(){var l,n,u,r,t;if(r=x,t=x,l=o(),null!==l){for(n=[],u=e(),null===u&&(u=a());null!==u;)n.push(u),u=e(),null===u&&(u=a());null!==n?l=[l,n]:(l=null,x=t)}else l=null,x=t;return null!==l&&(l=function(l,n,u){for(var r=[n],t=0;t<u.length;t++)r=r.concat(u[t]);return r}(r,l[0],l[1])),null===l&&(x=r),l}function e(){var l,n,u,r,t;if(r=x,t=x,n=c(),n=null!==n?n:"",null!==n?(u=o(),null===u&&(u=d()),null!==u?n=[n,u]:(n=null,x=t)):(n=null,x=t),null!==n)for(l=[];null!==n;)l.push(n),t=x,n=c(),n=null!==n?n:"",null!==n?(u=o(),null===u&&(u=d()),null!==u?n=[n,u]:(n=null,x=t)):(n=null,x=t);else l=null;return null!==l&&(l=function(l,n){function u(l){var n=l[0],u=l[1];n&&r.push(n),r.push(u)}for(var r=[],t=0;t<n.length;t++)u(n[t]);return r}(r,l)),null===l&&(x=r),l}function a(){var l,u,e,a,o,h;if(o=x,h=x,40===n.charCodeAt(x)?(l="(",x++):(l=null,0===j&&r('"("')),null!==l)if(u=c(),u=null!==u?u:"",null!==u){if(a=t(),null!==a)for(e=[];null!==a;)e.push(a),a=t();else e=null;null!==e?(41===n.charCodeAt(x)?(a=")",x++):(a=null,0===j&&r('")"')),null!==a?l=[l,u,e,a]:(l=null,x=h)):(l=null,x=h)}else l=null,x=h;else l=null,x=h;return null!==l&&(l=function(l,n,u){var r=[];r.push({type:"open-branch"}),n&&r.push(n);for(var t=0;t<u.length;t++)r=r.concat(u[t]);return r.push({type:"close-branch"}),r}(o,l[1],l[2])),null===l&&(x=o),l}function o(){var l,n;return n=x,l=A(),null===l&&(l=i(),null===l&&(l=h(),null===l&&(l=g()))),null!==l&&(l=function(l,n){if("atom"===n.type)return n;var u=Array.isArray(n)?n.join(""):n,r="*"!==u&&u.toLowerCase()===u;return u=u.charAt(0).toUpperCase()+u.slice(1),{type:"atom",symbol:u,isotope:null,aromatic:r,chiralClass:null,hydrogens:null,charge:null,klass:0}}(n,l)),null===l&&(x=n),l}function c(){var l,u;return u=x,45===n.charCodeAt(x)?(l="-",x++):(l=null,0===j&&r('"-"')),null===l&&(61===n.charCodeAt(x)?(l="=",x++):(l=null,0===j&&r('"="')),null===l&&(35===n.charCodeAt(x)?(l="#",x++):(l=null,0===j&&r('"#"')),null===l&&(36===n.charCodeAt(x)?(l="$",x++):(l=null,0===j&&r('"$"')),null===l&&(58===n.charCodeAt(x)?(l=":",x++):(l=null,0===j&&r('":"')),null===l&&(47===n.charCodeAt(x)?(l="/",x++):(l=null,0===j&&r('"/"')),null===l&&(92===n.charCodeAt(x)?(l="\\",x++):(l=null,0===j&&r('"\\\\"')),null===l&&(46===n.charCodeAt(x)?(l=".",x++):(l=null,0===j&&r('"."'))))))))),null!==l&&(l=function(l,n){var u={type:"bond",order:null,aromatic:!1,stereoDescriptor:0};switch(n){case".":u.order=0;break;case"-":u.order=1;break;case"=":u.order=2;break;case"#":u.order=3;break;case"$":u.order=4;break;case":":u.aromatic=!0;break;case"/":u.order=1,u.stereoDescriptor=1;break;case"\\":u.order=1,u.stereoDescriptor=-1}return u}(u,l)),null===l&&(x=u),l}function h(){var l,u,t,e,a,o,c,h,A,d;return A=x,d=x,91===n.charCodeAt(x)?(l="[",x++):(l=null,0===j&&r('"["')),null!==l?(u=b(),u=null!==u?u:"",null!==u?("se"===n.substr(x,2)?(t="se",x+=2):(t=null,0===j&&r('"se"')),null===t&&("as"===n.substr(x,2)?(t="as",x+=2):(t=null,0===j&&r('"as"')),null===t&&(t=i(),null===t&&(t=s(),null===t&&(t=g())))),null!==t?(e=f(),e=null!==e?e:"",null!==e?(a=p(),a=null!==a?a:"",null!==a?(o=C(),o=null!==o?o:"",null!==o?(c=v(),c=null!==c?c:"",null!==c?(93===n.charCodeAt(x)?(h="]",x++):(h=null,0===j&&r('"]"')),null!==h?l=[l,u,t,e,a,o,c,h]:(l=null,x=d)):(l=null,x=d)):(l=null,x=d)):(l=null,x=d)):(l=null,x=d)):(l=null,x=d)):(l=null,x=d)):(l=null,x=d),null!==l&&(l=function(l,n,u,r,t,e,a){var u=Array.isArray(u)?u.join(""):u,o="*"!==u&&u.toLowerCase()===u;u=u.charAt(0).toUpperCase()+u.slice(1);var c={type:"atom",symbol:u,isotope:n||null,aromatic:o,chiralClass:r||null,hydrogens:""===t?null:t,charge:""===e?null:e,klass:a||0};return c}(A,l[1],l[2],l[3],l[4],l[5],l[6])),null===l&&(x=A),l}function s(){var l,u,t;return t=x,/^[A-Z]/.test(n.charAt(x))?(l=n.charAt(x),x++):(l=null,0===j&&r("[A-Z]")),null!==l?(/^[a-z]/.test(n.charAt(x))?(u=n.charAt(x),x++):(u=null,0===j&&r("[a-z]")),u=null!==u?u:"",null!==u?l=[l,u]:(l=null,x=t)):(l=null,x=t),l}function A(){var l,u,t;return t=x,66===n.charCodeAt(x)?(l="B",x++):(l=null,0===j&&r('"B"')),null!==l?(114===n.charCodeAt(x)?(u="r",x++):(u=null,0===j&&r('"r"')),u=null!==u?u:"",null!==u?l=[l,u]:(l=null,x=t)):(l=null,x=t),null===l&&(t=x,67===n.charCodeAt(x)?(l="C",x++):(l=null,0===j&&r('"C"')),null!==l?(108===n.charCodeAt(x)?(u="l",x++):(u=null,0===j&&r('"l"')),u=null!==u?u:"",null!==u?l=[l,u]:(l=null,x=t)):(l=null,x=t),null===l&&(78===n.charCodeAt(x)?(l="N",x++):(l=null,0===j&&r('"N"')),null===l&&(79===n.charCodeAt(x)?(l="O",x++):(l=null,0===j&&r('"O"')),null===l&&(80===n.charCodeAt(x)?(l="P",x++):(l=null,0===j&&r('"P"')),null===l&&(83===n.charCodeAt(x)?(l="S",x++):(l=null,0===j&&r('"S"')),null===l&&(70===n.charCodeAt(x)?(l="F",x++):(l=null,0===j&&r('"F"')),null===l&&(73===n.charCodeAt(x)?(l="I",x++):(l=null,0===j&&r('"I"'))))))))),l}function i(){var l;return 98===n.charCodeAt(x)?(l="b",x++):(l=null,0===j&&r('"b"')),null===l&&(99===n.charCodeAt(x)?(l="c",x++):(l=null,0===j&&r('"c"')),null===l&&(110===n.charCodeAt(x)?(l="n",x++):(l=null,0===j&&r('"n"')),null===l&&(111===n.charCodeAt(x)?(l="o",x++):(l=null,0===j&&r('"o"')),null===l&&(112===n.charCodeAt(x)?(l="p",x++):(l=null,0===j&&r('"p"')),null===l&&(115===n.charCodeAt(x)?(l="s",x++):(l=null,0===j&&r('"s"'))))))),l}function d(){var l,u,t,e,a;return e=x,a=x,37===n.charCodeAt(x)?(l="%",x++):(l=null,0===j&&r('"%"')),null!==l?(/^[1-9]/.test(n.charAt(x))?(u=n.charAt(x),x++):(u=null,0===j&&r("[1-9]")),null!==u?(/^[0-9]/.test(n.charAt(x))?(t=n.charAt(x),x++):(t=null,0===j&&r("[0-9]")),null!==t?l=[l,u,t]:(l=null,x=a)):(l=null,x=a)):(l=null,x=a),null===l&&(/^[0-9]/.test(n.charAt(x))?(l=n.charAt(x),x++):(l=null,0===j&&r("[0-9]"))),null!==l&&(l=function(l,n){return n.join&&(n.shift(),n=n.join("")),{type:"ring-closure",index:parseInt(n)}}(e,l)),null===l&&(x=e),l}function f(){var l,u,t,e,a,o,c,h;return a=x,o=x,64===n.charCodeAt(x)?(l="@",x++):(l=null,0===j&&r('"@"')),null!==l?(64===n.charCodeAt(x)?(u="@",x++):(u=null,0===j&&r('"@"')),null===u&&(c=x,"TH"===n.substr(x,2)?(u="TH",x+=2):(u=null,0===j&&r('"TH"')),null!==u?(/^[1-2]/.test(n.charAt(x))?(t=n.charAt(x),x++):(t=null,0===j&&r("[1-2]")),null!==t?u=[u,t]:(u=null,x=c)):(u=null,x=c),null===u&&(c=x,"AL"===n.substr(x,2)?(u="AL",x+=2):(u=null,0===j&&r('"AL"')),null!==u?(/^[1-2]/.test(n.charAt(x))?(t=n.charAt(x),x++):(t=null,0===j&&r("[1-2]")),null!==t?u=[u,t]:(u=null,x=c)):(u=null,x=c),null===u&&(c=x,"SP"===n.substr(x,2)?(u="SP",x+=2):(u=null,0===j&&r('"SP"')),null!==u?(/^[1-3]/.test(n.charAt(x))?(t=n.charAt(x),x++):(t=null,0===j&&r("[1-3]")),null!==t?u=[u,t]:(u=null,x=c)):(u=null,x=c),null===u&&(c=x,"TB"===n.substr(x,2)?(u="TB",x+=2):(u=null,0===j&&r('"TB"')),null!==u?(h=x,49===n.charCodeAt(x)?(t="1",x++):(t=null,0===j&&r('"1"')),null!==t?(/^[0-9]/.test(n.charAt(x))?(e=n.charAt(x),x++):(e=null,0===j&&r("[0-9]")),e=null!==e?e:"",null!==e?t=[t,e]:(t=null,x=h)):(t=null,x=h),null===t&&(h=x,50===n.charCodeAt(x)?(t="2",x++):(t=null,0===j&&r('"2"')),null!==t?(48===n.charCodeAt(x)?(e="0",x++):(e=null,0===j&&r('"0"')),e=null!==e?e:"",null!==e?t=[t,e]:(t=null,x=h)):(t=null,x=h),null===t&&(/^[3-9]/.test(n.charAt(x))?(t=n.charAt(x),x++):(t=null,0===j&&r("[3-9]")))),null!==t?u=[u,t]:(u=null,x=c)):(u=null,x=c),null===u&&(c=x,"OH"===n.substr(x,2)?(u="OH",x+=2):(u=null,0===j&&r('"OH"')),null!==u?(h=x,49===n.charCodeAt(x)?(t="1",x++):(t=null,0===j&&r('"1"')),null!==t?(/^[0-9]/.test(n.charAt(x))?(e=n.charAt(x),x++):(e=null,0===j&&r("[0-9]")),e=null!==e?e:"",null!==e?t=[t,e]:(t=null,x=h)):(t=null,x=h),null===t&&(h=x,50===n.charCodeAt(x)?(t="2",x++):(t=null,0===j&&r('"2"')),null!==t?(/^[0-9]/.test(n.charAt(x))?(e=n.charAt(x),x++):(e=null,0===j&&r("[0-9]")),e=null!==e?e:"",null!==e?t=[t,e]:(t=null,x=h)):(t=null,x=h),null===t&&(h=x,51===n.charCodeAt(x)?(t="3",x++):(t=null,0===j&&r('"3"')),null!==t?(48===n.charCodeAt(x)?(e="0",x++):(e=null,0===j&&r('"0"')),e=null!==e?e:"",null!==e?t=[t,e]:(t=null,x=h)):(t=null,x=h),null===t&&(/^[4-9]/.test(n.charAt(x))?(t=n.charAt(x),x++):(t=null,0===j&&r("[4-9]"))))),null!==t?u=[u,t]:(u=null,x=c)):(u=null,x=c)))))),u=null!==u?u:"",null!==u?l=[l,u]:(l=null,x=o)):(l=null,x=o),l=null!==l?l:"",null!==l&&(l=function(l,n){return n[1]&&n[1].join&&(n[1][1].join&&(n[1][1]=n[1][1].join("")),n[1]=n[1].join("")),n.join&&(n=n.join("")),n}(a,l)),null===l&&(x=a),l}function C(){var l,u,t,e,a,o;return e=x,a=x,45===n.charCodeAt(x)?(l="-",x++):(l=null,0===j&&r('"-"')),null!==l?(45===n.charCodeAt(x)?(u="-",x++):(u=null,0===j&&r('"-"')),null===u&&(48===n.charCodeAt(x)?(u="0",x++):(u=null,0===j&&r('"0"')),null===u&&(o=x,49===n.charCodeAt(x)?(u="1",x++):(u=null,0===j&&r('"1"')),null!==u?(/^[0-5]/.test(n.charAt(x))?(t=n.charAt(x),x++):(t=null,0===j&&r("[0-5]")),t=null!==t?t:"",null!==t?u=[u,t]:(u=null,x=o)):(u=null,x=o),null===u&&(/^[2-9]/.test(n.charAt(x))?(u=n.charAt(x),x++):(u=null,0===j&&r("[2-9]"))))),u=null!==u?u:"",null!==u?l=[l,u]:(l=null,x=a)):(l=null,x=a),null===l&&(a=x,43===n.charCodeAt(x)?(l="+",x++):(l=null,0===j&&r('"+"')),null!==l?(43===n.charCodeAt(x)?(u="+",x++):(u=null,0===j&&r('"+"')),null===u&&(48===n.charCodeAt(x)?(u="0",x++):(u=null,0===j&&r('"0"')),null===u&&(o=x,49===n.charCodeAt(x)?(u="1",x++):(u=null,0===j&&r('"1"')),null!==u?(/^[0-5]/.test(n.charAt(x))?(t=n.charAt(x),x++):(t=null,0===j&&r("[0-5]")),t=null!==t?t:"",null!==t?u=[u,t]:(u=null,x=o)):(u=null,x=o),null===u&&(/^[2-9]/.test(n.charAt(x))?(u=n.charAt(x),x++):(u=null,0===j&&r("[2-9]"))))),u=null!==u?u:"",null!==u?l=[l,u]:(l=null,x=a)):(l=null,x=a)),null!==l&&(l=function(l,n){return n[1]||(n[1]="1"),("+"===n[1]||"-"===n[1])&&(n[1]="2"),n[1].join&&(n[1]=n[1].join("")),n=parseInt(n.join(""))}(e,l)),null===l&&(x=e),l}function p(){var l,u,t,e;return t=x,e=x,72===n.charCodeAt(x)?(l="H",x++):(l=null,0===j&&r('"H"')),null!==l?(/^[0-9]/.test(n.charAt(x))?(u=n.charAt(x),x++):(u=null,0===j&&r("[0-9]")),u=null!==u?u:"",null!==u?l=[l,u]:(l=null,x=e)):(l=null,x=e),null!==l&&(l=function(l,n){return""===n?1:parseInt(n)}(t,l[1])),null===l&&(x=t),l}function v(){var l,u,t,e,a;if(e=x,a=x,58===n.charCodeAt(x)?(l=":",x++):(l=null,0===j&&r('":"')),null!==l){if(/^[0-9]/.test(n.charAt(x))?(t=n.charAt(x),x++):(t=null,0===j&&r("[0-9]")),null!==t)for(u=[];null!==t;)u.push(t),/^[0-9]/.test(n.charAt(x))?(t=n.charAt(x),x++):(t=null,0===j&&r("[0-9]"));else u=null;null!==u?l=[l,u]:(l=null,x=a)}else l=null,x=a;return null!==l&&(l=function(l,n){return parseInt(n.join(""))}(e,l[1])),null===l&&(x=e),l}function b(){var l,u,t,e,a;return e=x,a=x,/^[1-9]/.test(n.charAt(x))?(l=n.charAt(x),x++):(l=null,0===j&&r("[1-9]")),null!==l?(/^[0-9]/.test(n.charAt(x))?(u=n.charAt(x),x++):(u=null,0===j&&r("[0-9]")),u=null!==u?u:"",null!==u?(/^[0-9]/.test(n.charAt(x))?(t=n.charAt(x),x++):(t=null,0===j&&r("[0-9]")),t=null!==t?t:"",null!==t?l=[l,u,t]:(l=null,x=a)):(l=null,x=a)):(l=null,x=a),null!==l&&(l=function(l,n,u,r){return parseInt(n+u+r)}(e,l[0],l[1],l[2])),null===l&&(x=e),l}function g(){var l;return 42===n.charCodeAt(x)?(l="*",x++):(l=null,0===j&&r('"*"')),l}function m(l){l.sort();for(var n=null,u=[],r=0;r<l.length;r++)l[r]!==n&&(u.push(l[r]),n=l[r]);return u}function y(){for(var l=1,u=1,r=!1,t=0;t<Math.max(x,I);t++){var e=n.charAt(t);"\n"===e?(r||l++,u=1,r=!1):"\r"===e||"\u2028"===e||"\u2029"===e?(l++,u=1,r=!0):(u++,r=!1)}return{line:l,column:u}}var S={SMILES:t,Chain:e,Branch:a,Atom:o,Bond:c,AtomSpec:h,ElementSymbol:s,OrganicSymbol:A,AromaticSymbol:i,RingClosure:d,ChiralClass:f,Charge:C,HCount:p,Class:v,Isotope:b,WILDCARD:g};if(void 0!==u){if(void 0===S[u])throw new Error("Invalid rule name: "+l(u)+".")}else u="SMILES";var x=0,j=0,I=0,k=[],E=S[u]();if(null===E||x!==n.length){var H=Math.max(x,I),w=H<n.length?n.charAt(H):null,B=y();throw new this.SyntaxError(m(k),w,H,B.line,B.column)}return E},toSource:function(){return this._source}};return n.SyntaxError=function(n,u,r,t,e){function a(n,u){var r,t;switch(n.length){case 0:r="end of input";break;case 1:r=n[0];break;default:r=n.slice(0,n.length-1).join(", ")+" or "+n[n.length-1]}return t=u?l(u):"end of input","Expected "+r+" but "+t+" found."}this.name="SyntaxError",this.expected=n,this.found=u,this.message=a(n,u),this.offset=r,this.line=t,this.column=e},n.SyntaxError.prototype=Error.prototype,n}(),"undefined"!=typeof module&&(module.exports=Parser);