public void MatchLiteral(String s, Symbol sym) {
    s = tab.Unescape(s.substring(1, s.length()-1));
    int i, len = s.length();
    State state = firstState;
    Action a = null;
    for (i = 0; i < len; i++) { // try to match s against existing DFA
      a = FindAction(state, s.charAt(i));
      if (a == null) break;
      state = a.target.state;
    }
    // if s was not totally consumed or leads to a non-final state => make new DFA from it
    if (i != len || state.endOf == null) {
      state = firstState; i = 0; a = null;
      dirtyDFA = true;
    }
    for (; i < len; i++) { // make new DFA for s[i..len-1]
      State to = NewState();
      NewTransition(state, to, Node.chr, s.charAt(i), Node.normalTrans);
      state = to;
    }
    Symbol matchedSym = state.endOf;
    if (state.endOf == null) {
      state.endOf = sym;
    } else if (matchedSym.tokenKind == Symbol.fixedToken || (a != null && a.tc == Node.contextTrans)) {
      // s matched a token with a fixed definition or a token with an appendix that will be cut off
      parser.SemErr("tokens " + sym.name + " and " + matchedSym.name + " cannot be distinguished");
    } else { // matchedSym == classToken || classLitToken
      matchedSym.tokenKind = Symbol.classLitToken;
      sym.tokenKind = Symbol.litToken;
    }
  }