JavaCC生成的Adder程序执行时持续等待输入的问题求助
我来帮你梳理这个问题的核心原因和解决办法——你遇到的情况其实是JavaCC解析器对EOF的依赖加上Windows与Linux命令行输入处理的差异共同导致的,还有一个容易忽略的命令行参数使用误区。
首先澄清一个关键误区
你之前尝试运行java Adder 123 + 1时程序卡住,根本原因是原代码没有处理命令行参数!你的Adder类main方法里直接用System.in作为输入源,所以命令行里的123 + 1只是程序的启动参数,并没有被当作解析输入,程序仍然在等待你从控制台输入内容,自然会一直“空闲”。
为什么WSL里java Adder < input.txt能正常运行?
在Linux/WSL环境中,使用<进行输入重定向时,系统会把文件内容全部送入程序的标准输入,并且在文件末尾自动发送EOF(文件结束符)。你的BNF规则Start()要求必须读到<EOF>才会结束解析,所以WSL能满足这个条件,程序正常完成解析。
Windows下输入重定向失效的原因
Windows的命令提示符(cmd)和PowerShell对输入重定向的EOF处理和Linux有差异:直接用< input.txt时,可能没有正确向Java程序传递EOF信号,导致你的解析器一直等待输入结束,无法触发<EOF>匹配。
解决办法
这里提供几个实用的方案,按推荐程度排序:
1. 修改代码支持命令行参数(最通用)
直接让程序把命令行参数当作输入内容,彻底摆脱对系统输入重定向的依赖。修改你的Parser.jj里的Adder类:
PARSER_BEGIN(Adder) import java.io.StringReader; import java.io.Reader; import java.io.InputStreamReader; public class Adder { public static void main( String[] args ) throws ParseException, TokenMgrError { Reader input; if (args.length > 0) { // 将命令行参数拼接成一个完整的输入字符串 StringBuilder inputContent = new StringBuilder(); for (String arg : args) { inputContent.append(arg).append(" "); } // 使用字符串作为输入源 input = new StringReader(inputContent.toString().trim()); } else { // 没有参数时,仍读取标准输入(兼容手动输入场景) input = new InputStreamReader(System.in); } Adder parser = new Adder(input); parser.Start(); System.out.println("解析完成!"); } } PARSER_END(Adder)
修改后,你可以直接运行java Adder 123 + 1,程序会自动把参数拼接成输入内容,无需依赖输入重定向,Windows和WSL下都能正常工作。
2. 在Windows下用管道替代输入重定向
如果不想修改代码,在Windows环境中可以用管道命令传递输入,这样能确保EOF被正确发送:
- 在cmd中执行:
type input.txt | java Adder - 在PowerShell中执行:
Get-Content input.txt | java Adder
3. 手动输入时主动发送EOF
如果需要手动输入内容测试,输入完表达式后:
- Windows控制台:按
Ctrl+Z,然后回车,发送EOF信号 - Linux/WSL控制台:按
Ctrl+D发送EOF信号
这样程序就能识别到输入结束,完成解析。
额外检查点
确保你的input.txt内容没有多余的特殊字符,换行符用Windows格式(CRLF)还是Linux格式(LF)不影响,因为你的规则里已经SKIP了换行和空格。
内容的提问来源于stack exchange,提问作者Omnibyte

