public override Expression Scan(ParseEngine engine) { var chars = engine.Characters; var start = engine.Pointer; if (chars[start] == '"' || (chars[start] == '@' && start + 1 < chars.Length && chars[start + 1] == '"')) { var index = start; var exp = new StringExpression(engine); var escape = false; var terminated = false; var sb = new StringBuilder(); if (chars[index] == '@') { index += 2; exp.literal = true; } else { index++; } while (index < chars.Length) { if (!literal && !escape && chars[index] == '\\') { escape = true; } else if (!escape && chars[index] == '"') { terminated = true; index++; break; } else if (escape) { switch (chars[index]) { case 't': sb.Append("\t"); break; case 'n': sb.AppendLine(); break; case '\\': case '"': sb.Append(chars[index]); break; default: engine.SetPointer(index); engine.AddError(new YAMPEscapeSequenceNotFoundError(engine, chars[index]), exp); break; } escape = false; } else { sb.Append(chars[index]); } index++; } if (!terminated) { engine.AddError(new YAMPStringNotTerminatedError(engine), exp); } exp.value = sb.ToString(); exp.Length = index - start; engine.SetPointer(index); return exp; } return null; }