📄 cs-tokenizer.cs
字号:
return Token.STAR; } if (c == '/'){ if (d == '='){ doread = true; return Token.OP_DIV_ASSIGN; } return Token.DIV; } if (c == '%'){ if (d == '='){ doread = true; return Token.OP_MOD_ASSIGN; } return Token.PERCENT; } if (c == '^'){ if (d == '='){ doread = true; return Token.OP_XOR_ASSIGN; } return Token.CARRET; } if (c == '<'){ if (d == '<'){ getChar (); d = peekChar (); if (d == '='){ doread = true; return Token.OP_SHIFT_LEFT_ASSIGN; } return Token.OP_SHIFT_LEFT; } else if (d == '='){ doread = true; return Token.OP_LE; } return Token.OP_LT; } if (c == '>'){ if (d == '>'){ getChar (); d = peekChar (); if (d == '='){ doread = true; return Token.OP_SHIFT_RIGHT_ASSIGN; } return Token.OP_SHIFT_RIGHT; } else if (d == '='){ doread = true; return Token.OP_GE; } return Token.OP_GT; } if (c == ':'){ if (d == ':'){ doread = true; return Token.DOUBLE_COLON; } val = Location; return Token.COLON; } return Token.ERROR; } int deambiguate_close_parens = 0; public void Deambiguate_CloseParens () { putback (')'); deambiguate_close_parens++; } void Error_NumericConstantTooLong () { Report.Error (1021, Location, "Numeric constant too long"); } bool decimal_digits (int c) { int d; bool seen_digits = false; if (c != -1){ if (number_pos == max_number_size) Error_NumericConstantTooLong (); number_builder [number_pos++] = (char) c; } // // We use peekChar2, because decimal_digits needs to do a // 2-character look-ahead (5.ToString for example). // while ((d = peekChar2 ()) != -1){ if (d >= '0' && d <= '9'){ if (number_pos == max_number_size) Error_NumericConstantTooLong (); number_builder [number_pos++] = (char) d; getChar (); seen_digits = true; } else break; } return seen_digits; } bool is_hex (int e) { return (e >= '0' && e <= '9') || (e >= 'A' && e <= 'F') || (e >= 'a' && e <= 'f'); } int real_type_suffix (int c) { int t; switch (c){ case 'F': case 'f': t = Token.LITERAL_FLOAT; break; case 'D': case 'd': t = Token.LITERAL_DOUBLE; break; case 'M': case 'm': t= Token.LITERAL_DECIMAL; break; default: return Token.NONE; } return t; } int integer_type_suffix (ulong ul, int c) { bool is_unsigned = false; bool is_long = false; if (c != -1){ bool scanning = true; do { switch (c){ case 'U': case 'u': if (is_unsigned) scanning = false; is_unsigned = true; getChar (); break; case 'l': if (!is_unsigned && (RootContext.WarningLevel >= 4)){ // // if we have not seen anything in between // report this error // Report.Warning (78, 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; getChar (); break; case 'L': if (is_long) scanning = false; is_long = true; getChar (); break; default: scanning = false; break; } c = peekChar (); } while (scanning); } if (is_long && is_unsigned){ val = ul; return Token.LITERAL_INTEGER; } else if (is_unsigned){ // uint if possible, or ulong else. if ((ul & 0xffffffff00000000) == 0) val = (uint) ul; else val = ul; } else if (is_long){ // long if possible, ulong otherwise if ((ul & 0x8000000000000000) != 0) val = ul; else val = (long) ul; } else { // int, uint, long or ulong in that order if ((ul & 0xffffffff00000000) == 0){ uint ui = (uint) ul; if ((ui & 0x80000000) != 0) val = ui; else val = (int) ui; } else { if ((ul & 0x8000000000000000) != 0) val = ul; else val = (long) ul; } } return Token.LITERAL_INTEGER; } // // given `c' as the next char in the input decide whether // we need to convert to a special type, and then choose // the best representation for the integer // int adjust_int (int c) { try { if (number_pos > 9){ ulong ul = (uint) (number_builder [0] - '0'); for (int i = 1; i < number_pos; i++){ ul = checked ((ul * 10) + ((uint)(number_builder [i] - '0'))); } return integer_type_suffix (ul, c); } else { uint ui = (uint) (number_builder [0] - '0'); for (int i = 1; i < number_pos; i++){ ui = checked ((ui * 10) + ((uint)(number_builder [i] - '0'))); } return integer_type_suffix (ui, c); } } catch (OverflowException) { error_details = "Integral constant is too large"; Report.Error (1021, Location, error_details); val = 0ul; return Token.LITERAL_INTEGER; } } int adjust_real (int t) { string s = new String (number_builder, 0, number_pos); const string error_details = "Floating-point constant is outside the range of type `{0}'"; switch (t){ case Token.LITERAL_DECIMAL: try { val = System.Decimal.Parse (s, styles, csharp_format_info); } catch (OverflowException) { val = 0m; Report.Error (594, Location, error_details, "decimal"); } break; case Token.LITERAL_FLOAT: try { val = (float) System.Double.Parse (s, styles, csharp_format_info); } catch (OverflowException) { val = 0.0f; Report.Error (594, Location, error_details, "float"); } break; case Token.LITERAL_DOUBLE: case Token.NONE: t = Token.LITERAL_DOUBLE; try { val = System.Double.Parse (s, styles, csharp_format_info); } catch (OverflowException) { val = 0.0; Report.Error (594, Location, error_details, "double"); } break; } return t; } int handle_hex () { int d; ulong ul; getChar (); while ((d = peekChar ()) != -1){ if (is_hex (d)){ number_builder [number_pos++] = (char) d; getChar (); } else break; } string s = new String (number_builder, 0, number_pos); try { if (number_pos <= 8) ul = System.UInt32.Parse (s, NumberStyles.HexNumber); else ul = System.UInt64.Parse (s, NumberStyles.HexNumber); } catch (OverflowException){ error_details = "Integral constant is too large"; Report.Error (1021, Location, error_details); val = 0ul; return Token.LITERAL_INTEGER; } catch (FormatException) { Report.Error (1013, Location, "Invalid number"); val = 0ul; return Token.LITERAL_INTEGER; } return integer_type_suffix (ul, peekChar ()); } // // Invoked if we know we have .digits or digits // int is_number (int c) { bool is_real = false; int type; number_pos = 0; if (c >= '0' && c <= '9'){ if (c == '0'){ int peek = peekChar (); if (peek == 'x' || peek == 'X') return handle_hex (); } decimal_digits (c); c = getChar (); } // // We need to handle the case of // "1.1" vs "1.string" (LITERAL_FLOAT vs NUMBER DOT IDENTIFIER) // if (c == '.'){ if (decimal_digits ('.')){ is_real = true; c = getChar (); } else { putback ('.'); number_pos--; return adjust_int (-1); } } if (c == 'e' || c == 'E'){ is_real = true; if (number_pos == max_number_size) Error_NumericConstantTooLong (); number_builder [number_pos++] = 'e'; c = getChar (); if (c == '+'){ if (number_pos == max_number_size) Error_NumericConstantTooLong (); number_builder [number_pos++] = '+'; c = -1; } else if (c == '-') { if (number_pos == max_number_size) Error_NumericConstantTooLong (); number_builder [number_pos++] = '-'; c = -1; } else { if (number_pos == max_number_size) Error_NumericConstantTooLong (); number_builder [number_pos++] = '+'; } decimal_digits (c); c = getChar (); } type = real_type_suffix (c); if (type == Token.NONE && !is_real){ putback (c); return adjust_int (c); } else is_real = true; if (type == Token.NONE){ putback (c); } if (is_real) return adjust_real (type); Console.WriteLine ("This should not be reached"); throw new Exception ("Is Number should never reach this point"); } // // Accepts exactly count (4 or 8) hex, no more no less // int getHex (int count, out bool error) { int i; int total = 0; int c; int top = count != -1 ? count : 4; getChar (); error = false; for (i = 0; i < top; i++){ c = getChar (); if (c >= '0' && c <= '9') c = (int) c - (int) '0'; else if (c >= 'A' && c <= 'F') c = (int) c - (int) 'A' + 10; else if (c >= 'a' && c <= 'f') c = (int) c - (int) 'a' + 10; else { error = true; return 0; } total = (total * 16) + c; if (count == -1){ int p = peekChar (); if (p == -1) break; if (!is_hex ((char)p)) break; } } return total; } int escape (int c) { bool error; int d; int v; d = peekChar (); if (c != '\\') return c; switch (d){ case 'a': v = '\a'; break; case 'b': v = '\b'; break; case 'n': v = '\n'; break; case 't': v = '\t'; break; case 'v': v = '\v'; break; case 'r': v = '\r'; break; case '\\': v = '\\'; break; case 'f': v = '\f'; break; case '0': v = 0; break; case '"': v = '"'; break; case '\'': v = '\''; break; case 'x': v = getHex (-1, out error); if (error) goto default; return v; case 'u': v = getHex (4, out error); if (error) goto default; return v; case 'U': v = getHex (8, out error); if (error) goto default; return v; default: Report.Error (1009, Location, "Unrecognized escape sequence `\\{0}'", (char)d); return d; } getChar (); return v; } int getChar () { int x; if (putback_char != -1) { x = putback_char; putback_char = -1; } else x = reader.Read (); if (x == '\n') { line++; ref_line++; previous_col = col; col = 0; } else col++; return x; } int peekChar () { if (putback_char != -1) return putback_char; putback_char = reader.Read (); return putback_char; } int peekChar2 () { if (putback_char != -1) return putback_char; return reader.Peek (); } void putback (int c) { if (putback_char != -1){ Console.WriteLine ("Col: " + col); Console.WriteLine ("Row: " + line); Console.WriteLine ("Name: " + ref_name.Name); Console.WriteLine ("Current [{0}] putting back [{1}] ", putback_char, c); throw new Exception ("This should not happen putback on putback"); } if (c == '\n' || col == 0) { // It won't happen though. line--; ref_line--; col = previous_col; } else col--; putback_char = c; } public bool advance () { return peekChar () != -1; } public Object Value { get { return val; } } public Object value () { return val; } bool IsCastToken (int token) { switch (token) { case Token.BANG: case Token.TILDE: case Token.IDENTIFIER: case Token.LITERAL_INTEGER: case Token.LITERAL_FLOAT: case Token.LITERAL_DOUBLE: case Token.LITERAL_DECIMAL: case Token.LITERAL_CHARACTER:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -