public ScriptLiteralToken(string val, ScriptLiteralTokenType type, ScriptVariableType exactType, int line, int character) : base(val, line, character) { LiteralType = type; ExactType = exactType; CompiledValue = null; }
protected virtual int TryParseLiteral(out ScriptToken codeObj) { ScriptLiteralTokenType ctype = ScriptLiteralTokenType.None; ScriptVariableType etype = ScriptVariableType.Undefined; int state = 0, pos = this.Position, len = this.Length; char c; int charCode; // use ushort for char code instead of int? codeObj = null; StringBuilder val = null; StringBuilder charCodeHex = null; while (pos < len && state < 100) { c = this.ScriptText[pos++]; switch (state) { case 0: // the very beginning if (c == '@') { ctype = ScriptLiteralTokenType.String; etype = ScriptVariableType.String; state = 20; break; } goto case 1; case 1: // don't know if it is really a literal if (c == 'n') { ctype = ScriptLiteralTokenType.Null; etype = ScriptVariableType.String; state = 80; break; } if (c == 't') { ctype = ScriptLiteralTokenType.Boolean; etype = ScriptVariableType.Bool; state = 90; break; } if (c == 'f') { ctype = ScriptLiteralTokenType.Boolean; etype = ScriptVariableType.Bool; state = 95; break; } if (c == '\'') { ctype = ScriptLiteralTokenType.Char; etype = ScriptVariableType.Char; state = 10; break; } if (c == '"') { ctype = ScriptLiteralTokenType.String; etype = ScriptVariableType.String; val = new StringBuilder(); state = 30; break; } if (c == '+' && SignInLiteral) { ctype = ScriptLiteralTokenType.Decimal; etype = ScriptVariableType.Int; val = new StringBuilder(); state = 41; break; } // possibly a positive number if (c == '-' && SignInLiteral) { ctype = ScriptLiteralTokenType.Decimal; etype = ScriptVariableType.Int; val = new StringBuilder(); val.Append(c); state = 41; break; } // possibly a negative number if (c == '.') { ctype = ScriptLiteralTokenType.Decimal; etype = ScriptVariableType.Double; val = new StringBuilder(); val.Append(c); state = 43; break; } // possibly starts from a mantissa of a floating point number if (c == '0') { etype = ScriptVariableType.Int; val = new StringBuilder(); val.Append(c); state = 40; break; } if (c >= '1' && c <= '9') { ctype = ScriptLiteralTokenType.Decimal; etype = ScriptVariableType.Int; val = new StringBuilder(); val.Append(c); state = 42; break; } return(0); // parsing a character literal case 10: val = new StringBuilder(); if (c == '\\') { state = 11; break; } val.Append(c); state = 12; break; case 11: if (c == '0') { val.Append((char)0); } else if (c == 't') { val.Append('\t'); } else if (c == 'r') { val.Append('\r'); } else if (c == 'n') { val.Append('\n'); } else if (c == 'u') { charCodeHex = new StringBuilder(); state = 15; break; } else if (c == 'x') { charCodeHex = new StringBuilder(); state = 17; break; } else { val.Append(c); } state = 12; break; case 12: if (c != '\'') { return(0); } state = 100; break; case 15: goto case 18; case 16: goto case 18; case 17: goto case 18; case 18: if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) { charCodeHex.Append(c); if (++state > 18) { state = 12; charCode = (int)Convert.ToUInt32(charCodeHex.ToString(), 16); val.Append((char)charCode); charCodeHex = null; } break; } if (charCodeHex.Length > 0) { charCode = (int)Convert.ToUInt32(charCodeHex.ToString(), 16); val.Append((char)charCode); charCodeHex = null; } state = 12; goto case 12; // parsing a string literal without escape sequences case 20: if (c == '"') { val = new StringBuilder(); state = 21; break; } return(0); case 21: if (c == '"') { state = 22; break; } val.Append(c); break; case 22: // two double quoted in a row result in a doublequote added to a string if (c == '"') { val.Append(c); state = 21; break; } pos--; state = 100; break; // parsing a string literal with escape sequences case 30: if (c == '"') { state = 100; break; } if (c == '\\') { state = 31; break; } if (c == '\r' || c == '\n') { return(0); // in C# newlines are not allowed in strings with escape sequences :/ } val.Append(c); break; case 31: if (c == '0') { val.Append((char)0); } else if (c == 't') { val.Append('\t'); } else if (c == 'r') { val.Append('\r'); } else if (c == 'n') { val.Append('\n'); } else if (c == 'u') { charCodeHex = new StringBuilder(); state = 35; break; } else if (c == 'x') { charCodeHex = new StringBuilder(); state = 37; break; } else { val.Append(c); } state = 30; break; case 35: goto case 38; case 36: goto case 38; case 37: goto case 38; case 38: if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) { charCodeHex.Append(c); if (++state > 38) { state = 30; charCode = (int)Convert.ToUInt32(charCodeHex.ToString(), 16); val.Append((char)charCode); charCodeHex = null; } break; } if (charCodeHex.Length > 0) { charCode = (int)Convert.ToUInt32(charCodeHex.ToString(), 16); val.Append((char)charCode); charCodeHex = null; } state = 30; goto case 30; // parsing a numeric value case 40: // possibly a hex/bin/octal value (starts with 0) if (c == 'x' || c == 'X') { ctype = ScriptLiteralTokenType.Hex; val.Clear(); state = 50; break; } if (c == 'b' || c == 'B') { ctype = ScriptLiteralTokenType.Binary; val.Clear(); state = 60; break; } if (c >= '0' && c <= '7') { ctype = ScriptLiteralTokenType.Octal; val.Clear(); val.Append(c); state = 70; break; } ctype = ScriptLiteralTokenType.Decimal; state = 42; goto case 42; case 41: // starts with - or + if (c == '.') { etype = ScriptVariableType.Double; val.Append(c); state = 43; break; } if (c >= '0' && c <= '9') { val.Append(c); state = 42; break; } return(0); case 42: // starts with a digit if (c == '.') { etype = ScriptVariableType.Double; state = 44; break; } if (c >= '0' && c <= '9') { val.Append(c); break; } if (c == 'F' || c == 'f') { etype = ScriptVariableType.Float; state = 100; break; } if (c == 'D' || c == 'd') { etype = ScriptVariableType.Double; state = 100; break; } if (c == 'L' || c == 'l') { etype = ScriptVariableType.Long; state = 100; break; } if (c == 'M' || c == 'm') { etype = ScriptVariableType.Decimal; state = 100; break; } if (c == 'U' || c == 'u') { etype = ScriptVariableType.UInt; state = 79; break; } pos--; state = 100; break; case 43: // starts with -. or just . if (c >= '0' && c <= '9') { val.Append(c); state = 45; break; } return(0); case 44: // first digit of the mantissa if (c >= '0' && c <= '9') { val.Append('.'); val.Append(c); state = 45; break; } pos -= 2; state = 100; break; case 45: // mantissa (only numbers allowed) if (c >= '0' && c <= '9') { val.Append(c); break; } if (c == 'F' || c == 'f') { etype = ScriptVariableType.Float; state = 100; break; } if (c == 'D' || c == 'd') { etype = ScriptVariableType.Double; state = 100; break; } if (c == 'L' || c == 'l') { etype = ScriptVariableType.Long; state = 100; break; } if (c == 'M' || c == 'm') { etype = ScriptVariableType.Decimal; state = 100; break; } if (c == 'U' || c == 'u') { etype = ScriptVariableType.UInt; state = 79; break; } pos--; state = 100; break; // hex value (0x...) case 50: if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) { val.Append(c); state = 51; break; } ctype = ScriptLiteralTokenType.Decimal; pos -= 2; state = 100; break; case 51: if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) { val.Append(c); break; } if (c == 'L' || c == 'l') { etype = ScriptVariableType.Long; state = 100; break; } if (c == 'U' || c == 'u') { etype = ScriptVariableType.UInt; state = 79; break; } pos--; state = 100; break; // bin value (0b...) case 60: if (c == '0' || c == '1') { val.Append(c); state = 61; break; } ctype = ScriptLiteralTokenType.Decimal; pos -= 2; state = 100; break; case 61: if (c == '0' || c == '1') { val.Append(c); break; } if (c == 'L' || c == 'l') { etype = ScriptVariableType.Long; state = 100; break; } if (c == 'U' || c == 'u') { etype = ScriptVariableType.UInt; state = 79; break; } pos--; state = 100; break; // octal value (0...) case 70: if (c >= '0' && c <= '7') { val.Append(c); break; } if (c == '8' || c == '9') { ctype = ScriptLiteralTokenType.Decimal; val.Append(c); state = 42; break; } if (c == '.') { ctype = ScriptLiteralTokenType.Decimal; state = 44; break; } if (c == 'L' || c == 'l') { etype = ScriptVariableType.Long; state = 100; break; } if (c == 'U' || c == 'u') { etype = ScriptVariableType.UInt; state = 79; break; } pos--; state = 100; break; case 79: // number suffix started with u or U if (c == 'L' || c == 'l') { etype = ScriptVariableType.ULong; state = 100; break; } pos--; state = 100; break; // null case 80: if (c == 'u') { state = 81; break; } return(0); case 81: if (c == 'l') { state = 82; break; } return(0); case 82: if (c == 'l') { val = new StringBuilder(); val.Append("null"); state = 100; break; } return(0); // true case 90: if (c == 'r') { state = 91; break; } return(0); case 91: if (c == 'u') { state = 92; break; } return(0); case 92: if (c == 'e') { val = new StringBuilder(); val.Append("true"); state = 100; break; } return(0); // false case 95: if (c == 'a') { state = 96; break; } return(0); case 96: if (c == 'l') { state = 97; break; } return(0); case 97: if (c == 's') { state = 98; break; } return(0); case 98: if (c == 'e') { val = new StringBuilder(); val.Append("false"); state = 100; break; } return(0); default: return(0); } } if (val == null) { return(0); } codeObj = new ScriptLiteralToken(val.ToString(), ctype, etype, Line, Symbol); return(pos - this.Position); }