如何用CUP与JFlex显示当前解析动作并满足作业输出要求?
解决CUP自定义归约动作输出(带产生式编号)的方案
当然有办法实现!我当初做编译原理作业用JFlex+CUP的时候,也碰到过默认调试输出不符合作业要求的情况,下面给你分享几个实用的解决思路:
一、直接在CUP产生式中添加归约输出动作
这是最直接也最适合作业场景的方法——给每个产生式手动添加输出代码,明确指定产生式编号。CUP允许在产生式的语义动作块里加入自定义代码,你只需要在每个产生式后面的{: :}块里添加打印语句即可。
比如针对你的示例文法,修改后的CUP代码片段如下:
// 给每个产生式分配编号,归约时输出对应信息 S ::= a X c {: System.out.println("归约:产生式1"); :}; X ::= b X {: System.out.println("归约:产生式2"); :}; X ::= b {: System.out.println("归约:产生式3"); :}; X ::= Y d {: System.out.println("归约:产生式4"); :}; Y ::= Y d {: System.out.println("归约:产生式5"); :}; Y ::= d {: System.out.println("归约:产生式6"); :};
这样每次触发对应产生式的归约动作时,就会精准输出你需要的格式,完全符合作业要求。
二、修改CUP生成的Parser类实现批量输出
如果你的文法产生式非常多,手动给每个产生式加动作太繁琐,可以直接修改CUP自动生成的Java Parser类:
- 找到生成的
Parser.java文件,定位到处理归约的核心方法(通常叫reduce或者类似的名称); - 在方法内部找到当前归约对应的产生式编号(CUP内部会维护产生式的索引);
- 添加打印语句,格式比如
System.out.println("归约:产生式" + 产生式编号);。
这个方法适合大规模文法,但需要你对CUP生成的代码结构有一定了解,调试起来稍微麻烦一点。
三、JFlex侧实现Token输出
至于词法单元(tokens)的输出,JFlex本身就可以轻松实现:在每个token匹配规则后面添加打印语句即可。示例JFlex规则片段:
"a" { System.out.println("Token: a"); return new Symbol(sym.a); } "b" { System.out.println("Token: b"); return new Symbol(sym.b); } "c" { System.out.println("Token: c"); return new Symbol(sym.c); } "d" { System.out.println("Token: d"); return new Symbol(sym.d); } // 其他规则...
这样词法分析阶段就会逐个输出识别到的token。
组合使用效果
把上面的词法输出和语法归约输出结合起来,输入abbbc时,你会得到类似这样的输出:
Token: a Token: b Token: b Token: b Token: c 归约:产生式3 归约:产生式2 归约:产生式2 归约:产生式1
完全满足作业要求的输出格式。
相比CUP自带的-debug选项输出的大量冗余内部信息,这种自定义输出的方式更清晰、更贴合作业需求,强烈推荐第一种方法(手动给产生式加动作),简单直接不容易出错。
内容的提问来源于stack exchange,提问作者84danie
相关产品推荐
相关产品推荐

