在.NET中解析VB6代码

5

我有一个用C#编写的WPF项目,为了获取有关外部依赖项的一些信息,我需要解析VB6脚本。脚本的位置会发生变化,内容也会有所改变,但我感兴趣的主要代码格式将如下:

Select Case Fields("blah").Value
    Case "Some value"
        Fields("other blah").List = Lists("a list name")
    ...
End Select

我需要从中提取出当字段“blah”设置为“some value”时,字段“other blah”的列表更改为列表“a list name”。我尝试在谷歌上搜索VB6解析器,以便作为.NET库编写,但是还没有找到任何东西。冒着得到像这样的答案的风险,我是否应该只使用正则表达式来查找VB6脚本中的此类代码,并提取所需数据?该代码在子程序中找到,因此我无法传入“blah”,“some value”并返回“other blah”,“a list name”。我对此VB6脚本的内容无法控制。

参见这个问题。例如,有一个VBScript语法,以及第三方商业VB6解析器 - MarkJ
1个回答

4

您可以通过几个步骤来解析它。请注意,正则表达式可能会忽略字符串和注释,因此请谨慎使用。

首先,我们将使用一个辅助类处理Fields("Target").List = Lists("Value")行:

class ListData
{
    public string Target { get; set; }
    public string Value { get; set; }
}

输出模式:

string patternSelectCase = @"
Select\s+Case\s+Fields\(""(?<CaseField>[\w\s]+)""\)\.Value
(?<Cases>.*?)
End\s+Select
";

string patternCase = @"
Case\s+""(?<Case>[\w\s]+)""\s+
(?:Fields\(""(?<Target>[\w\s]+)""\)\.List\s*=\s*Lists\(""(?<Value>[\w\s]+)""\)\s+)*
";

接下来,我们可以尝试通过两次解析文本(代码可能有点丑陋,但相当基础):

MatchCollection matches = Regex.Matches(vb, patternSelectCase,
        RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | 
        RegexOptions.Singleline);

Console.WriteLine(matches.Count);

var data = new Dictionary<String, Dictionary<String, List<ListData>>>();
foreach (Match match in matches)
{
    var caseData = new Dictionary<String, List<ListData>>();
    string caseField = match.Groups["CaseField"].Value;
    string cases = match.Groups["Cases"].Value;

    MatchCollection casesMatches = Regex.Matches(cases, patternCase,
             RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | 
             RegexOptions.Singleline);
    foreach (Match caseMatch in casesMatches)
    {
        string caseTitle = caseMatch.Groups["Case"].Value;
        var targetCaptures = caseMatch.Groups["Target"].Captures.Cast<Capture>();
        var valueCaptures = caseMatch.Groups["Value"].Captures.Cast<Capture>();
        caseData.Add(caseTitle, targetCaptures.Zip(valueCaptures, (t, v) =>
            new ListData
            {
                Target = t.Value,
                Value = v.Value
            }).ToList());
    }

    data.Add(caseField, caseData);
}

现在你拥有一个包含所有数据的字典。例如:
string s = data["foo"]["Some value2"].First().Value;

下面是一个可行的示例:https://gist.github.com/880148

谢谢!这些正则表达式很棒,比我想出来的更全面。因为我使用的是.NET 3.5(我没有说明,抱歉),所以我不得不从http://weblogs.thinktecture.com/cnagel/2010/02/linq-with-net-4-zip.html添加了一个Zip扩展方法。我需要修改我的匹配并可能有一个新的正则表达式来处理“Case Else”,因为它也会出现(我在原始问题中没有提到)。 - Sarah Vessels

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接