我用Flex和Bison为扫描器/解析器编写了类似C语言的语言的解释器。当执行完整程序文件时它可以正常工作。
现在我正在尝试为解释器实现REPL以供交互使用。我希望它能像Ruby或ML中的命令行解释器一样工作:
- 显示提示符
- 接受一条或多条语句
- 如果表达式不完整
- 显示继续提示符
- 允许用户继续输入行
- 当行以完整表达式结尾时,
- 回显评估最后一个表达式的结果
- 显示主提示符
我的语法从top_level
开始,代表语言中的单个语句。 词法分析器被配置为在stdin上进行交互模式。 我在完整文件和REPL模式下都使用相同的扫描器和语法,因为两个界面没有语义上的区别。
我的主要评估循环结构如下。
while (!interpreter.done) {
if (interpreter.repl)
printf(prompt);
int status = yyparse(interpreter);
if (status) {
if (interpreter.error)
report_error(interpreter);
}
else {
if (interpreter.repl)
puts(interpreter.result);
}
}
除了提示和回显逻辑外,这段代码运行良好。如果用户在一行上输入多个语句,则此循环会打印出多余的提示和表达式。如果表达式跨越多行,则此代码不会打印出连续提示符。这些问题的发生是因为提示/回显逻辑的粒度是语法中的top_level
语句,但读取行的逻辑深入到词法分析器中。
如何重新构造评估循环以处理REPL提示和回显是最佳方法呢?也就是说:
- 如何每行显示一个提示符
- 如何在正确的时间显示继续提示
- 如何判断完整表达式是否是该行上的最后一个表达式
(我不想更改扫描器语言以传递换行符标记,因为那将严重改变语法。修改YY_INPUT
并向Bison语法添加几个操作将是可以接受的。此外,我正在使用带有Xcode的标准Flex 2.5.35和Bison 2.3。)