public static void Visit(CompileResult compileResult, VisitorCallback callback) { if (compileResult == null) { throw new ArgumentNullException(nameof(compileResult)); } var program = compileResult.Program; if (compileResult.Program == null) { throw new ArgumentNullException(nameof(compileResult)); } var modules = program.getModules(); var visitor = new VB6ASTTreeViewGeneratorVisitor(callback); for (int i = 0; i < modules.size(); i++) { var module = (ModuleImpl)modules.get(i); var ctx = module.getCtx(); visitor.visit(ctx); } }
// This method looks up the depth of the $CONTENT identifier. // We use it to determine where to cut relative paths. // TODO: Parse wrapper only once, not one time per pattern. Well, it hardly matters for performance I think, so leave it. public void SetCutDepthAndCutPath() { var wrapperCompileResult = VB6Compiler.Compile("Test.bas", vbWrapperCode, false); var translator = new Translator(wrapperCompileResult); DebugClass.LogError("SetCutDepthAndCutPath: " + vbWrapperCode); var visitorCallback = new VisitorCallback() { Callback = (node, parent) => { var identifier = node.getText().Trim('"').Trim(); //if (identifier == Content) var path = translator.GetExtendedPathList(node); DebugClass.LogError("SetCutDepthAndCutPath: " + VbCode + ": " + PrintPath(path)); if (identifier == Content) { // Exact match if (path[path.Count - 1].NodeTypeName == "VsICSContext") { cutDepthOfContent = path.Count - 1; DebugClass.LogError("SetCutDepth: MATCH"); } // Bounded if (!PathContains(path, "VsICSContext")) { cutDepthOfContent = path.Count; DebugClass.LogError("SetCutDepth: BOUND MATCH"); } cutPath = path.Take(cutDepthOfContent).ToList(); } } }; // First time is to set cutDepthOfContent VB6Compiler.Visit(wrapperCompileResult, visitorCallback); // Second time is to set cutPath VB6Compiler.Visit(wrapperCompileResult, visitorCallback); if (cutDepthOfContent == -1) { throw new InvalidOperationException(nameof(cutDepthOfContent) + " not initialized"); } }
private void frmVB6ASTBrowser_Load(object sender, EventArgs e) { var compileResult = VB6Compiler.Compile(FileName, null, false); nodeMap = new Dictionary <ParseTree, TreeNode>(); translator = new Translator(compileResult); var visitorCallback = new VisitorCallback() { Callback = (node, parent) => { var name = VbToCsharpPattern.LookupNodeType(node); var lines = node.getText().Split('\n'); string firstLine = (lines.Length > 0) ? lines[0] : ""; if (parent != null && nodeMap.ContainsKey(parent)) { var tvNode = nodeMap[parent].Nodes.Add(nodeMap.Count.ToString(new NumberFormatInfo()), name + ": " + firstLine); tvNode.Tag = node; nodeMap[node] = tvNode; } else { var tvNode = treVB6AST.Nodes.Add(nodeMap.Count.ToString(new NumberFormatInfo()), name + ": " + firstLine); tvNode.Tag = node; nodeMap[node] = tvNode; } //nodes.Add(node); } }; txtDebug.ScrollBars = ScrollBars.Both; VB6Compiler.Visit(compileResult, visitorCallback); //treVB6AST.ExpandAll(); }
public static List <ImmutableList <IndexedPath> > GetExtendedPathList(ParseTree pnode) { var paths = new List <ImmutableList <IndexedPath> >(); ParseTree root = null; VB6NodeTree nodeTree = new VB6NodeTree(pnode); var visitorCallback = new VisitorCallback() { Callback = (node, parent) => { if (root == null) { root = node; } paths.Add(nodeTree.GetPath(node)); } }; var visitor = new VB6ASTTreeViewGeneratorVisitor(visitorCallback); visitor.visit(pnode); return(paths); }
public void VbParsePattern(string pattern) { SetCutDepthAndCutPath(); var code = vbWrapperCode.Replace(Content, pattern); var compileResult = VB6Compiler.Compile("Test.bas", code, false); var translator = new Translator(compileResult); PatternIdentifiers = GetIdentifiersAndSetTokens(translator, compileResult); var paths = new List <IndexedPath> [PatternIdentifiers.Length]; ParseTree root = null; DebugClass.LogError("PATTERN: " + VbCode); var visitorCallback = new VisitorCallback() { Callback = (node, parent) => { DebugClass.LogError("Node: " + PrintPath(translator.GetExtendedPathList(node)) + ": " + node.getText()); if (root == null) { root = node; } var i = 0; foreach (var identifier in PatternIdentifiers) { if (node.getText().Trim('"') == identifier && IsInsideSubOrFunction(translator.GetExtendedPathList(node))) { var path = translator.GetExtendedPathList(node); if (paths[i] == null) { paths[i] = path; } } i++; } } }; VB6Compiler.Visit(compileResult, visitorCallback); var lowestCommonDepth = -1; var cutDepth = -1; var comparePath = paths.Length > 0 ? paths[0] : tokenPath; if (comparePath == null) { DebugClass.LogError("VB Code: " + VbCode); throw new InvalidOperationException(nameof(comparePath) + " is null"); } int commonDepth = Math.Min(cutPath.Count, comparePath.Count); for (int i = 0; i < commonDepth; i++) { DebugClass.LogError("COMPARE PATHS: " + PrintPath(cutPath)); foreach (var path in paths) { DebugClass.LogError("COMPARE PATHS: " + PrintPath(path)); } DebugClass.LogError(""); if (cutPath[i].NodeTypeName != comparePath[i].NodeTypeName) { break; } else { lowestCommonDepth = Math.Min(comparePath.Count - 1, i + 1); } } if (lowestCommonDepth >= comparePath.Count) { DebugClass.LogError("VB Code: " + VbCode + ", Identifier: " + PatternIdentifiers[0]); } VbTreeNodeType = comparePath[lowestCommonDepth].NodeTypeName; // Skip uninteresting wrapper nodes while (VbTreeNodeType == "VsICSContext" || VbTreeNodeType == "ImplicitCallStmt_InStmtContext") { lowestCommonDepth++; VbTreeNodeType = comparePath[lowestCommonDepth].NodeTypeName; } // VbTreeNodeType == "ICS_B_ProcedureCallContext") while (VbTreeNodeType == "ArgsCallContext" || VbTreeNodeType == "AmbiguousIdentifierContext") { lowestCommonDepth--; VbTreeNodeType = comparePath[lowestCommonDepth].NodeTypeName; } cutDepth = lowestCommonDepth + 1; finalCutDepthOfContent = cutDepth; var cutPaths = new List <IndexedPath> [PatternIdentifiers.Length]; var k = 0; foreach (var path in paths) { var cutPath = new List <IndexedPath>(); for (var i = cutDepth; i < path.Count; i++) { cutPath.Add(path[i]); } cutPaths[k] = cutPath; k++; } VbPaths = cutPaths; }
public string[] GetIdentifiersAndSetTokens(Translator translator, CompileResult compileResult) { var identifiers = new List <string>(); var tokensPerNode = new List <TokenInfo>(); //var tokens = new List<Tuple<int, string>>(); var seen = new Dictionary <string, bool>(); var visitorCallback = new VisitorCallback() { Callback = (node, parent) => { //if (node.GetType().Name == "AmbiguousIdentifierContext") var identifier = node.getText().Trim('"').Trim(); //DebugClass.Log("GetIdentifier: " + identifier); var path = translator.GetExtendedPathList(node); if (IsInsideSubOrFunction(path)) { if (identifier.Length == 1 && identifier.All(char.IsUpper)) { if (!seen.ContainsKey(identifier)) { seen[identifier] = true; if (identifier != ReservedLetterForDiscardedResults) { identifiers.Add(identifier); } } } else { // A general method will for each token add the parent node, and its path, // then extract this path for each token, extract all tokens from path and // check that the token exists in the extracted tokens. // Does this account for the order? Partly, it accounts for the order // within different nodes, but not multiple tokens within the same node. // So to handle that we need to group tokens by node. var tokens = GetTokens(node); if (tokens.Count > 0) { tokenPath = tokenPath ?? path; tokensPerNode.Add(new TokenInfo(path, tokens.Select(x => x.Item2).ToList())); DebugClass.LogError("TOKENS" + string.Join("@", tokens)); } } } } }; VB6Compiler.Visit(compileResult, visitorCallback); _patternTokens = tokensPerNode; if (cutDepthOfContent == -1) { throw new InvalidOperationException(nameof(cutDepthOfContent) + " not initialized"); } return(identifiers.ToArray()); }
public VB6ASTTreeViewGeneratorVisitor(VisitorCallback callback) { this.Callback = callback; }