diff --git a/Source/Core/Properties/AssemblyInfo.cs b/Source/Core/Properties/AssemblyInfo.cs index e3c96d8b903aac3ef77463fbbe68f580b1eae6d7..4d44e34792819ff0d6083ba48df8e91e64053c75 100755 --- a/Source/Core/Properties/AssemblyInfo.cs +++ b/Source/Core/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using CodeImp.DoomBuilder; // Build Number // Revision // -[assembly: AssemblyVersion("2.3.0.2827")] +[assembly: AssemblyVersion("2.3.0.2828")] [assembly: NeutralResourcesLanguageAttribute("en")] -[assembly: AssemblyHash("05a160b")] +[assembly: AssemblyHash("dc72c53")] diff --git a/Source/Core/ZDoom/ZScriptParser.cs b/Source/Core/ZDoom/ZScriptParser.cs index d3366181f852f9329952964747c1f9ee7ba4ded4..c0b92375c17c4acb55605394c22a90a100220e15 100755 --- a/Source/Core/ZDoom/ZScriptParser.cs +++ b/Source/Core/ZDoom/ZScriptParser.cs @@ -833,6 +833,7 @@ namespace CodeImp.DoomBuilder.ZDoom } // inject superclasses, since everything is parsed by now + Dictionary<int, ThingTypeInfo> things = General.Map.Config.GetThingTypes(); foreach (ZScriptClassStructure cls in allclasseslist) { ActorStructure actor = cls.Actor; @@ -843,7 +844,6 @@ namespace CodeImp.DoomBuilder.ZDoom if (actor.baseclass == null) { //check if this class inherits from a class defined in game configuration - Dictionary<int, ThingTypeInfo> things = General.Map.Config.GetThingTypes(); string inheritclasscheck = inheritclass.ToLowerInvariant(); bool thingfound = false; diff --git a/Source/Core/ZDoom/ZScriptTokenizer.cs b/Source/Core/ZDoom/ZScriptTokenizer.cs index 06d22b52c1ce950b65047b2b25366844f72b197f..8321a225bd8fd5d68531cbe909a7be11b4d3bae7 100755 --- a/Source/Core/ZDoom/ZScriptTokenizer.cs +++ b/Source/Core/ZDoom/ZScriptTokenizer.cs @@ -117,6 +117,7 @@ namespace CodeImp.DoomBuilder.ZDoom { private BinaryReader reader; private Dictionary<string, ZScriptTokenType> namedtokentypes; // these are tokens that have precise equivalent in the enum (like operators) + private Dictionary<ZScriptTokenType, string> namedtokentypesreverse; // these are tokens that have precise equivalent in the enum (like operators) private List<string> namedtokentypesorder; // this is the list of said tokens ordered by length. public long LastPosition { get; private set; } @@ -125,6 +126,7 @@ namespace CodeImp.DoomBuilder.ZDoom { reader = br; namedtokentypes = new Dictionary<string, ZScriptTokenType>(); + namedtokentypesreverse = new Dictionary<ZScriptTokenType, string>(); namedtokentypesorder = new List<string>(); // initialize the token type list. IEnumerable<ZScriptTokenType> tokentypes = Enum.GetValues(typeof(ZScriptTokenType)).Cast<ZScriptTokenType>(); @@ -136,6 +138,7 @@ namespace CodeImp.DoomBuilder.ZDoom if (attrs.Length == 0) continue; // namedtokentypes.Add(attrs[0].Value, tokentype); + namedtokentypesreverse.Add(tokentype, attrs[0].Value); namedtokentypesorder.Add(attrs[0].Value); } @@ -158,292 +161,402 @@ namespace CodeImp.DoomBuilder.ZDoom } } - public ZScriptToken ExpectToken(params ZScriptTokenType[] oneof) + private ZScriptToken TryReadWhitespace() { - long cpos = reader.BaseStream.Position; + long cpos = LastPosition = reader.BaseStream.Position; + char c = reader.ReadChar(); + + // + string whitespace = " \r\t\u00A0"; + + // check whitespace + if (whitespace.Contains(c)) + { + string ws_content = ""; + ws_content += c; + while (true) + { + char cnext = reader.ReadChar(); + if (whitespace.Contains(cnext)) + { + ws_content += cnext; + continue; + } + + reader.BaseStream.Position--; + break; + } - ZScriptToken tok = ReadToken(); - if (tok == null) return null; + ZScriptToken tok = new ZScriptToken(); + tok.Type = ZScriptTokenType.Whitespace; + tok.Value = ws_content; + return tok; + } - tok.IsValid = (oneof.Contains(tok.Type)); - if (!tok.IsValid) reader.BaseStream.Position = cpos; - return tok; + reader.BaseStream.Position = cpos; + return null; } - // short_circuit only checks for string literals and "everything else", reporting "everything else" as invalid tokens - public ZScriptToken ReadToken(bool short_circuit = false) + private ZScriptToken TryReadIdentifier() { - try + long cpos = LastPosition = reader.BaseStream.Position; + char c = reader.ReadChar(); + + // check identifier + if ((c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + (c == '_')) { - ZScriptToken tok; + string id_content = ""; + id_content += c; + while (true) + { + char cnext = reader.ReadChar(); + if ((cnext >= 'a' && cnext <= 'z') || + (cnext >= 'A' && cnext <= 'Z') || + (cnext == '_') || + (cnext >= '0' && cnext <= '9')) + { + id_content += cnext; + continue; + } - long cpos = reader.BaseStream.Position; // I really hope we can rewind this <_< - char c = reader.ReadChar(); - LastPosition = cpos; + reader.BaseStream.Position--; + break; + } - // - string whitespace = " \r\t\u00A0"; + ZScriptToken tok = new ZScriptToken(); + tok.Type = ZScriptTokenType.Identifier; + tok.Value = id_content; + return tok; + } - // check whitespace - if (whitespace.Contains(c)) + reader.BaseStream.Position = cpos; + return null; + } + + private ZScriptToken TryReadNumber() + { + long cpos = LastPosition = reader.BaseStream.Position; + char c = reader.ReadChar(); + + // check integer + if ((c >= '0' && c <= '9') || c == '.') + { + bool isint = true; + bool isdouble = (c == '.'); + bool isexponent = false; + if (isdouble) // make sure next character is an integer, otherwise its probably a member access { - string ws_content = ""; - ws_content += c; - while (true) + char cnext = reader.ReadChar(); + if (!(cnext >= '0' && cnext <= '9')) { - char cnext = reader.ReadChar(); - if (whitespace.Contains(cnext)) - { - ws_content += cnext; - continue; - } - + isint = false; reader.BaseStream.Position--; - break; } - - tok = new ZScriptToken(); - tok.Type = ZScriptTokenType.Whitespace; - tok.Value = ws_content; - return tok; } - if (!short_circuit) + if (isint) { - // check identifier - if ((c >= 'a' && c <= 'z') || - (c >= 'A' && c <= 'Z') || - (c == '_')) + bool isoctal = (c == '0'); + bool ishex = false; + string i_content = ""; + i_content += c; + while (true) { - string id_content = ""; - id_content += c; - while (true) + char cnext = reader.ReadChar(); + if (!isdouble && (cnext == 'x') && i_content.Length == 1) + { + isoctal = false; + ishex = true; + } + else if ((cnext >= '0' && cnext <= '7') || + (!isoctal && cnext >= '8' && cnext <= '9') || + (ishex && ((cnext >= 'a' && cnext <= 'f') || (cnext >= 'A' && cnext <= 'F')))) + { + i_content += cnext; + } + else if (!ishex && !isdouble && !isexponent && cnext == '.') + { + isdouble = true; + isoctal = false; + i_content += '.'; + } + else if (!isoctal && !ishex && !isexponent && (cnext == 'e' || cnext == 'E')) + { + isexponent = true; + isdouble = true; + i_content += 'e'; + cnext = reader.ReadChar(); + if (cnext == '-') i_content += '-'; + else reader.BaseStream.Position--; + } + else { - char cnext = reader.ReadChar(); - if ((cnext >= 'a' && cnext <= 'z') || - (cnext >= 'A' && cnext <= 'Z') || - (cnext == '_') || - (cnext >= '0' && cnext <= '9')) - { - id_content += cnext; - continue; - } - reader.BaseStream.Position--; break; } - - tok = new ZScriptToken(); - tok.Type = ZScriptTokenType.Identifier; - tok.Value = id_content; - return tok; } - // check integer - if ((c >= '0' && c <= '9') || c == '.') + ZScriptToken tok = new ZScriptToken(); + tok.Type = (isdouble ? ZScriptTokenType.Double : ZScriptTokenType.Integer); + tok.Value = i_content; + try { - bool isint = true; - bool isdouble = (c == '.'); - bool isexponent = false; - if (isdouble) // make sure next character is an integer, otherwise its probably a member access + if (ishex || isoctal || !isdouble) { - char cnext = reader.ReadChar(); - if (!(cnext >= '0' && cnext <= '9')) - { - isint = false; - reader.BaseStream.Position--; - } + int numbase = 10; + if (ishex) numbase = 16; + else if (isoctal) numbase = 8; + tok.ValueInt = Convert.ToInt32(tok.Value, numbase); + tok.ValueDouble = tok.ValueInt; + } + else if (isdouble) + { + string dval = (tok.Value[0] == '.') ? "0" + tok.Value : tok.Value; + tok.ValueDouble = Convert.ToDouble(dval); + tok.ValueInt = (int)tok.ValueDouble; } + } + catch (Exception) + { + //throw new Exception(tok.ToString()); + return null; + } + + return tok; + } + } + + reader.BaseStream.Position = cpos; + return null; + } + + private ZScriptToken TryReadStringOrComment(bool allowstring, bool allowname, bool allowblock, bool allowline) + { + long cpos = LastPosition = reader.BaseStream.Position; + char c = reader.ReadChar(); - if (isint) + switch (c) + { + case '/': // comment + { + if (!allowblock && !allowline) break; + char cnext = reader.ReadChar(); + if (cnext == '/') { - bool isoctal = (c == '0'); - bool ishex = false; - string i_content = ""; - i_content += c; + if (!allowline) break; + // line comment: read until newline but not including it + string cmt = ""; while (true) { - char cnext = reader.ReadChar(); - if (!isdouble && (cnext == 'x') && i_content.Length == 1) - { - isoctal = false; - ishex = true; - } - else if ((cnext >= '0' && cnext <= '7') || - (!isoctal && cnext >= '8' && cnext <= '9') || - (ishex && ((cnext >= 'a' && cnext <= 'f') || (cnext >= 'A' && cnext <= 'F')))) - { - i_content += cnext; - } - else if (!ishex && !isdouble && !isexponent && cnext == '.') - { - isdouble = true; - isoctal = false; - i_content += '.'; - } - else if (!isoctal && !ishex && !isexponent && (cnext == 'e' || cnext == 'E')) - { - isexponent = true; - isdouble = true; - i_content += 'e'; - cnext = reader.ReadChar(); - if (cnext == '-') i_content += '-'; - else reader.BaseStream.Position--; - } - else + cnext = reader.ReadChar(); + if (cnext == '\n') { reader.BaseStream.Position--; break; } - } - tok = new ZScriptToken(); - tok.Type = (isdouble ? ZScriptTokenType.Double : ZScriptTokenType.Integer); - tok.Value = i_content; - try - { - if (ishex || isoctal || !isdouble) - { - int numbase = 10; - if (ishex) numbase = 16; - else if (isoctal) numbase = 8; - tok.ValueInt = Convert.ToInt32(tok.Value, numbase); - tok.ValueDouble = tok.ValueInt; - } - else if (isdouble) - { - string dval = (tok.Value[0] == '.') ? "0" + tok.Value : tok.Value; - tok.ValueDouble = Convert.ToDouble(dval); - tok.ValueInt = (int)tok.ValueDouble; - } - } - catch (Exception) - { - //throw new Exception(tok.ToString()); - return null; + cmt += cnext; } + ZScriptToken tok = new ZScriptToken(); + tok.Type = ZScriptTokenType.LineComment; + tok.Value = cmt; return tok; } - } - } - - // check everything else - switch (c) - { - case '\n': // newline + else if (cnext == '*') { - ZScriptToken newline = new ZScriptToken(); - newline.Type = ZScriptTokenType.Newline; - newline.Value += c; - return newline; - } - - case '/': // comment - { - char cnext = reader.ReadChar(); - if (cnext == '/') + if (!allowblock) break; + // block comment: read until closing sequence + string cmt = ""; + while (true) { - // line comment: read until newline but not including it - string cmt = ""; - while (true) + cnext = reader.ReadChar(); + if (cnext == '*') { - cnext = reader.ReadChar(); - if (cnext == '\n') - { - reader.BaseStream.Position--; + char cnext2 = reader.ReadChar(); + if (cnext2 == '/') break; - } - cmt += cnext; + reader.BaseStream.Position--; } - tok = new ZScriptToken(); - tok.Type = ZScriptTokenType.LineComment; - tok.Value = cmt; - return tok; + cmt += cnext; } - else if (cnext == '*') - { - // block comment: read until closing sequence - string cmt = ""; - while (true) - { - cnext = reader.ReadChar(); - if (cnext == '*') - { - char cnext2 = reader.ReadChar(); - if (cnext2 == '/') - break; - - reader.BaseStream.Position--; - } - - cmt += cnext; - } - tok = new ZScriptToken(); - tok.Type = ZScriptTokenType.BlockComment; - tok.Value = cmt; - return tok; - } - break; + ZScriptToken tok = new ZScriptToken(); + tok.Type = ZScriptTokenType.BlockComment; + tok.Value = cmt; + return tok; } + break; + } - case '"': - case '\'': + case '"': + case '\'': + { + if ((c == '"' && !allowstring) || (c == '\'' && !allowname)) break; + ZScriptTokenType type = (c == '"' ? ZScriptTokenType.String : ZScriptTokenType.Name); + string s = ""; + while (true) { - ZScriptTokenType type = (c == '"' ? ZScriptTokenType.String : ZScriptTokenType.Name); - string s = ""; - while (true) + // todo: parse escape sequences properly + char cnext = reader.ReadChar(); + if (cnext == '\\') // escape sequence. right now, do nothing { - // todo: parse escape sequences properly - char cnext = reader.ReadChar(); - if (cnext == '\\') // escape sequence. right now, do nothing - { - cnext = reader.ReadChar(); - s += cnext; - } - else if (cnext == c) - { - tok = new ZScriptToken(); - tok.Type = type; - tok.Value = s; - return tok; - } - else s += cnext; + cnext = reader.ReadChar(); + s += cnext; + } + else if (cnext == c) + { + ZScriptToken tok = new ZScriptToken(); + tok.Type = type; + tok.Value = s; + return tok; } + else s += cnext; } + } + + } + + reader.BaseStream.Position = cpos; + return null; + } + + private ZScriptToken TryReadNamedToken() + { + long cpos = LastPosition = reader.BaseStream.Position; + // named tokens + char[] namedtoken_buf = reader.ReadChars(namedtokentypesorder[0].Length); + string namedtoken = new string(namedtoken_buf); + foreach (string namedtokentype in namedtokentypesorder) + { + if (namedtoken.StartsWith(namedtokentype)) + { + // found the token. + reader.BaseStream.Position = cpos + namedtokentype.Length; + ZScriptToken tok = new ZScriptToken(); + tok.Type = namedtokentypes[namedtokentype]; + tok.Value = namedtokentype; + return tok; } + } - reader.BaseStream.Position = cpos; + reader.BaseStream.Position = cpos; + return null; + } - if (!short_circuit) + public ZScriptToken ExpectToken(params ZScriptTokenType[] oneof) + { + long cpos = reader.BaseStream.Position; + + try + { + // try to expect whitespace + if (oneof.Contains(ZScriptTokenType.Whitespace)) + { + ZScriptToken tok = TryReadWhitespace(); + if (tok != null) return tok; + } + + // try to expect an identifier + if (oneof.Contains(ZScriptTokenType.Identifier)) + { + ZScriptToken tok = TryReadIdentifier(); + if (tok != null) return tok; + } + + bool blinecomment = oneof.Contains(ZScriptTokenType.LineComment); + bool bblockcomment = oneof.Contains(ZScriptTokenType.BlockComment); + bool bstring = oneof.Contains(ZScriptTokenType.String); + bool bname = oneof.Contains(ZScriptTokenType.Name); + + if (bstring || bname || bblockcomment || blinecomment) + { + // try to expect a string + ZScriptToken tok = TryReadStringOrComment(bstring, bname, bblockcomment, blinecomment); + if (tok != null) return tok; + } + + // if we are expecting a number (double or int), try to read it + if (oneof.Contains(ZScriptTokenType.Integer) || oneof.Contains(ZScriptTokenType.Double)) { - // named tokens - char[] namedtoken_buf = reader.ReadChars(namedtokentypesorder[0].Length); - string namedtoken = new string(namedtoken_buf); - foreach (string namedtokentype in namedtokentypesorder) + ZScriptToken tok = TryReadNumber(); + if (tok != null && oneof.Contains(tok.Type)) return tok; + } + + // try to expect special tokens + // read max + char[] namedtoken_buf = reader.ReadChars(namedtokentypesorder[0].Length); + string namedtoken = new string(namedtoken_buf); + foreach (ZScriptTokenType expected in oneof) + { + // check if there is a value for this one + if (!namedtokentypesreverse.ContainsKey(expected)) + continue; + string namedtokentype = namedtokentypesreverse[expected]; + if (namedtoken.StartsWith(namedtokentype)) { - if (namedtoken.StartsWith(namedtokentype)) - { - // found the token. - reader.BaseStream.Position = cpos + namedtokentype.Length; - tok = new ZScriptToken(); - tok.Type = namedtokentypes[namedtokentype]; - tok.Value = namedtokentype; - return tok; - } + // found the token. + reader.BaseStream.Position = cpos + namedtokentype.Length; + ZScriptToken tok = new ZScriptToken(); + tok.Type = namedtokentypes[namedtokentype]; + tok.Value = namedtokentype; + return tok; } } + } + catch (IOException) + { + reader.BaseStream.Position = cpos; + return null; + } + + // token was not found, try to read the token that was actually found and return that + reader.BaseStream.Position = cpos; + ZScriptToken invalid = ReadToken(); + invalid.IsValid = false; + reader.BaseStream.Position = cpos; + return invalid; + } + + // short_circuit only checks for string literals and "everything else", reporting "everything else" as invalid tokens + public ZScriptToken ReadToken(bool short_circuit = false) + { + try + { + ZScriptToken tok; + + // + tok = TryReadWhitespace(); + if (tok != null) return tok; + + if (!short_circuit) + { + tok = TryReadIdentifier(); + if (tok != null) return tok; + + tok = TryReadNumber(); + if (tok != null) return tok; + } + + tok = TryReadStringOrComment(true, true, true, true); + if (tok != null) return tok; + + if (!short_circuit) + { + tok = TryReadNamedToken(); + if (tok != null) return tok; + } // token not found. tok = new ZScriptToken(); tok.Type = ZScriptTokenType.Invalid; - tok.Value = "" + c; + tok.Value = "" + reader.ReadChar(); tok.IsValid = false; - reader.BaseStream.Position = cpos+1; return tok; } catch (IOException) diff --git a/Source/Plugins/BuilderModes/Properties/AssemblyInfo.cs b/Source/Plugins/BuilderModes/Properties/AssemblyInfo.cs index b4cf7c92c170afcb6ca85a89e7be6a1a38c8a937..49e3e16f68e3087f188d635a006544b7c882ce0b 100755 --- a/Source/Plugins/BuilderModes/Properties/AssemblyInfo.cs +++ b/Source/Plugins/BuilderModes/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Resources; // Build Number // Revision // -[assembly: AssemblyVersion("2.3.0.2827")] +[assembly: AssemblyVersion("2.3.0.2828")] [assembly: NeutralResourcesLanguageAttribute("en")]