public TokenValue LoadToken() { TokenValue r; string val; _start: int x = row; int y = column; switch (peek_char(0)) { case '\0': return(null); case ' ': case '\r': case '\n': case '\t': get_char(); goto _start; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': val = LoadNumber(); r = new TokenValue(Token.NUMBER_LITERAL, val, new Location(file, x, y)); return(r); case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': case '_': val = LoadIdentifier(); r = new TokenValue(val, new Location(file, x, y)); return(r); case '{': get_char(); r = new TokenValue(Token.OPEN_BRACE, "{", new Location(file, x, y)); close_token.Push(r); return(r); case '}': get_char(); r = new TokenValue(Token.CLOSE_BRACE, "}", new Location(file, x, y)); PopCloseToen(Token.OPEN_BRACE); return(r); case '(': get_char(); r = new TokenValue(Token.OPEN_PARENS, "(", new Location(file, x, y)); close_token.Push(r); return(r); case ')': get_char(); r = new TokenValue(Token.CLOSE_PARENS, ")", new Location(file, x, y)); PopCloseToen(Token.OPEN_PARENS); return(r); case '[': get_char(); r = new TokenValue(Token.OPEN_BRACKET, "[", new Location(file, x, y)); close_token.Push(r); return(r); case ']': get_char(); r = new TokenValue(Token.CLOSE_BRACKET, "]", new Location(file, x, y)); PopCloseToen(Token.OPEN_BRACKET); return(r); case '.': get_char(); r = new TokenValue(Token.DOT, ".", new Location(file, x, y)); return(r); case ',': get_char(); r = new TokenValue(Token.COMMA, ",", new Location(file, x, y)); return(r); case ':': get_char(); r = new TokenValue(Token.COLON, ":", new Location(file, x, y)); return(r); case ';': get_char(); r = new TokenValue(Token.SEMICOLON, ";", new Location(file, x, y)); PopCloseToen(Token.SEMICOLON); return(r); case '~': r = new TokenValue(Token.TILDE, "~", new Location(file, x, y)); get_char(); return(r); case '+': get_char(); if (peek_char(0) == '=') { get_char(); r = new TokenValue(Token.OP_ADD_ASSIGN, "+=", new Location(file, x, y)); } else if (peek_char(0) == '+') { get_char(); r = new TokenValue(Token.OP_INC, "++", new Location(file, x, y)); } else { r = new TokenValue(Token.PLUS, "+", new Location(file, x, y)); } return(r); case '-': get_char(); if (peek_char(0) == '=') { get_char(); r = new TokenValue(Token.OP_SUB_ASSIGN, "-=", new Location(file, x, y)); } else if (peek_char(0) == '-') { get_char(); r = new TokenValue(Token.OP_DEC, "--", new Location(file, x, y)); } else { r = new TokenValue(Token.MINUS, "-", new Location(file, x, y)); } return(r); case '*': get_char(); if (peek_char(0) == '=') { get_char(); r = new TokenValue(Token.OP_MULT_ASSIGN, "*=", new Location(file, x, y)); } else { r = new TokenValue(Token.STAR, "*", new Location(file, x, y)); } return(r); case '%': get_char(); if (peek_char(0) == '=') { get_char(); r = new TokenValue(Token.OP_MOD_ASSIGN, "%=", new Location(file, x, y)); } else { r = new TokenValue(Token.PERCENT, "%", new Location(file, x, y)); } return(r); case '/': get_char(); if (peek_char(0) == '/') { while (true) { char ch = get_char(); if (ch == '\n') { goto _start; } if (ch == '\0') { return(null); } } } if (peek_char(0) == '*') { get_char(); while (true) { char ch = get_char(); if (ch == '*' && peek_char(0) == '/') { get_char(); goto _start; } if (ch == '\0') { throw new Exception("不期望的文件结尾"); } } } if (peek_char(0) == '=') { get_char(); r = new TokenValue(Token.OP_DIV_ASSIGN, "/=", new Location(file, x, y)); } else { r = new TokenValue(Token.DIV, "/", new Location(file, x, y)); } return(r); case '!': get_char(); if (peek_char(0) == '=') { get_char(); r = new TokenValue(Token.OP_NE, "!=", new Location(file, x, y)); } else { r = new TokenValue(Token.BANG, "!", new Location(file, x, y)); } return(r); case '=': get_char(); if (peek_char(0) == '=') { get_char(); r = new TokenValue(Token.OP_EQ, "==", new Location(file, x, y)); } else if (peek_char(0) == '>') { get_char(); r = new TokenValue(Token.ARROW, "=>", new Location(file, x, y)); } else { r = new TokenValue(Token.ASSIGN, "!", new Location(file, x, y)); } return(r); case '<': get_char(); if (peek_char(0) == '=') { get_char(); r = new TokenValue(Token.OP_LE, "<=", new Location(file, x, y)); } else if (peek_char(0) == '<') { get_char(); if (peek_char(0) == '=') { get_char(); r = new TokenValue(Token.OP_SHIFT_LEFT_ASSIGN, "<<=", new Location(file, x, y)); } else { r = new TokenValue(Token.OP_SHIFT_LEFT, "<<", new Location(file, x, y)); } } else { r = new TokenValue(Token.OP_LT, "<", new Location(file, x, y)); close_token.Push(r); } return(r); case '>': get_char(); if (close_token.Count > 0) { var p = close_token.Peek(); if (p.token == Token.OP_LT) { close_token.Pop(); p.token = Token.GENERIC_LT; r = new TokenValue(Token.GENERIC_GT, ">", new Location(file, x, y)); return(r); } } if (peek_char(0) == '=') { get_char(); r = new TokenValue(Token.OP_GE, ">=", new Location(file, x, y)); } else if (peek_char(0) == '>') { get_char(); if (peek_char(0) == '=') { get_char(); r = new TokenValue(Token.OP_SHIFT_RIGHT_ASSIGN, ">>=", new Location(file, x, y)); } else { r = new TokenValue(Token.OP_SHIFT_RIGHT, ">>", new Location(file, x, y)); } } else { r = new TokenValue(Token.OP_GT, ">", new Location(file, x, y)); } return(r); case '&': get_char(); if (peek_char(0) == '=') { get_char(); r = new TokenValue(Token.OP_AND_ASSIGN, "&=", new Location(file, x, y)); } else if (peek_char(0) == '&') { get_char(); r = new TokenValue(Token.OP_AND, "&&", new Location(file, x, y)); } else { r = new TokenValue(Token.BITWISE_AND, "&", new Location(file, x, y)); } return(r); case '|': get_char(); if (peek_char(0) == '=') { get_char(); r = new TokenValue(Token.OP_OR_ASSIGN, "|=", new Location(file, x, y)); } else if (peek_char(0) == '|') { get_char(); r = new TokenValue(Token.OP_OR, "||", new Location(file, x, y)); } else { r = new TokenValue(Token.BITWISE_OR, "|", new Location(file, x, y)); } return(r); case '^': get_char(); if (peek_char(0) == '=') { get_char(); r = new TokenValue(Token.OP_XOR_ASSIGN, "^=", new Location(file, x, y)); } else { r = new TokenValue(Token.XOR, "^", new Location(file, x, y)); } return(r); case '?': get_char(); r = new TokenValue(Token.INTERR, "?", new Location(file, x, y)); return(r); case '\'': case '\"': val = LoadString(false); r = new TokenValue(Token.STRING_LITERAL, val, new Location(file, x, y)); return(r); case '@': if (peek_char(0) == '\'' || peek_char(0) == '\"') { get_char(); val = LoadString(true); r = new TokenValue(Token.STRING_LITERAL, val, new Location(file, x, y)); return(r); } goto default; default: throw new Exception("无效字符:" + peek_char(0)); } }
static void PrintValue(string name, object v, int tab) { if (v == null) { PrintLine(name + " : null", tab); return; } var t = v.GetType(); if (v is string || v is int || t.IsEnum || v is bool) { PrintLine(name + " : " + v, tab); return; } if (v is Location) { return; } if (v is TokenValue) { TokenValue k = v as TokenValue; PrintLine(name + " : " + k.value, tab); return; } if (t.Name == "List`1") { System.Collections.IList dict = v as System.Collections.IList; var count = dict.Count; PrintLine(name + " : List[" + count + "]", tab); int i = 0; foreach (object p in dict) { PrintValue("[" + i + "]", p, tab + 1); ++i; } return; } if (t.IsArray) { Array a = v as Array; var count = a.Length; PrintLine(name + " : Array[" + count + "]", tab); for (int i = 0; i < count; i++) { PrintValue("[" + i + "]", a.GetValue(i), tab + 1); } return; } if (t.Name == "Dictionary`2") { System.Collections.IDictionary dict = v as System.Collections.IDictionary; var count = dict.Count; PrintLine(name + " : Dictionary[" + count + "]", tab); foreach (System.Collections.DictionaryEntry p in dict) { PrintValue("[" + p.Key + "]", p.Value, tab + 1); } return; } PrintLine(name + " : " + t.Name, tab); PrintAst(v, tab + 1); }