字符串到令牌序列
本文关键字:令牌 字符串 | 更新日期: 2023-09-27 18:06:28
我正在解析命令序列字符串,需要将每个字符串转换为字符串[],该字符串将按照读取的顺序包含命令令牌。
原因是这些序列被存储在数据库中,以指示协议客户端为单个远程应用程序执行特定的指定序列。这些字符串中有一些特殊的令牌,我需要将它们添加到字符串[]中,因为它们不代表正在传输的数据;相反,它们表示阻塞暂停。
序列不包含分隔符。在命令序列中可以找到任意数量的特殊令牌,这就是为什么我不能简单地用regex解析字符串。此外,序列中的所有这些特殊命令都用${}
"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}"}