public static string Parse(CharStream stream) { var startingPos = stream.Position; try { var output = ""; var quote = Quote.Parse(stream); char c; while ((c = stream.PeekNext()) != '\0') { if (c == '\\') { output += stream.ForceReadNext(); } else if (Quote.Peek(stream, quote)) { break; // un-escaped quote means we're ending the string } output += stream.ForceReadNext(); } Quote.Parse(stream, quote); return output; } catch (Exception e) { string msg = String.Format( "something went wrong parsing an <string_value> starting at {0}", stream.ComputeDetailedPosition(startingPos)); throw new Exceptions.ParseException(msg, e); } }
public static AST.INode Parse(CharStream stream) { var startingPos = stream.Position; try { // Parse the quote and store that in the AST of the stringValue var quote = Quote.Parse(stream); var value = new AST.StringValue(quote); AST.INode expression; char c; // Trim starting space WhiteSpace.Parse(stream, true); // as long as we have more characters left // we'll keep reading, and break from within this loop body // when we reached the same quote that started this entire parser logic. while ((c = stream.PeekNext()) != '\0') { if (c == '\\') { // skip the escape character && read the next one stream.Skip(); c = stream.PeekNext(); if (c == '\\' || c == '{' || c == '}' || c == '\'' || c == '"') { c = stream.ForceReadNext(); value.appendChar(c); } else if (c == 'u') { // skip the starter character stream.Skip(); // try to read unicode character value.appendChar(ReadUnicodeCharacter(stream)); } else { var msg = String.Format( "character \\{0} is not a valid escape character", c); throw stream.CreateException(msg); } // unicode characters are also supported in the classical U+xxxxxx notation } else if (c == 'U' && stream.PeekNext(1) == '+') { // skip the starter characters stream.Skip(2); // try to read unicode character value.appendChar(ReadUnicodeCharacter(stream)); } else if (c == '\n' || c == '\r') // newlines get converted to a space { stream.Skip(); var lc = value.LastCharacter; // we add this dummy character, such that we wouldn't add a space in // languages that don't use a space in general, such as chinese. if (!Char.IsWhiteSpace(lc) && lc != AST.StringValue.DummyNewlineWhitespaceCharacter) value.appendChar(AST.StringValue.DummyNewlineWhitespaceCharacter); } else { if (Quote.Peek(stream, quote)) { break; // un-escaped quote means we're ending the string } else if (Expander.PeekAndParse(stream, out expression)) { value.appendExpression(expression); } else { c = stream.ForceReadNext(); var lc = value.LastCharacter; if(!Char.IsWhiteSpace(c) || (lc != AST.StringValue.DummyNewlineWhitespaceCharacter && !Char.IsWhiteSpace(lc))) value.appendChar(c); } } } // Eventually we expect exactly the same string back Quote.Parse(stream, quote); return value; } catch (Exception e) { string msg = String.Format( "something went wrong parsing an <string_value> starting at {0}", stream.ComputeDetailedPosition(startingPos)); throw new Exceptions.ParseException(msg, e); } }