bash 如何处理解析错误?
How bash handle parsing errors?
对于上下文,我正在尝试创建一个过于简化的 bash 版本,不像 bash 完整的脚本解释器,只是一系列命令和运算符 (|,||, &&, <, >, <<, >>,$, $?)
小解释器,简而言之,我使用的心智模型是:
- Lexer + Expander:在第一阶段,我使用了一个简单的状态机来分析和存储数据(命令、参数、重定向文件等)并将 lex 输入到令牌中,我扩展了 env 变量,我也处理词法错误.(就像检查有效字符的有限状态一样简单)。
- 解析器:在第 i 个阶段,我打算从标记 + 数据中创建一个 AST,并处理解析错误。
- 执行者:最后我会执行AST。
不,我在解析器阶段,我正在考虑如何处理解析错误,现在我的想法超出了有效语句的可能范围,似乎很难检查这种输入的有效性导致范围太大或者至少我是这么认为的,而且我确信这个问题有一些通用的解决方案,为什么我确定?因为 bash 已经做到了。
例如这条语句:
$ < $FILE || && > outfile
从词法分析器的角度来看,这一切都是光明的,但从解析器的角度来看,它肯定不是有效输入。现在一个可能的解决方案是检查输入中是否有命令令牌,如果没有则无效。但是这个呢:
$ || ls > $FILE && cat < $FILE
所有有效的词素,但无法解析的语句,也许也可以针对“如果行以 OR 或 AND 标记错误开头”进行检查。
现在的具体问题是 如何 bash 准确解析这些命令和运算符的组合, 要么有某种更通用的解决方案,要么我只剩下针对输入的 if&else 错误检查我认为是无效的。老实说,这看起来既愚蠢又麻烦。
- 要准确地 理解 Bash 如何解析脚本,您需要查看 Bash 的源代码。对于 Bash 如何在越来越复杂的情况下工作,基本上有分形经验法则,任何短到适合 SO 响应的描述可能不够详细,无法为您提供完整的图片。
shell 解析的大部分复杂性在于标记化,尽管您当然不需要担心多年来出现的所有复杂情况。语法本身很简单;它旨在由使用 Bison(或其他一些 yacc 派生工具)等工具生成的解析器进行解析,这正是 Bash 的工作原理。
Bash识别的各种句法规则散布在Bash manual, but the grammar is based on the standard shell grammar specified in the Posix standard, which is probably an easier starting point. In that document, the grammar is included as what is basically a Yacc input file (without any of the semantic actions necessary for an actual implementation); you can find it at the end of section 2.10. Make sure to read the initial part of that section, though, because it contains important information about how tokens are classified. Also, take note of section 2.3, token recognition中。
在这两个部分之间,您将找到 shell 引用规则的精确描述以及在解析之前完成的各种扩展(或者,更好地说,与解析混合在一起,因为 command substitution整个过程是递归的。)你可能不想在第一次阅读时就吸收所有这些内容,尽管它也会帮助你更有效地使用 shell.
Bash 实现了更多的功能,但可能大部分或全部都超出了您的需要。
对于上下文,我正在尝试创建一个过于简化的 bash 版本,不像 bash 完整的脚本解释器,只是一系列命令和运算符 (|,||, &&, <, >, <<, >>,$, $?)
小解释器,简而言之,我使用的心智模型是:
- Lexer + Expander:在第一阶段,我使用了一个简单的状态机来分析和存储数据(命令、参数、重定向文件等)并将 lex 输入到令牌中,我扩展了 env 变量,我也处理词法错误.(就像检查有效字符的有限状态一样简单)。
- 解析器:在第 i 个阶段,我打算从标记 + 数据中创建一个 AST,并处理解析错误。
- 执行者:最后我会执行AST。
不,我在解析器阶段,我正在考虑如何处理解析错误,现在我的想法超出了有效语句的可能范围,似乎很难检查这种输入的有效性导致范围太大或者至少我是这么认为的,而且我确信这个问题有一些通用的解决方案,为什么我确定?因为 bash 已经做到了。
例如这条语句:
$ < $FILE || && > outfile
从词法分析器的角度来看,这一切都是光明的,但从解析器的角度来看,它肯定不是有效输入。现在一个可能的解决方案是检查输入中是否有命令令牌,如果没有则无效。但是这个呢:
$ || ls > $FILE && cat < $FILE
所有有效的词素,但无法解析的语句,也许也可以针对“如果行以 OR 或 AND 标记错误开头”进行检查。
现在的具体问题是 如何 bash 准确解析这些命令和运算符的组合, 要么有某种更通用的解决方案,要么我只剩下针对输入的 if&else 错误检查我认为是无效的。老实说,这看起来既愚蠢又麻烦。
shell 解析的大部分复杂性在于标记化,尽管您当然不需要担心多年来出现的所有复杂情况。语法本身很简单;它旨在由使用 Bison(或其他一些 yacc 派生工具)等工具生成的解析器进行解析,这正是 Bash 的工作原理。
Bash识别的各种句法规则散布在Bash manual, but the grammar is based on the standard shell grammar specified in the Posix standard, which is probably an easier starting point. In that document, the grammar is included as what is basically a Yacc input file (without any of the semantic actions necessary for an actual implementation); you can find it at the end of section 2.10. Make sure to read the initial part of that section, though, because it contains important information about how tokens are classified. Also, take note of section 2.3, token recognition中。
在这两个部分之间,您将找到 shell 引用规则的精确描述以及在解析之前完成的各种扩展(或者,更好地说,与解析混合在一起,因为 command substitution整个过程是递归的。)你可能不想在第一次阅读时就吸收所有这些内容,尽管它也会帮助你更有效地使用 shell.
Bash 实现了更多的功能,但可能大部分或全部都超出了您的需要。