Skip to content

Instantly share code, notes, and snippets.

@adamabernathy
Last active January 10, 2018 17:15
Show Gist options
  • Save adamabernathy/fb6f10bd046839cad933248385551eec to your computer and use it in GitHub Desktop.
Save adamabernathy/fb6f10bd046839cad933248385551eec to your computer and use it in GitHub Desktop.
Parse string with "parameter:value" style search syntax to object.
/**
* Parse string with `parameter:value` style search syntax to object.
*
* Examples:
* state:ut --> {state: ['ut']}
* state:ut,az,id --> {state: ['ut', 'az', 'id]}
* complete --> {complete: 1} // defaults to value of 1
* {air_temp > 10} --> {filter_on: '(air_temp > 10)'} // explicit statement
*
* @param {string} blob, query
* @returns {object}, Mesonet API formatted query parameters
*
* (C) 2018 Adam C. Abernathy, [email protected]. Licence MIT
* https://gist.github.com/adamabernathy/fb6f10bd046839cad933248385551eec
*/
const parseQueryStatement = blob => {
if (typeof blob === 'undefined' || blob === null || blob === '') return null;
const ast = {};
blob = blob.toLowerCase();
// Need to seperate any filter expressions from parameter tokens
if (blob.indexOf('{') !== -1 && blob.indexOf('}' !== -1)) {
const filterStartPos = blob.indexOf('{');
const filterStopPos = blob.indexOf('}');
ast.filter_on = `(${blob.slice(filterStartPos + 1, filterStopPos)})`;
blob = `${blob.slice(0, filterStartPos)}${blob.slice(filterStopPos + 1)}`.trim();
}
// Parse out the tokens assuming there will be escaped strings
// The idea here is to keep track of if we are inside an escaped string or not
const statements = blob.match(/\\?.|^$/g).reduce(
(tokens, lex) => {
if (lex === '"') {
tokens.quote ^= 1; // XOR inside quote is true
} else if (!tokens.quote && lex === ' ') {
tokens.expression.push('');
} else {
// put the string together to comprise the expression
tokens.expression[tokens.expression.length - 1] += lex.replace(/\\(.)/, '$1');
}
return tokens;
},
{ expression: [''] },
).expression;
for (let i = 0, l = statements.length; i < l; i++) {
if (statements[i] !== '') {
const token = statements[i].split(':');
token[1] = token[1] || 1;
ast[token[0]] = typeof token[1] === 'string' ? token[1].split(',') : token[1];
}
}
return ast;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment