字符串到令牌序列

本文关键字:令牌 字符串 | 更新日期: 2023-09-27 18:06:28

我正在解析命令序列字符串,需要将每个字符串转换为字符串[],该字符串将按照读取的顺序包含命令令牌。

原因是这些序列被存储在数据库中,以指示协议客户端为单个远程应用程序执行特定的指定序列。这些字符串中有一些特殊的令牌,我需要将它们添加到字符串[]中,因为它们不代表正在传输的数据;相反,它们表示阻塞暂停。

序列不包含分隔符。在命令序列中可以找到任意数量的特殊令牌,这就是为什么我不能简单地用regex解析字符串。此外,序列中的所有这些特殊命令都用${}

包装。下面是我需要解析为令牌的数据示例(P1表示阻塞暂停一秒钟):
"some data to transmit${P1}more data here"

结果数组应该是这样的:

{ "some data to transmit", "${P1}", "more data here" }

我认为LINQ可以帮助这个,但我不太确定。我能想到的唯一解决方案是循环遍历每个字符,直到找到$,然后检测是否有特殊的暂停命令,然后使用索引从那里解析序列。

字符串到令牌序列

一个选项是使用Regex.Split(str, @"('${.*?})")并忽略当你有两个特殊的令牌相邻时你得到的空字符串。

也许Regex.Split(str, @"('${.*?})").Where(s => s != "")是你想要的。

好了,正如评论中提到的,我建议您阅读有关lexer的内容。他们有能力做任何事情,甚至比你描述的还要多。

既然您的要求如此简单,我认为手工编写词法分析器并不太难。下面是一些可以这样做的伪代码。

IEnumerable<string> tokenize(string str) {
    var result = new List<string>();
    int pos = -1;
    int state = 0;
    int temp = -1;
    while( ++pos < str.Length ) {
        switch(state) {
            case 0:
                if( str[pos] == "$" ) { state = 1; temp = pos; }
                break;
            case 1:
                if( str[pos] == "{" ) { state = 2; } else { state = 0; }
                break;
            case 2:
                if( str[pos] == "}" } {
                    state = 0;
                    result.Add( str.Substring(0, temp) );
                    result.Add( str.Substring(temp, pos) );
                    str = str.Substring(pos);
                    pos = -1;
                }
                break;
            }
    }
    if( str != "" ) {
        result.Add(str);
    }
    return result;
}

或者类似的东西。我通常在第一次尝试时得到Substring的参数错误,但这是一般的想法。

您可以使用ANTLR之类的东西获得更强大(且更易于阅读)的词法分析器。

使用Gabe的一点点建议,我想出了一个解决方案,这正是我想要做的:

string tokenPattern = @"('${'w{1,4}})";
string cmdSequence = "${P}test${P}${P}test${P}${Cr}";
string[] tokenized = (from token in Regex.Split(cmdSequence, tokenPattern)
                      where token != string.Empty
                      select token).ToArray();
对于上面示例中的命令序列,数组包含以下内容:
{ "${P}", "test", "${P}", "${P}", "test", "${P}", "${Cr}"}