(function(root) {
  'use strict';

  function intentUtteranceExpand(phrase) {
    const expandSlotRegex = /\(.*\|.*\)/gi;
    const expandSlotWordRegex = /([^||()]+)/gi;

    function expand(phrase) {
      if (typeof phrase !== 'string') {
        return [];
      }

      const parts = phrase.match(/\{\(.*?\)\}+|\{.*?\}+|\(.*?\)+|[^[\s]+/gi);
      const phrases = [];

      if (Array.isArray(parts)) {
        for (var i = 0; i < parts.length; i++) {
          expandSlotRegex.lastIndex = 0;
          const part = parts[i];

          if (expandSlotRegex.test(part)) {

            if (/^\{.*\}$/.test(part)) {
              var words = part.match(/\{\((.*)\).*\|.*\}/i);
              if (Array.isArray(words) && words[1]) {
                words = words[1].split('|');

                for (var j = 0; j < words.length; j++) {
                  const slot = part.replace(/\(.*\)/i, words[j]);
                  const copy = parts.slice(0);

                  copy.splice(i, 1, slot);
                  phrases.push(copy);
                }
              }
            } else {
              const words = part.match(/([^||()]+)/gi);

              for (var j = 0; j < words.length; j++) {
                const word = words[j];
                var copy = parts.slice(0);

                copy.splice(i, 1, word);
                phrases.push(copy);

                // remove word, ie. (|foo)
                if (words.length === 1) {
                  copy = parts.slice(0);
                  copy.splice(i, 1);
                  phrases.push(copy);
                }
              }
            }

            break;
          }
        }

        if (!phrases.length) {
          return [phrase];
        }

        const joinedPhrases = phrases.map(function(p) {
          return p.join(' ');
        });

        return joinedPhrases.reduce(function(acc, p, i) {
          expandSlotRegex.lastIndex = 0;
          if (expandSlotRegex.test(p)) {
            acc[i] = expand(p);
          }

          return acc;
        }, joinedPhrases).reduce(function(a, b) {
          return a.concat(b);
        }, []);
      } else {
        return [phrase];
      }
    }

    return expand(phrase);
  }

  if (typeof exports !== 'undefined') {
    if (typeof module !== 'undefined' && module.exports) {
      exports = module.exports = intentUtteranceExpand;
    }
    exports.intentUtteranceExpand = intentUtteranceExpand;
  } else if (typeof define === 'function' && define.amd) {
    define([], function() {
      return intentUtteranceExpand;
    });
  } else {
    root.intentUtteranceExpand = intentUtteranceExpand;
  }

})(this);

@@ -85,87 +85,347 @@
 nst 
-expandSlotRegex = /%5C(.*%5C%7C.*%5C)/gi;%0A    const expandSlotWordRegex = /(%5B%5E%7C%7C()%5D+)/g
+phrasePartsRegex = /%5C%7B%5C(.*?%5C)%5C%7D+%7C%5C%7B.*?%5C%7D+%7C%5C(.*?%5C)+%7C%5B%5E%5B%5Cs%5D+/gi;%0A    const slotRegex = /%5E%5C%7B.*%5C%7D$/i;%0A    const expandSlotRegex = /%5C(.*%5C%7C.*%5C)/gi;%0A    const expandSlotWordRegex = /(%5B%5E%7C%7C()%5D+)/gi;%0A    const wordsInsideExpandSlotRegex = /(%5B%5E%7C%7C()%5D+)/gi;%0A    const wordsInsideSlotRegex = /%5C%7B%5C((.*)%5C).*%5C%7C.*%5C%7D/i;%0A    const insideParensRegex = /%5C(.*%5C)/
 i;%0A%0A
@@ -532,77 +532,89 @@
     
-const parts = phrase.match(/%5C%7B%5C(.*?%5C)%5C%7D+%7C%5C%7B.*?%5C%7D+%7C%5C(.*?%5C)+%7C%5B%5E%5B%5Cs%5D+/gi
+phrasePartsRegex.lastIndex = 0;%0A      const parts = phrase.match(phrasePartsRegex
 );%0A 
@@ -755,32 +755,67 @@
 .lastIndex = 0;%0A
+          slotRegex.lastIndex = 0;%0A
           const 
@@ -893,26 +893,25 @@
     if (
-/%5E%5C%7B.*%5C%7D$/
+slotRegex
 .test(pa
@@ -935,17 +935,74 @@
     
-var
+wordsInsideSlotRegex.lastIndex = 0;%0A              const
  words
+Match
  = p
@@ -1015,32 +1015,32 @@
 tch(
-/%5C%7B%5C((.*)%5C).*%5C%7C.*%5C%7D/i
+wordsInsideSlotRegex
 );%0A
+%0A
     
@@ -1072,16 +1072,21 @@
 ay(words
+Match
 ) && wor
@@ -1087,16 +1087,21 @@
 && words
+Match
 %5B1%5D) %7B%0A 
@@ -1111,24 +1111,30 @@
             
+const 
 words = word
@@ -1134,16 +1134,21 @@
  = words
+Match
 %5B1%5D.spli
@@ -1205,32 +1205,83 @@
 .length; j++) %7B%0A
+                  insideParensRegex.lastIndex = 0;%0A
                 
@@ -1308,25 +1308,33 @@
 replace(
-/%5C(.*%5C)/i
+insideParensRegex
 , words%5B
@@ -1540,47 +1540,115 @@
     
-const words = part.match(/(%5B%5E%7C%7C()%5D+)/gi
+wordsInsideExpandSlotRegex.lastIndex = 0;%0A              const words = part.match(wordsInsideExpandSlotRegex
 );%0A%0A

move regex to vars