public bool parsing_catch_when;
int parsing_string_interpolation;
+ int string_interpolation_section;
+ Stack<bool> parsing_string_interpolation_quoted;
public bool parsing_interpolation_format;
public int current_token;
public object val;
public int parsing_string_interpolation;
+ public int string_interpolation_section;
+ public Stack<bool> parsing_string_interpolation_quoted;
public Position (Tokenizer t)
{
ifstack = new Stack<int> (clone);
}
parsing_generic_less_than = t.parsing_generic_less_than;
- parsing_string_interpolation = t.parsing_string_interpolation;
+ string_interpolation_section = t.string_interpolation_section;
current_token = t.current_token;
val = t.val;
+ parsing_string_interpolation = t.parsing_string_interpolation;
+ string_interpolation_section = t.string_interpolation_section;
+ if (t.parsing_string_interpolation_quoted != null && t.parsing_string_interpolation_quoted.Count != 0) {
+ var clone = t.parsing_string_interpolation_quoted.ToArray ();
+ Array.Reverse (clone);
+ parsing_string_interpolation_quoted = new Stack<bool> (clone);
+ }
}
}
ifstack = p.ifstack;
parsing_generic_less_than = p.parsing_generic_less_than;
parsing_string_interpolation = p.parsing_string_interpolation;
+ parsing_string_interpolation_quoted = p.parsing_string_interpolation_quoted;
current_token = p.current_token;
val = p.val;
}
static bool is_identifier_start_character (int c)
{
- return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || Char.IsLetter ((char)c);
+ if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_')
+ return true;
+
+ if (c < 0x80)
+ return false;
+
+ return is_identifier_start_character_slow_part ((char) c);
}
static bool is_identifier_part_character (char c)
return is_identifier_part_character_slow_part (c);
}
- static bool is_identifier_part_character_slow_part (char c)
+ static bool is_identifier_start_character_slow_part (char c)
{
- if (Char.IsLetter (c))
+ switch (Char.GetUnicodeCategory (c)) {
+ case UnicodeCategory.LetterNumber:
+ case UnicodeCategory.UppercaseLetter:
+ case UnicodeCategory.LowercaseLetter:
+ case UnicodeCategory.TitlecaseLetter:
+ case UnicodeCategory.ModifierLetter:
+ case UnicodeCategory.OtherLetter:
return true;
+ }
+ return false;
+ }
+ static bool is_identifier_part_character_slow_part (char c)
+ {
switch (Char.GetUnicodeCategory (c)) {
- case UnicodeCategory.ConnectorPunctuation:
-
- // combining-character: A Unicode character of classes Mn or Mc
- case UnicodeCategory.NonSpacingMark:
- case UnicodeCategory.SpacingCombiningMark:
-
- // decimal-digit-character: A Unicode character of the class Nd
- case UnicodeCategory.DecimalDigitNumber:
+ // connecting-character: A Unicode character of the class Pc
+ case UnicodeCategory.ConnectorPunctuation:
+
+ // combining-character: A Unicode character of classes Mn or Mc
+ case UnicodeCategory.NonSpacingMark:
+ case UnicodeCategory.SpacingCombiningMark:
+
+ // decimal-digit-character: A Unicode character of the class Nd
+ case UnicodeCategory.DecimalDigitNumber:
+
+ // plus is_identifier_start_character_slow_part
+ case UnicodeCategory.LetterNumber:
+ case UnicodeCategory.UppercaseLetter:
+ case UnicodeCategory.LowercaseLetter:
+ case UnicodeCategory.TitlecaseLetter:
+ case UnicodeCategory.ModifierLetter:
+ case UnicodeCategory.OtherLetter:
return true;
+
+ // formatting-character: A Unicode character of the class Cf
+ case UnicodeCategory.Format:
+ // csc bug compatibility which recognizes it as a whitespace
+ return c != 0xFEFF;
}
return false;
case Token.DECIMAL:
case Token.BOOL:
case Token.STRING:
+ case Token.SBYTE:
return Token.OPEN_PARENS_CAST;
}
}
case '{':
val = ltb.Create (current_source, ref_line, col);
+
+ if (parsing_string_interpolation > 0)
+ ++string_interpolation_section;
+
return Token.OPEN_BRACE;
case '}':
if (parsing_string_interpolation > 0) {
- if (peek_char () != '}') {
+ if (string_interpolation_section == 0) {
--parsing_string_interpolation;
- return TokenizeInterpolatedString ();
+ bool quoted;
+ if (parsing_string_interpolation_quoted != null && parsing_string_interpolation_quoted.Count > 0) {
+ quoted = parsing_string_interpolation_quoted.Pop ();
+ } else {
+ quoted = false;
+ }
+
+ return TokenizeInterpolatedString (quoted);
}
- continue;
+ --string_interpolation_section;
}
val = ltb.Create (current_source, ref_line, col);
return Token.ERROR;
case '$':
- if (peek_char () == '"') {
+ switch (peek_char ()) {
+ case '"':
+ get_char ();
+ return TokenizeInterpolatedString (false);
+ case '@':
get_char ();
- return TokenizeInterpolatedString ();
+ if (peek_char () == '"') {
+ get_char ();
+ return TokenizeInterpolatedString (true);
+ }
+
+ break;
}
break;
return Token.OP_LT;
}
- int TokenizeInterpolatedString ()
+ int TokenizeInterpolatedString (bool quoted)
{
int pos = 0;
var start_location = Location;
var ch = get_char ();
switch (ch) {
case '"':
+ if (quoted && peek_char () == '"') {
+ get_char ();
+ break;
+ }
+
val = new StringLiteral (context.BuiltinTypes, CreateStringFromBuilder (pos), start_location);
return Token.INTERPOLATED_STRING_END;
case '{':
}
++parsing_string_interpolation;
+ if (quoted) {
+ if (parsing_string_interpolation_quoted == null)
+ parsing_string_interpolation_quoted = new Stack<bool> ();
+ }
+
+ if (parsing_string_interpolation_quoted != null) {
+ parsing_string_interpolation_quoted.Push (quoted);
+ }
+
val = new StringLiteral (context.BuiltinTypes, CreateStringFromBuilder (pos), start_location);
return Token.INTERPOLATED_STRING;
case '\\':
+ if (quoted)
+ break;
+
++col;
int surrogate;
ch = escape (ch, out surrogate);
private void handle_one_line_xml_comment ()
{
int c;
- while ((c = peek_char ()) == ' ')
- get_char (); // skip heading whitespaces.
while ((c = peek_char ()) != -1 && c != '\n' && c != '\r') {
xml_comment_buffer.Append ((char) get_char ());
}