public static Symbol LookupSymbol(Node tree, string identifier, bool strongonly) { Match ident = identifierRegex.Match(identifier); if (!ident.Success) { throw new Exception("Invalid identifier specified " + identifier); } if (!identifier.Contains("::")) { Node classNode = FindNode(tree, ident.Captures[0].Value); if (classNode == null) { if (strongonly) { throw new Exception("Invalid weak symbol " + identifier); } else { return new WeakSymbol(identifier); } } else { return new StrongSymbol(classNode); } } else { ident = fullIdentRegex.Match(identifier); if (!ident.Success) { throw new Exception("Couldn't parse full identifier"); } Node classNode = FindNode(tree, ident.Groups["class"].Value); if (classNode == null) { throw new Exception("Invalid class in identifier " + identifier); } Node propNode = FindNode(classNode, ident.Groups["name"].Value); if (propNode == null) { throw new Exception("Invalid property in identifier " + identifier); } return new StrongSymbol(classNode, propNode); } throw new Exception("Invalid symbol"); }
public void EmitNode(Node n, StringBuilder sb, int level) { if (n is ClassNode) { EmitClassNode(n as ClassNode, sb, level); } else if (n is EnumNode) { EmitEnumNode(n as EnumNode, sb); } }
public void EmitEnums(Node root, StringBuilder sb) { sb.AppendLine("// Generated code"); sb.AppendLine("// DO NOT EDIT"); sb.AppendLine(); sb.AppendLine("package internal"); sb.AppendLine(); foreach (Node n in root.childNodes) { EmitEnumNode(n as EnumNode, sb); } }
// single level private static Node FindNode(Node tree, string symbol) { foreach (Node child in tree.childNodes) { if (child.Name == symbol) { return child; } } return null; }
public void EmitEnums(Node root, StringBuilder sb) { sb.AppendLine("// Generated code"); sb.AppendLine("// DO NOT EDIT"); sb.AppendLine(); sb.AppendLine("package steamlang"); sb.AppendLine(); sb.AppendLine("import ("); sb.AppendLine(" \"strings\""); sb.AppendLine(" \"sort\""); sb.AppendLine(" \"fmt\""); sb.AppendLine(")"); sb.AppendLine(); foreach (Node n in root.childNodes) { EmitEnumNode(n as EnumNode, sb); } }
public void EmitClasses(Node root, StringBuilder sb) { sb.AppendLine("// Generated code"); sb.AppendLine("// DO NOT EDIT"); sb.AppendLine(); sb.AppendLine("package internal"); sb.AppendLine(); sb.AppendLine("import ("); sb.AppendLine(" \"io\""); sb.AppendLine(" \"encoding/binary\""); sb.AppendLine(" \"code.google.com/p/goprotobuf/proto\""); sb.AppendLine(" . \"github.com/manveru/go-steam/steamid\""); sb.AppendLine(")"); sb.AppendLine(); foreach (Node n in root.childNodes) { EmitClassNode(n as ClassNode, sb); } }
public void EmitClasses(Node root, StringBuilder sb) { sb.AppendLine("// Generated code"); sb.AppendLine("// DO NOT EDIT"); sb.AppendLine(); sb.AppendLine("package steamlang"); sb.AppendLine(); sb.AppendLine("import ("); sb.AppendLine(" \"io\""); sb.AppendLine(" \"encoding/binary\""); sb.AppendLine(" \"github.com/golang/protobuf/proto\""); sb.AppendLine(" \"github.com/Philipp15b/go-steam/steamid\""); sb.AppendLine(" \"github.com/Philipp15b/go-steam/rwu\""); sb.AppendLine(" . \"github.com/Philipp15b/go-steam/internal/protobuf\""); sb.AppendLine(")"); sb.AppendLine(); foreach (Node n in root.childNodes) { EmitClassNode(n as ClassNode, sb); } }
public static void Main(string[] args) { if (args.Length < 2) { Console.WriteLine("Must have at least two parameters: SteamKit root path and output path!"); return; } string steamKitPath = Path.GetFullPath(args[0]); string languagePath = Path.Combine(steamKitPath, "Resources", "SteamLanguage"); string outputPath = Path.GetFullPath(args[1]); Environment.CurrentDirectory = languagePath; var codeGen = new GoGen(args.Length > 2 && args[2] == "debug"); Queue<Token> tokenList = LanguageParser.TokenizeString(File.ReadAllText("steammsg.steamd")); Node root = TokenAnalyzer.Analyze(tokenList); Node rootEnumNode = new Node(); Node rootMessageNode = new Node(); rootEnumNode.childNodes.AddRange(root.childNodes.Where(n => n is EnumNode)); rootMessageNode.childNodes.AddRange(root.childNodes.Where(n => n is ClassNode)); StringBuilder enumBuilder = new StringBuilder(); StringBuilder messageBuilder = new StringBuilder(); codeGen.EmitEnums(rootEnumNode, enumBuilder); codeGen.EmitClasses(rootMessageNode, messageBuilder); string outputEnumFile = Path.Combine(outputPath, "enums.go"); string outputMessageFile = Path.Combine(outputPath, "messages.go"); Directory.CreateDirectory(Path.GetDirectoryName(outputEnumFile)); File.WriteAllText(Path.Combine(steamKitPath, outputEnumFile), enumBuilder.ToString()); File.WriteAllText(Path.Combine(steamKitPath, outputMessageFile), messageBuilder.ToString()); }
public static Node Analyze( Queue<Token> tokens ) { Node root = new Node(); while (tokens.Count > 0) { Token cur = tokens.Dequeue(); switch (cur.Name) { case "EOF": break; case "preprocess": Token text = Expect(tokens, "string"); if (cur.Value == "import") { Queue<Token> parentTokens = LanguageParser.TokenizeString( File.ReadAllText( text.Value ) ); Node newRoot = Analyze( parentTokens ); foreach (Node child in newRoot.childNodes) { root.childNodes.Add(child); } } break; case "identifier": switch (cur.Value) { case "class": { Token name = Expect(tokens, "identifier"); Token ident = null, parent = null; Token op1 = Optional(tokens, "operator", "<"); if (op1 != null) { ident = Expect(tokens, "identifier"); Token op2 = Expect(tokens, "operator", ">"); } Token expect = Optional(tokens, "identifier", "expects"); if (expect != null) { parent = Expect(tokens, "identifier"); } ClassNode cnode = new ClassNode(); cnode.Name = name.Value; if (ident != null) { cnode.Ident = SymbolLocator.LookupSymbol(root, ident.Value, false); } if (parent != null) { //cnode.Parent = SymbolLocator.LookupSymbol(root, parent.Value, true); } root.childNodes.Add(cnode); ParseInnerScope(tokens, cnode, root); } break; case "enum": { Token name = Expect(tokens, "identifier"); Token datatype = null; Token op1 = Optional(tokens, "operator", "<"); if (op1 != null) { datatype = Expect(tokens, "identifier"); Token op2 = Expect(tokens, "operator", ">"); } Token flag = Optional( tokens, "identifier", "flags" ); EnumNode enode = new EnumNode(); enode.Name = name.Value; if ( flag != null ) { enode.Flags = flag.Value; } if (datatype != null) { enode.Type = SymbolLocator.LookupSymbol(root, datatype.Value, false); } root.childNodes.Add(enode); ParseInnerScope(tokens, enode, root); } break; } break; } } return root; }
private static void ParseInnerScope(Queue<Token> tokens, Node parent, Node root) { Token scope1 = Expect(tokens, "operator", "{"); Token scope2 = Optional(tokens, "operator", "}"); while (scope2 == null) { PropNode pnode = new PropNode(); Token t1 = tokens.Dequeue(); Token t1op1 = Optional(tokens, "operator", "<"); Token flagop = null; if (t1op1 != null) { flagop = Expect(tokens, "identifier"); Token t1op2 = Expect(tokens, "operator", ">"); pnode.FlagsOpt = flagop.Value; } Token t2 = Optional(tokens, "identifier"); Token t3 = Optional(tokens, "identifier"); if (t3 != null) { pnode.Name = t3.Value; pnode.Type = SymbolLocator.LookupSymbol(root, t2.Value, false); pnode.Flags = t1.Value; } else if (t2 != null) { pnode.Name = t2.Value; pnode.Type = SymbolLocator.LookupSymbol(root, t1.Value, false); } else { pnode.Name = t1.Value; } Token defop = Optional(tokens, "operator", "="); if ( defop != null ) { while ( true ) { Token value = tokens.Dequeue(); pnode.Default.Add( SymbolLocator.LookupSymbol( root, value.Value, false ) ); if ( Optional( tokens, "operator", "|" ) != null ) continue; Expect( tokens, "terminator", ";" ); break; } } else { Expect( tokens, "terminator", ";" ); } Token obsolete = Optional( tokens, "identifier", "obsolete" ); if ( obsolete != null ) { pnode.Obsolete = ""; Token obsoleteReason = Optional( tokens, "string" ); if ( obsoleteReason != null ) pnode.Obsolete = obsoleteReason.Value; } parent.childNodes.Add(pnode); scope2 = Optional(tokens, "operator", "}"); } }
public static void EmitCode(Node root, ICodeGen gen, StringBuilder sb, string nspace, bool supportsGC, bool internalFile ) { gen.EmitNamespace(sb, false, nspace); int level = 0; if (gen.SupportsNamespace()) level = 1; if ( internalFile ) gen.EmitSerialBase( sb, level, supportsGC ); foreach (Node n in root.childNodes) { gen.EmitNode(n, sb, level); } gen.EmitNamespace(sb, true, nspace); }
public StrongSymbol(Node classNode, Node prop) { Class = classNode; Prop = prop; }
public StrongSymbol(Node classNode) { Class = classNode; }
private static void ParseInnerScope(Queue<Token> tokens, Node parent, Node root) { Token scope1 = Expect(tokens, "operator", "{"); Token scope2 = Optional(tokens, "operator", "}"); while (scope2 == null) { PropNode pnode = new PropNode(); Token t1 = tokens.Dequeue(); Token t1op1 = Optional(tokens, "operator", "<"); Token flagop = null; if (t1op1 != null) { flagop = Expect(tokens, "identifier"); Token t1op2 = Expect(tokens, "operator", ">"); pnode.FlagsOpt = flagop.Value; } Token t2 = Optional(tokens, "identifier"); Token t3 = Optional(tokens, "identifier"); if (t3 != null) { pnode.Name = t3.Value; pnode.Type = SymbolLocator.LookupSymbol(root, t2.Value, false); pnode.Flags = t1.Value; } else if (t2 != null) { pnode.Name = t2.Value; pnode.Type = SymbolLocator.LookupSymbol(root, t1.Value, false); } else { pnode.Name = t1.Value; } Token defop = Optional(tokens, "operator", "="); if (defop != null) { Token value = tokens.Dequeue(); pnode.Default = SymbolLocator.LookupSymbol(root, value.Value, false); } Expect(tokens, "terminator", ";"); parent.childNodes.Add(pnode); scope2 = Optional(tokens, "operator", "}"); } }