/// <summary> /// Escape characters inside a text literal /// </summary> private string PELEscape(TextPortion SourcePosition, char EscapeChar) { StringBuilder sb = new StringBuilder(SourcePosition.Length); //Last position in the string var old_pos = SourcePosition.Begin; //Caret for finding \ var crt = new Caret(); crt.Source = SourcePosition.Text; string esc_char = EscapeChar.ToString(), esc_chars = esc_char + esc_char; for (var pos = SourcePosition.Text.IndexOf('\\', SourcePosition.Begin, SourcePosition.Length); pos >= 0; pos = SourcePosition.Text.IndexOf('\\', pos, SourcePosition.End - pos)) { //Append in-between text if (pos != old_pos) sb.Append(SourcePosition.Text.Substring(old_pos, pos - old_pos).Replace(esc_chars, esc_char)); if (pos == SourcePosition.End) { ThrowParseError("Expected a character to escape", new TextPortion(pos, 1)); break; } pos++; //End of file if (pos >= SourcePosition.End) break; switch (SourcePosition.Text[pos]) { case '\\': sb.Append('\\'); pos++; break; case 'r': case 'R': sb.Append('\r'); pos++; break; case 'n': case 'N': sb.Append('\n'); pos++; break; case 't': case 'T': sb.Append('\t'); pos++; break; case 'x': case 'X': pos++; crt.Position = pos; if (!crt.Match(@"(?<cap>([0-9a-fA-F]{2})+)\\")) ThrowParseError( "Expected one or more consecutive 2-digit hexadecimal values, followed by a \\ (eg \\x2A\\, or \\x02A5F2\\)", new TextPortion(pos, 1)); else { var cap = crt.LastMatch.Groups["cap"].Value; for (int i = 0; i < cap.Length; i += 2) sb.Append((char) Int16.Parse(cap.Substring(i, 2), NumberStyles.HexNumber)); pos = crt.Position; } break; case 'u': case 'U': pos++; crt.Position = pos; if (!crt.Match(@"(?<cap>([0-9a-fA-F]{4})+)\\")) ThrowParseError( "Expected one or more consecutive 4-digit hexadecimal values, followed by a \\ (eg \\u002A\\, or \\u000200A510F2\\)", new TextPortion(pos, 1)); else { var cap = crt.LastMatch.Groups["cap"].Value; for (int i = 0; i < cap.Length; i += 4) sb.Append((char) Int16.Parse(cap.Substring(i, 4), NumberStyles.HexNumber)); pos = crt.Position; } break; default: ThrowParseError("Unexpected escape character", new TextPortion(pos, 1)); break; } old_pos = pos; } //Append remaining text if (old_pos != SourcePosition.End) sb.Append(SourcePosition.Text, old_pos, SourcePosition.End - old_pos); return sb.ToString(); }