Skip to content

Instantly share code, notes, and snippets.

@rikschennink
Last active January 12, 2017 07:35
Show Gist options
  • Save rikschennink/ea453f9050aeb8e060ebf93dfade26f6 to your computer and use it in GitHub Desktop.
Save rikschennink/ea453f9050aeb8e060ebf93dfade26f6 to your computer and use it in GitHub Desktop.
Parsing strings with JavaScript
const arrow = (str, i) => str[i] === '-' && str[i+1] === '>';
const string = (c) => c === "'" || c === '"';
const comma = (c) => c === ',';
const opener = (c) => c === '(';
const closer = (c) => c === ')';
const parse = (i, str, result) => {
let value = '';
let quote = null;
while (i < str.length) {
// character reference
let c = str[i];
// enter level
if (opener(c)) {
let fn = [value.trim()];
i = parse(i + 1, str, fn);
result.push(fn);
value = '';
}
// exit level
else if (closer(c)) {
if (value.trim().length) {
result.push(value.trim());
}
return i+1;
}
// function names or arguments
else {
// we're in a string
// as long as the exit has not been found add to value
if (quote !== null && c !== quote) {
// accept any value
value += c;
}
// we've found the string exit
else if (c === quote) {
quote = null;
}
// we're not in a string and we found a string opener
else if (string(c)) {
quote = c;
}
// we're not in a string
else {
// we've found an arrow
if (arrow(str, i)) {
// we might have finished a function without parenthesis
if (value.trim().length) {
result.push([value.trim()]);
value = '';
}
// skip two additional characters because arrow is of length 2
i+=2;
}
// we've reached an argument separator
else if (comma(c)) {
// push value
if (value.trim().length) {
result.push(value.trim());
}
value = '';
}
else {
value += c;
}
}
// next character
i++;
}
}
if (value.trim().length) {
result.push([value.trim()]);
}
return i;
};
export const parseTransformChain = string => {
let result = [];
parse(0, string, result);
return result;
};
"foo"
// [["foo"]]
"foo -> bar"
// [ ["foo"], ["bar"] ]
"foo(a, b)"
// [ ["foo", "a", "b"], ["bar"] ]
"foo(a, 'a, b')"
// [ ["foo", "a", "a, b"] ]
"foo -> bar(baz(a, b))"
// [ ["foo"], ["bar", ["baz", "a", "b"] ] ]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment