void HighlightStateBuilder::build(StringListLangElem *elem,
        HighlightState *state) {
    const string &name = elem->getName();

    StringDefs *alternatives = elem->getAlternatives();
    WordList wordList;

    bool doubleQuoted = false, nonDoubleQuoted = false, buildAsWordList = true;

    for (StringDefs::const_iterator it = alternatives->begin(); it
            != alternatives->end(); ++it) {
        const string &rep = (*it)->toString();

        // double quoted strings generate WordListRules, otherwise simple ListRules

        // we don't allow double quoted strings mixed with non double quoted
        if (((*it)->isDoubleQuoted() && nonDoubleQuoted)
                || (!(*it)->isDoubleQuoted() && doubleQuoted)) {
            throw HighlightBuilderException(
                    "cannot mix double quoted and non double quoted", elem);
        }

        doubleQuoted = (*it)->isDoubleQuoted();
        nonDoubleQuoted = !(*it)->isDoubleQuoted();

        wordList.push_back(rep);

        // now check whether we must build a word list rule (word boundary) or an
        // ordinary list; as soon as we find something that is not to be isolated
        // we set buildAsWordList as false
        if (buildAsWordList && (!doubleQuoted || !is_to_isolate(rep))) {
            buildAsWordList = false;
        }
    }

    HighlightRulePtr rule;

    if (buildAsWordList)
        rule = HighlightRulePtr(highlightRuleFactory->createWordListRule(name,
                wordList, elem->isCaseSensitive()));
    else
        rule = HighlightRulePtr(highlightRuleFactory->createListRule(name,
                wordList, elem->isCaseSensitive()));

    rule->setAdditionalInfo(elem->toStringParserInfo());

    state->addRule(rule);

    setExitLevel(elem, rule.get());
}
/**
 * Case of a list of alternatives
 * @param elem
 * @param state
 */
void
RegExpStateBuilder::build(StringListLangElem *elem, RegExpStatePointer state)
{
  const string &name = elem->getName();

  StringDefs *alternatives = elem->getAlternatives();
  string stringdef;
  
  for (StringDefs::const_iterator it = alternatives->begin(); it != alternatives->end();) {
      const string &rep = (*it)->toString();
      
      // check whether the regular expression string must be made non case sensitive
      const string &nonsensitive_processed = 
          (elem->isCaseSensitive() ? rep : 
              RegexPreProcessor::make_nonsensitive(rep));

      // this must be checked on the original string (not the one already made
      // non sensistive); however, we will use the already made nonsensitive
      if ((*it)->isDoubleQuoted() && is_to_isolate(rep)) {
          // we must make a non-marking group since the string can contain
          // alternative symbols. For instance,
          // \<(?:class|for|else)\>
          // correctly detects 'for' only in isolation, while
          // (?:\<class|for|else\>)
          // will not
          stringdef += 
              buildex_isolated(non_marking_group(nonsensitive_processed));
      } else {
          stringdef += nonsensitive_processed;
      }
      
      if (++it != alternatives->end())
          stringdef += '|'; // the alternatives separator
  }

  RegExpFormatterPtr formatter(new RegExpFormatter(name));

  // the final regexp is enclosed in (?: ) i.e., non marking group
  add_exp(state, non_marking_group(stringdef), elem, formatter);
  build(static_cast<StateStartLangElem *>(elem), state);
}