我目前正在创建Linux shell以了解有关系统调用的更多信息。
我已经弄明白了大部分事情。解析器,令牌生成,将适当的事物传递给适当的系统调用 - 工作。
问题是,即使在我开始制作令牌之前,我将整个命令字符串拆分为单独的单词。它基于分离器阵列,效果出奇的好。除了我正在努力为它添加额外的功能,如转义序列或引号。我不能没有它,因为即使使用基本grep命令的人也使用带引号的参数。我需要添加以下功能:
' '
- 忽略在这两者之间找到的所有其他分隔符,运算符或双引号,将其作为一个字符串传递,不要在结果字中包含这些引号," "
- 与上述相同,但忽略单引号,\\
- 将其转换为单反斜杠,\(space)
- 将其转义为空格,不要将结果空格解析为分隔符\"
,\'
- 类似于上述内容。 它们中的每一个似乎都是一个例外。它们中的每一个必须在命令中可能的位置的多样性上操作,被包括在结果中与否,对其余的解析具有影响。它使我的代码看起来像泥泞的大球。
有更好的方法吗?是否有更通用的算法用于此目的?
答案 0 :(得分:1)
你正在尝试使用非传统的词法分析器解决程序分析(lexing和解析)中的经典问题(我将整个命令字符串分成单独的单词...... )。好的,那么你就会遇到非传统的麻烦,让词法分析者“正确”。
这并不意味着这种方式注定要失败,并且没有看到你的问题的具体实例,(你列出了一组你想要处理的结构,但没有说明为什么这些很难处理),它很难提供任何具体的建议。它也不意味着这种方式会带来成功;拆分该行可能会破坏不应该被破坏的令牌(通常是通过对已经被转义的内容感到困惑)。
使用标准词法分析器(例如Flex或any of the 1000 variants you can get)的关键在于它们提供了一种经过验证的方法来处理复杂的lexing问题,这通常基于人们可以使用常规的概念用于描述单个词位形状的表达式。因此,每个lexeme类型都有一个regexp,因此它们是海洋,但每个都很容易自己指定。
我使用强词法和解析器(使用该列表中的一个)完成了~~ 40种语言。我向你保证,标准方法在经验上非常有效。惊喜的类型很容易理解和管理。非标准方法总是存在以一种糟糕的方式让您感到惊讶的风险。
最后一句话:Unix的shell语言让人们在40年内添加了疯狂的东西。期望工作至少是中等难度,并且不要指望它像Wirth的原始Pascal一样。