public static string LexStringLiteral(LexReader reader, IDictionary <char, char> basicEscapes, IDictionary <char, Func <LexReader, string> > advancedEscapes, string openingSequence, string closingSequence, bool escapeClosingByDoubling) { var builder = new StringBuilder(); if (!reader.ContinuesWith(openingSequence)) { return(null); } var startingPos = reader.GetPosition(); string doubleClosingSequence = closingSequence + closingSequence; reader.Consume(openingSequence.Length); while (true) { if (reader.EndOfFile()) { throw new LexException(reader.GetPosition(), "Unexpected end of string literal.").AddPosition(startingPos, "Start of string literal").Freeze(); } if (escapeClosingByDoubling && reader.ContinuesWith(doubleClosingSequence)) { reader.Consume(doubleClosingSequence.Length); builder.Append(doubleClosingSequence); } else if (reader.ContinuesWith(closingSequence)) { reader.Consume(closingSequence.Length); return(builder.ToString()); } else if ((basicEscapes != null || advancedEscapes != null) && reader.ContinuesWith("\\")) { reader.Consume(1); char escape = reader.ConsumeChar(); char replacement; Func <LexReader, string> replacementFunc; if (basicEscapes.TryGetValue(escape, out replacement)) { builder.Append(replacement); } else if (advancedEscapes.TryGetValue(escape, out replacementFunc)) { builder.Append(replacementFunc(reader)); } else { throw new LexException(reader.GetPosition(-1), @"Unrecognized escape sequence: ""\{0}"".".Fmt(escape)); } // could introduce support for other behaviours on unrecognized \x, such as no-escape (\x => \x) or as-is escape (\x => x) } else { builder.Append(reader.ConsumeChar()); } } }
public override Token ParseToken(LexReader reader) { if (reader.EndOfFile()) { return(new EndOfFileToken(reader.GetPosition())); } else { return(null); } }
public static string LexStringLiteral(LexReader reader, IDictionary<char, char> basicEscapes, IDictionary<char, Func<LexReader, string>> advancedEscapes, string openingSequence, string closingSequence, bool escapeClosingByDoubling) { var builder = new StringBuilder(); if (!reader.ContinuesWith(openingSequence)) return null; var startingPos = reader.GetPosition(); string doubleClosingSequence = closingSequence + closingSequence; reader.Consume(openingSequence.Length); while (true) { if (reader.EndOfFile()) throw new LexException(reader.GetPosition(), "Unexpected end of string literal.").AddPosition(startingPos, "Start of string literal").Freeze(); if (escapeClosingByDoubling && reader.ContinuesWith(doubleClosingSequence)) { reader.Consume(doubleClosingSequence.Length); builder.Append(doubleClosingSequence); } else if (reader.ContinuesWith(closingSequence)) { reader.Consume(closingSequence.Length); return builder.ToString(); } else if ((basicEscapes != null || advancedEscapes != null) && reader.ContinuesWith("\\")) { reader.Consume(1); char escape = reader.ConsumeChar(); char replacement; Func<LexReader, string> replacementFunc; if (basicEscapes.TryGetValue(escape, out replacement)) builder.Append(replacement); else if (advancedEscapes.TryGetValue(escape, out replacementFunc)) builder.Append(replacementFunc(reader)); else throw new LexException(reader.GetPosition(-1), @"Unrecognized escape sequence: ""\{0}"".".Fmt(escape)); // could introduce support for other behaviours on unrecognized \x, such as no-escape (\x => \x) or as-is escape (\x => x) } else { builder.Append(reader.ConsumeChar()); } } }