forked from enviPath/enviPy
Current Dev State
This commit is contained in:
438
static/js/ketcher2/node_modules/varstream/src/VarStreamReader.js
generated
vendored
Executable file
438
static/js/ketcher2/node_modules/varstream/src/VarStreamReader.js
generated
vendored
Executable file
@ -0,0 +1,438 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Nicolas Froidure
|
||||
*
|
||||
* This file is free software;
|
||||
* you can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License (GPL) as published by the Free Software
|
||||
* Foundation, in version 3. It is distributed in the
|
||||
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
|
||||
*
|
||||
*/
|
||||
|
||||
// AMD + global + NodeJS : You can use this object by inserting a script
|
||||
// or using an AMD loader (like RequireJS) or using NodeJS
|
||||
(function(root,define){ define([], function() {
|
||||
'use strict';
|
||||
// START: Module logic start
|
||||
|
||||
// Constructor
|
||||
function VarStreamReader (scope, prop, options) {
|
||||
// Keep a ref to the root scope
|
||||
this.rootScope={root: scope, prop: prop};
|
||||
// Save the options
|
||||
this.options=options;
|
||||
// Store current scopes for backward references
|
||||
this.previousNodes=[];
|
||||
// The parse state
|
||||
this.state=PARSE_NEWLINE;
|
||||
// The current values
|
||||
this.leftValue='';
|
||||
this.rightValue='';
|
||||
this.operator='';
|
||||
this.escaped=ESC_NONE;
|
||||
}
|
||||
|
||||
// Static consts
|
||||
VarStreamReader.STRICT_MODE=1;
|
||||
VarStreamReader.OPTIONS=VarStreamReader.STRICT_MODE;
|
||||
|
||||
// Constants
|
||||
// Chars
|
||||
var CHR_ENDL = '\n'
|
||||
, CHR_CR = '\r'
|
||||
, CHR_SEP = '.'
|
||||
, CHR_BCK = '^'
|
||||
, CHR_EQ = '='
|
||||
, CHR_ESC = '\\'
|
||||
, CHR_PLU = '+'
|
||||
, CHR_MIN = '-'
|
||||
, CHR_MUL = '*'
|
||||
, CHR_DIV = '/'
|
||||
, CHR_MOD = '%'
|
||||
, CHR_REF = '&'
|
||||
, CHR_NEW = '!'
|
||||
, CHR_COM = '#'
|
||||
// Chars sets
|
||||
, EQ_OPS = [CHR_PLU,CHR_MIN,CHR_MUL,CHR_DIV,CHR_MOD,CHR_REF]
|
||||
, ARRAY_OPS = [CHR_PLU,CHR_MUL,CHR_NEW]
|
||||
, ARRAY_NODE_CHARS = /^[0-9]+$/
|
||||
, PROP_NODE_CHARS = /^[a-zA-Z0-9_]+$/
|
||||
, BCK_CHARS = /^\^[0-9]*$/
|
||||
// Parsing status
|
||||
, PARSE_NEWLINE = 1
|
||||
, PARSE_LVAL = 2
|
||||
, PARSE_OPERATOR = 3
|
||||
, PARSE_RVAL = 4
|
||||
, PARSE_MLSTRING = 5
|
||||
, PARSE_COMMENT = 6
|
||||
, PARSE_SILENT = 7
|
||||
// Escape status
|
||||
, ESC_NONE = 0
|
||||
, ESC_LF = 1
|
||||
, ESC_ALL = 3
|
||||
;
|
||||
|
||||
VarStreamReader.prototype.resolveScope = function (val) {
|
||||
var nodes = val.split(CHR_SEP)
|
||||
, scope = this.rootScope
|
||||
, n = 0
|
||||
;
|
||||
|
||||
// Looking for backward refs in the first node
|
||||
if(nodes[0] && nodes[0][0] == CHR_BCK) {
|
||||
// if no numbers adding every previous nodes
|
||||
if(nodes[0] == CHR_BCK) {
|
||||
n = this.previousNodes.length ? this.previousNodes.length - 1 : 0;
|
||||
// if numbers
|
||||
} else {
|
||||
// check it
|
||||
if(!BCK_CHARS.test(nodes[0])) {
|
||||
if(this.options&VarStreamReader.STRICT_MODE) {
|
||||
throw new Error('Malformed backward reference.');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
n = parseInt(nodes[0].substring(1), 10);
|
||||
}
|
||||
if(n > this.previousNodes.length) {
|
||||
if(this.options&VarStreamReader.STRICT_MODE) {
|
||||
throw new SyntaxError('Backward reference index is greater than the'
|
||||
+ ' previous node max index.');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
this.previousNodes.length = n;
|
||||
nodes.shift();
|
||||
nodes.unshift.apply(nodes,this.previousNodes);
|
||||
}
|
||||
|
||||
// Looping throught each nodes
|
||||
for(var i=0, j=nodes.length; i<j; i++) {
|
||||
// Checking if the node is not empty
|
||||
if(''===nodes[i]) {
|
||||
if(this.options&VarStreamReader.STRICT_MODE) {
|
||||
throw new Error('The leftValue can\'t have empty nodes ('+val+').');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
// Array operators
|
||||
if(-1!==ARRAY_OPS.indexOf(nodes[i])||ARRAY_NODE_CHARS.test(nodes[i])) {
|
||||
// Ensure the scope is an array
|
||||
if('undefined'=== typeof scope.root[scope.prop]
|
||||
||!(scope.root[scope.prop] instanceof Array)) {
|
||||
scope.root[scope.prop]=[];
|
||||
}
|
||||
if(nodes[i]===CHR_PLU) {
|
||||
nodes[i]=scope.root[scope.prop].length;
|
||||
}
|
||||
if(nodes[i]===CHR_MUL) {
|
||||
nodes[i]=scope.root[scope.prop].length-1;
|
||||
}
|
||||
if(nodes[i]===CHR_NEW) {
|
||||
nodes[i]=scope.root[scope.prop].length=0;
|
||||
}
|
||||
} else {
|
||||
// Checking node chars
|
||||
if(!PROP_NODE_CHARS.test(nodes[i])) {
|
||||
if(this.options&VarStreamReader.STRICT_MODE) {
|
||||
throw new SyntaxError('Illegal chars found in a the node'
|
||||
+ ' "'+nodes[i]+'".');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
// Ensure the scope is an object
|
||||
if('undefined'=== typeof scope.root[scope.prop]
|
||||
||!(scope.root[scope.prop] instanceof Object)) {
|
||||
scope.root[scope.prop]={};
|
||||
}
|
||||
}
|
||||
// Resolving the node scope
|
||||
scope={
|
||||
root : scope.root[scope.prop],
|
||||
prop : nodes[i]
|
||||
};
|
||||
}
|
||||
|
||||
// Keep previous nodes for backwards references
|
||||
this.previousNodes = nodes;
|
||||
|
||||
return scope;
|
||||
};
|
||||
|
||||
VarStreamReader.prototype.read = function (chunk) {
|
||||
// Looping throught chunk chars
|
||||
for(var i=0, j=chunk.length; i<j; i++) {
|
||||
// detect escaped chars
|
||||
if(chunk[i]===CHR_ESC && (
|
||||
this.state===PARSE_RVAL
|
||||
||this.state===PARSE_SILENT
|
||||
||this.state===PARSE_MLSTRING
|
||||
)
|
||||
) {
|
||||
if(this.escaped) {
|
||||
this.escaped=ESC_NONE;
|
||||
} else {
|
||||
this.escaped=ESC_ALL;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// parsing chars according to the current state
|
||||
switch(this.state) {
|
||||
// Continue while newlines
|
||||
case PARSE_NEWLINE:
|
||||
this.escaped=ESC_NONE;
|
||||
this.operator='';
|
||||
this.leftValue='';
|
||||
this.rightValue='';
|
||||
if(chunk[i]===CHR_ENDL||chunk[i]===CHR_CR) {
|
||||
continue;
|
||||
}
|
||||
// Read left value content
|
||||
case PARSE_LVAL:
|
||||
// Detect comments
|
||||
if(chunk[i]===CHR_COM) {
|
||||
this.state=PARSE_COMMENT;
|
||||
continue;
|
||||
}
|
||||
// Detect special operators
|
||||
if(this.leftValue.lastIndexOf(CHR_SEP)!=this.leftValue.length-1
|
||||
&&-1!==EQ_OPS.indexOf(chunk[i])) {
|
||||
this.state=PARSE_OPERATOR;
|
||||
this.operator=chunk[i];
|
||||
continue;
|
||||
}
|
||||
// Detect the = operator
|
||||
if(CHR_EQ===chunk[i]) {
|
||||
this.state=PARSE_RVAL;
|
||||
this.operator=chunk[i];
|
||||
continue;
|
||||
}
|
||||
// Fail if a new line is found
|
||||
if(chunk[i]===CHR_ENDL||chunk[i]===CHR_CR) {
|
||||
if(this.options&VarStreamReader.STRICT_MODE) {
|
||||
throw SyntaxError('Unexpected new line found while parsing '
|
||||
+' a leftValue.');
|
||||
}
|
||||
this.state=PARSE_NEWLINE;
|
||||
continue;
|
||||
}
|
||||
// Store LVAL chars
|
||||
this.state=PARSE_LVAL;
|
||||
this.leftValue+=chunk[i];
|
||||
continue;
|
||||
// Read right value content
|
||||
case PARSE_RVAL:
|
||||
// Left value should not be empty
|
||||
if(''===this.leftValue) {
|
||||
if(this.options&VarStreamReader.STRICT_MODE) {
|
||||
throw SyntaxError('Found an empty leftValue.');
|
||||
}
|
||||
this.state=PARSE_SILENT;
|
||||
}
|
||||
// Stop if a new line is found
|
||||
if(chunk[i]===CHR_ENDL||chunk[i]===CHR_CR) {
|
||||
// rightValue can be empty only with the = operator
|
||||
// or if the string is multiline
|
||||
if(this.operator!=CHR_EQ&&''===this.rightValue
|
||||
&&this.escaped===ESC_NONE) {
|
||||
if(this.options&VarStreamReader.STRICT_MODE) {
|
||||
throw SyntaxError('Found an empty rightValue.');
|
||||
}
|
||||
this.state=PARSE_NEWLINE;
|
||||
continue;
|
||||
}
|
||||
// Compute rval
|
||||
// if it's a ref
|
||||
if(this.operator===CHR_REF) {
|
||||
this.rightValue=this.resolveScope(this.rightValue);
|
||||
} else if('null'===this.rightValue) {
|
||||
this.rightValue=null;
|
||||
// Booleans
|
||||
} else if('true'===this.rightValue) {
|
||||
this.rightValue=true;
|
||||
} else if('false'===this.rightValue) {
|
||||
this.rightValue=false;
|
||||
// Numbers
|
||||
} else if('NaN'===this.rightValue) {
|
||||
this.rightValue=NaN;
|
||||
} else if(/^\-?([0-9]+(\.[0-9]+)?|Infinity)$/
|
||||
.test(this.rightValue)) {
|
||||
this.rightValue=Number(this.rightValue);
|
||||
}
|
||||
// Compute lval
|
||||
this.leftValue=this.resolveScope(this.leftValue);
|
||||
// set rval in lval (with operators)
|
||||
if(null!==this.leftValue) {
|
||||
switch(this.operator) {
|
||||
case CHR_REF:
|
||||
this.leftValue.root[this.leftValue.prop] = this.rightValue ?
|
||||
this.rightValue.root[this.rightValue.prop] :
|
||||
null;
|
||||
break;
|
||||
case CHR_EQ:
|
||||
if(this.rightValue!=='' || 'string' ===
|
||||
typeof this.leftValue.root[this.leftValue.prop]) {
|
||||
this.leftValue.root[this.leftValue.prop]=this.rightValue;
|
||||
} else {
|
||||
delete this.leftValue.root[this.leftValue.prop];
|
||||
}
|
||||
break;
|
||||
case CHR_PLU:
|
||||
this.leftValue.root[this.leftValue.prop] +=
|
||||
null === this.rightValue ? NaN : this.rightValue;
|
||||
break;
|
||||
case CHR_MIN:
|
||||
this.leftValue.root[this.leftValue.prop] -=
|
||||
null === this.rightValue ? NaN : this.rightValue;
|
||||
break;
|
||||
case CHR_MUL:
|
||||
this.leftValue.root[this.leftValue.prop] *=
|
||||
null === this.rightValue ? NaN : this.rightValue;
|
||||
break;
|
||||
case CHR_DIV:
|
||||
this.leftValue.root[this.leftValue.prop] /=
|
||||
null === this.rightValue ? NaN : this.rightValue;
|
||||
break;
|
||||
case CHR_MOD:
|
||||
this.leftValue.root[this.leftValue.prop] %=
|
||||
null === this.rightValue ? NaN : this.rightValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// if the newline was escaped, continue to read the string
|
||||
if(this.escaped) {
|
||||
if(chunk[i]===CHR_CR) {
|
||||
this.escaped=ESC_LF;
|
||||
} else {
|
||||
this.escaped=ESC_NONE;
|
||||
}
|
||||
if(null!==this.leftValue) {
|
||||
this.state=PARSE_MLSTRING;
|
||||
this.leftValue.root[this.leftValue.prop]+=chunk[i];
|
||||
} else {
|
||||
this.state=PARSE_SILENT;
|
||||
}
|
||||
} else {
|
||||
this.state=PARSE_NEWLINE;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// Store RVAL chars
|
||||
if(this.escaped) {
|
||||
if(this.escaped==ESC_ALL) {
|
||||
if(this.options&VarStreamReader.STRICT_MODE) {
|
||||
throw Error('Found an escape char but there was nothing to escape.');
|
||||
}
|
||||
this.rightValue+='\\';
|
||||
}
|
||||
this.escaped=ESC_NONE;
|
||||
}
|
||||
this.rightValue+=chunk[i];
|
||||
continue;
|
||||
// Parse the content of a multiline value
|
||||
case PARSE_MLSTRING:
|
||||
if(this.escaped) {
|
||||
if(this.escaped===ESC_ALL&&chunk[i]===CHR_CR) {
|
||||
this.escaped=ESC_LF;
|
||||
} else if(chunk[i]===CHR_ENDL) {
|
||||
this.escaped=ESC_NONE;
|
||||
} else {
|
||||
if(this.escaped===ESC_LF) {
|
||||
if(this.options&VarStreamReader.STRICT_MODE) {
|
||||
throw new SyntaxError('Assuming a LF after an escaped CR, '
|
||||
+chunk[i]+' found instead.');
|
||||
}
|
||||
} else {
|
||||
if(this.options&VarStreamReader.STRICT_MODE) {
|
||||
throw new SyntaxError('Found an escape char but there was'
|
||||
+ ' nothing to escape.');
|
||||
}
|
||||
this.leftValue.root[this.leftValue.prop]+='\\';
|
||||
}
|
||||
this.escaped=ESC_NONE;
|
||||
}
|
||||
} else if(chunk[i]===CHR_ENDL||chunk[i]===CHR_CR) {
|
||||
this.state=PARSE_NEWLINE;
|
||||
continue;
|
||||
}
|
||||
// Store RVAL chars
|
||||
this.leftValue.root[this.leftValue.prop]+=chunk[i];
|
||||
continue;
|
||||
// Finding the = char after an operator
|
||||
case PARSE_OPERATOR:
|
||||
if(chunk[i]===CHR_EQ) {
|
||||
this.state=PARSE_RVAL;
|
||||
continue;
|
||||
}
|
||||
if(this.options&VarStreamReader.STRICT_MODE) {
|
||||
throw new SyntaxError('Unexpected char after the'
|
||||
+ ' "'+this.operator+'" operator. Expected "="'
|
||||
+ ' found "'+chunk[i]+'".');
|
||||
}
|
||||
if(chunk[i]===CHR_ENDL || chunk[i]===CHR_CR) {
|
||||
this.state=PARSE_NEWLINE;
|
||||
} else {
|
||||
this.state=PARSE_SILENT;
|
||||
}
|
||||
continue;
|
||||
// Parsing a comment content
|
||||
case PARSE_COMMENT:
|
||||
if((chunk[i]===CHR_ENDL&&!(this.escaped&ESC_LF))
|
||||
||(chunk[i]===CHR_CR&&!(this.escaped&ESC_ALL))) {
|
||||
this.state=PARSE_NEWLINE;
|
||||
continue;
|
||||
}
|
||||
if(chunk[i]===CHR_CR&&(this.escaped&ESC_ALL)) {
|
||||
this.escaped=ESC_LF;
|
||||
}
|
||||
if(chunk[i]===CHR_ENDL&&(this.escaped&ESC_LF)) {
|
||||
this.escaped=ESC_NONE;
|
||||
}
|
||||
continue;
|
||||
// Something was wrong, waiting for a newline to continue parsing
|
||||
case PARSE_SILENT:
|
||||
if((chunk[i]===CHR_ENDL&&!(this.escaped&ESC_LF))
|
||||
||(chunk[i]===CHR_CR&&!(this.escaped&ESC_ALL))) {
|
||||
this.state=PARSE_NEWLINE;
|
||||
continue;
|
||||
}
|
||||
if(chunk[i]===CHR_CR&&(this.escaped&ESC_ALL)) {
|
||||
this.escaped=ESC_LF;
|
||||
}
|
||||
if(chunk[i]===CHR_ENDL&&(this.escaped&ESC_LF)) {
|
||||
this.escaped=ESC_NONE;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// END: Module logic end
|
||||
|
||||
return VarStreamReader;
|
||||
|
||||
});})(this,typeof define === 'function' && define.amd ?
|
||||
// AMD
|
||||
define :
|
||||
// NodeJS
|
||||
(typeof exports === 'object'?function (name, deps, factory) {
|
||||
var root=this;
|
||||
if(typeof name === 'object') {
|
||||
factory=deps; deps=name;
|
||||
}
|
||||
module.exports=factory.apply(this, deps.map(function(dep){
|
||||
return require(dep);
|
||||
}));
|
||||
}:
|
||||
// Global
|
||||
function (name, deps, factory) {
|
||||
var root=this;
|
||||
if(typeof name === 'object') {
|
||||
factory=deps; deps=name;
|
||||
}
|
||||
this.VarStreamReader=factory.apply(this, deps.map(function(dep){
|
||||
return root[dep.substring(dep.lastIndexOf('/')+1)];
|
||||
}));
|
||||
}.bind(this)
|
||||
)
|
||||
);
|
||||
Reference in New Issue
Block a user