@Override
	public Handle stringLiteral(TerminalAST stringLiteralAST) {
		String chars = stringLiteralAST.getText();
		ATNState left = newState(stringLiteralAST);
		ATNState right;
		String s = CharSupport.getStringFromGrammarStringLiteral(chars);
		if (s == null) {
			// the lexer will already have given an error
			return new Handle(left, left);
		}

		int n = s.length();
		ATNState prev = left;
		right = null;
		for (int i = 0; i < n; ) {
			right = newState(stringLiteralAST);
			int codePoint = s.codePointAt(i);
			prev.addTransition(createTransition(right, codePoint, codePoint, stringLiteralAST));
			prev = right;
			i += Character.charCount(codePoint);
		}
		stringLiteralAST.atnState = left;
		return new Handle(left, right);
	}
For a lexer, a string is a sequence of char to match.  That is,
 "fog" is treated as 'f' 'o' 'g' not as a single transition in
 the DFA.  Machine== o-'f'-&gt;o-'o'-&gt;o-'g'-&gt;o and has n+1 states
 for n characters.
 if "caseInsensitive" option is enabled, "fog" will be treated as
 o-('f'|'F') -> o-('o'|'O') -> o-('g'|'G')
tool/src/org/antlr/v4/automata/LexerATNFactory.java