using System;
using System.Text;
using System.Collections;
+using System.Collections.Generic;
using System.IO;
using System.Globalization;
using System.Reflection;
}
}
+ sealed class IdentifiersComparer : IEqualityComparer<char[]>
+ {
+ readonly int length;
+
+ public IdentifiersComparer (int length)
+ {
+ this.length = length;
+ }
+
+ public bool Equals (char[] x, char[] y)
+ {
+ for (int i = 0; i < length; ++i)
+ if (x [i] != y [i])
+ return false;
+
+ return true;
+ }
+
+ public int GetHashCode (char[] obj)
+ {
+ int h = 0;
+ for (int i = 0; i < length; ++i)
+ h = (h << 5) - h + obj [i];
+
+ return h;
+ }
+ }
+
SeekableStreamReader reader;
SourceFile ref_name;
CompilationUnit file_name;
// Class variables
//
static KeywordEntry[][] keywords;
- static Hashtable keyword_strings;
+ static Dictionary<string, object> keyword_strings; // TODO: HashSet
static NumberStyles styles;
static NumberFormatInfo csharp_format_info;
const int max_id_size = 512;
static char [] id_builder = new char [max_id_size];
- static CharArrayHashtable [] identifiers = new CharArrayHashtable [max_id_size + 1];
+ public static Dictionary<char[], string>[] identifiers = new Dictionary<char[], string>[max_id_size + 1];
const int max_number_size = 512;
static char [] number_builder = new char [max_number_size];
static int number_pos;
+
+ static StringBuilder static_cmd_arg = new System.Text.StringBuilder ();
//
// Details about the error encoutered by the tokenizer
static void AddKeyword (string kw, int token)
{
- keyword_strings.Add (kw, kw);
+ keyword_strings.Add (kw, null);
int length = kw.Length;
if (keywords [length] == null) {
static void InitTokens ()
{
- keyword_strings = new Hashtable ();
+ keyword_strings = new Dictionary<string, object> ();
// 11 is the length of the longest keyword for now
keywords = new KeywordEntry [11] [];
public static bool IsKeyword (string s)
{
- return keyword_strings [s] != null;
+ return keyword_strings.ContainsKey (s);
}
//
//
Report.Warning (78, 4, Location, "The 'l' suffix is easily confused with the digit '1' (use 'L' for clarity)");
}
- //
- // This goto statement causes the MS CLR 2.0 beta 1 csc to report an error, so
- // work around that.
- //
- //goto case 'L';
- if (is_long)
- scanning = false;
- is_long = true;
- get_char ();
- break;
+
+ goto case 'L';
case 'L':
if (is_long)
return current_token;
}
- static StringBuilder static_cmd_arg = new System.Text.StringBuilder ();
-
void get_cmd_arg (out string cmd, out string arg)
{
int c;
// Keep identifiers in an array of hashtables to avoid needless
// allocations
//
- CharArrayHashtable identifiers_group = identifiers [pos];
+ var identifiers_group = identifiers [pos];
+ string s;
if (identifiers_group != null) {
- val = identifiers_group [id_builder];
- if (val != null) {
- val = new LocatedToken (loc, (string) val);
+ if (identifiers_group.TryGetValue (id_builder, out s)) {
+ val = new LocatedToken (loc, s);
if (quoted)
AddEscapedIdentifier ((LocatedToken) val);
return Token.IDENTIFIER;
}
} else {
- identifiers_group = new CharArrayHashtable (pos);
+ // TODO: this should be number of files dependant
+ // corlib compilation peaks at 1000 and System.Core at 150
+ int capacity = pos > 20 ? 10 : 100;
+ identifiers_group = new Dictionary<char[],string> (capacity, new IdentifiersComparer (pos));
identifiers [pos] = identifiers_group;
}
char [] chars = new char [pos];
Array.Copy (id_builder, chars, pos);
- val = new String (id_builder, 0, pos);
- identifiers_group.Add (chars, val);
-
- if (RootContext.Version == LanguageVersion.ISO_1) {
- for (int i = 1; i < chars.Length; i += 3) {
- if (chars [i] == '_' && (chars [i - 1] == '_' || chars [i + 1] == '_')) {
- Report.Error (1638, loc,
- "`{0}': Any identifier with double underscores cannot be used when ISO language version mode is specified", val.ToString ());
- }
- }
- }
+ s = new string (id_builder, 0, pos);
+ identifiers_group.Add (chars, s);
- val = new LocatedToken (loc, (string) val);
+ val = new LocatedToken (loc, s);
if (quoted)
AddEscapedIdentifier ((LocatedToken) val);
return Token.IDENTIFIER;