2 // Author: Sergey Chaban (serge@wildwestsoftware.com)
\r
7 namespace Mono.ILASM {
\r
11 internal class StringHelper : StringHelperBase {
\r
13 private static readonly string startIdChars = "#$@_";
\r
14 private static readonly string idChars = "_$@?`";
\r
18 /// <param name="host"></param>
\r
19 public StringHelper (ILTokenizer host) : base (host)
\r
26 /// <returns></returns>
\r
27 public override bool Start (char ch)
\r
29 mode = Token.UNKNOWN;
\r
31 if (Char.IsLetter (ch) || startIdChars.IndexOf (ch) != -1) {
\r
33 } else if (ch == '\'') {
\r
34 mode = Token.SQSTRING;
\r
35 } else if (ch == '"') {
\r
36 mode = Token.QSTRING;
\r
39 return (mode != Token.UNKNOWN);
\r
43 private static bool IsIdChar (int c)
\r
46 return (Char.IsLetterOrDigit(ch) || idChars.IndexOf (ch) != -1);
\r
51 /// <returns></returns>
\r
52 public override string Build ()
\r
54 if (mode == Token.UNKNOWN) return String.Empty;
\r
57 ILReader reader = host.Reader;
\r
59 StringBuilder idsb = new StringBuilder ();
\r
60 if (mode == Token.SQSTRING || mode == Token.QSTRING) {
\r
61 int term = (mode == Token.SQSTRING) ? '\'' : '"';
\r
62 reader.Read (); // skip quote
\r
63 for (ch = reader.Read (); ch != -1; ch = reader.Read ()) {
\r
69 ch = reader.Read ();
\r
72 * Long string can be broken across multiple lines
\r
73 * by using '\' as the last char in line.
\r
74 * Any white space chars between '\' and the first
\r
75 * char on the next line are ignored.
\r
78 reader.SkipWhitespace ();
\r
82 int escaped = Escape (reader, ch);
\r
83 if (escaped == -1) {
\r
91 idsb.Append((char)ch);
\r
94 while ((ch = reader.Read ()) != -1) {
\r
95 if (IsIdChar (ch)) {
\r
96 idsb.Append ((char) ch);
\r
103 return idsb.ToString ();
\r
111 /// <param name="ch"></param>
\r
112 /// <returns></returns>
\r
113 public static int Escape (ILReader reader, int ch)
\r
117 if (ch >= '0' && ch <='7') {
\r
118 StringBuilder octal = new StringBuilder ();
\r
119 octal.Append ((char)ch);
\r
120 int possibleOctalChar = reader.Peek ();
\r
121 if (possibleOctalChar >= '0' && possibleOctalChar <='7') {
\r
122 octal.Append ((char)reader.Read ());
\r
123 possibleOctalChar = reader.Peek ();
\r
124 if (possibleOctalChar >= '0' && possibleOctalChar <='7')
\r
125 octal.Append ((char)reader.Read ());
\r
127 res = Convert.ToInt32(octal.ToString (), 8);
\r
129 int id = "abfnrtv\"'\\".IndexOf ((char)ch);
\r
131 res = "\a\b\f\n\r\t\v\"'\\" [id];
\r