CoolFace
Datasetpublic

basant307/AI_Governance_Project

sourceHugging Faceapache-2.0updated 2mo agoView on Hugging Face
0likes48downloads
parse.mjs255 linesDownload Raw Back to selector
1import { warn } from '../util/index.mjs';2import * as is from '../is.mjs';3import exprs from './expressions.mjs';4import newQuery from './new-query.mjs';5import Type from './type.mjs';6 7/**8 * Of all the expressions, find the first match in the remaining text.9 * @param {string} remaining The remaining text to parse10 * @returns The matched expression and the newly remaining text `{ expr, match, name, remaining }`11 */12const consumeExpr = ( remaining ) => {13  let expr;14  let match;15  let name;16 17  for( let j = 0; j < exprs.length; j++ ){18    let e = exprs[ j ];19    let n = e.name;20 21    let m = remaining.match( e.regexObj );22 23    if( m != null ){24      match = m;25      expr = e;26      name = n;27 28      let consumed = m[0];29      remaining = remaining.substring( consumed.length );30 31      break; // we've consumed one expr, so we can return now32    }33  }34 35  return {36    expr: expr,37    match: match,38    name: name,39    remaining: remaining40  };41};42 43 44/**45 * Consume all the leading whitespace46 * @param {string} remaining The text to consume47 * @returns The text with the leading whitespace removed48 */49const consumeWhitespace = ( remaining ) => {50  let match = remaining.match( /^\s+/ );51 52  if( match ){53    let consumed = match[0];54    remaining = remaining.substring( consumed.length );55  }56 57  return remaining;58};59 60/**61 * Parse the string and store the parsed representation in the Selector.62 * @param {string} selector The selector string63 * @returns `true` if the selector was successfully parsed, `false` otherwise64 */65const parse = function( selector ){66  let self = this;67 68  let remaining = self.inputText = selector;69 70  let currentQuery = self[0] = newQuery();71  self.length = 1;72 73  remaining = consumeWhitespace( remaining ); // get rid of leading whitespace74 75  for( ;; ){76    let exprInfo = consumeExpr( remaining );77 78    if( exprInfo.expr == null ){79      warn( 'The selector `' + selector + '`is invalid' );80      return false;81    } else {82      let args = exprInfo.match.slice( 1 );83 84      // let the token populate the selector object in currentQuery85      let ret = exprInfo.expr.populate( self, currentQuery, args );86 87      if( ret === false ){88        return false; // exit if population failed89      } else if( ret != null ){90        currentQuery = ret; // change the current query to be filled if the expr specifies91      }92    }93 94    remaining = exprInfo.remaining;95 96    // we're done when there's nothing left to parse97    if( remaining.match( /^\s*$/ ) ){98      break;99    }100  }101 102  let lastQ = self[self.length - 1];103 104  if( self.currentSubject != null ){105    lastQ.subject = self.currentSubject;106  }107 108  lastQ.edgeCount = self.edgeCount;109  lastQ.compoundCount = self.compoundCount;110 111  for( let i = 0; i < self.length; i++ ){112    let q = self[i];113 114    // in future, this could potentially be allowed if there were operator precedence and detection of invalid combinations115    if( q.compoundCount > 0 && q.edgeCount > 0 ){116      warn( 'The selector `' + selector + '` is invalid because it uses both a compound selector and an edge selector' );117      return false;118    }119 120    if( q.edgeCount > 1 ){121      warn( 'The selector `' + selector + '` is invalid because it uses multiple edge selectors' );122      return false;123    } else if( q.edgeCount === 1 ){124      warn( 'The selector `' + selector + '` is deprecated.  Edge selectors do not take effect on changes to source and target nodes after an edge is added, for performance reasons.  Use a class or data selector on edges instead, updating the class or data of an edge when your app detects a change in source or target nodes.' );125    }126  }127 128  return true; // success129};130 131/**132 * Get the selector represented as a string.  This value uses default formatting,133 * so things like spacing may differ from the input text passed to the constructor.134 * @returns {string} The selector string135 */136export const toString = function(){137  if( this.toStringCache != null ){138    return this.toStringCache;139  }140 141  let clean = function( obj ){142    if( obj == null ){143      return '';144    } else {145      return obj;146    }147  };148 149  let cleanVal = function( val ){150    if( is.string( val ) ){151      return '"' + val + '"';152    } else {153      return clean( val );154    }155  };156 157  let space = ( val ) => {158    return ' ' + val + ' ';159  };160 161  let checkToString = ( check, subject ) => {162    let { type, value } = check;163 164    switch( type ){165      case Type.GROUP: {166        let group = clean( value );167 168        return group.substring( 0, group.length - 1 );169      }170 171      case Type.DATA_COMPARE: {172        let { field, operator } = check;173 174        return '[' + field + space( clean( operator ) ) + cleanVal( value ) + ']';175      }176 177      case Type.DATA_BOOL: {178        let { operator, field } = check;179 180        return '[' + clean( operator ) + field + ']';181      }182 183      case Type.DATA_EXIST: {184        let { field } = check;185 186        return '[' + field + ']';187      }188 189      case Type.META_COMPARE: {190        let { operator, field } = check;191 192        return '[[' + field + space( clean( operator ) ) + cleanVal( value ) + ']]';193      }194 195      case Type.STATE: {196        return value;197      }198 199      case Type.ID: {200        return '#' + value;201      }202 203      case Type.CLASS: {204        return '.' + value;205      }206 207      case Type.PARENT:208      case Type.CHILD: {209        return queryToString(check.parent, subject) + space('>') + queryToString(check.child, subject);210      }211 212      case Type.ANCESTOR:213      case Type.DESCENDANT: {214        return queryToString(check.ancestor, subject) + ' ' + queryToString(check.descendant, subject);215      }216 217      case Type.COMPOUND_SPLIT: {218        let lhs = queryToString(check.left, subject);219        let sub = queryToString(check.subject, subject);220        let rhs = queryToString(check.right, subject);221 222        return lhs + (lhs.length > 0 ? ' ' : '') + sub + rhs;223      }224 225      case Type.TRUE: {226        return '';227      }228    }229  };230 231  let queryToString = ( query, subject ) => {232    return query.checks.reduce((str, chk, i) => {233      return str + (subject === query && i === 0 ? '$' : '') + checkToString(chk, subject);234    }, '');235  };236 237  let str = '';238 239  for( let i = 0; i < this.length; i++ ){240    let query = this[ i ];241 242    str += queryToString( query, query.subject );243 244    if( this.length > 1 && i < this.length - 1 ){245      str += ', ';246    }247  }248 249  this.toStringCache = str;250 251  return str;252};253 254export default { parse, toString };255 
basant307/AI_Governance_Project · CoolFace