使用Bison/Flex开发自定义语言解析器:如何返回主表达式结果?
问题分析与解决方案
你的问题核心在于fulloperation规则设计不合理:该规则仅在operation后跟随其他语句时才调用printres($1)输出结果,而单独的operation作为表达式语句时,仅生成表达式节点却未触发计算输出;同时规则的第一个分支未给$$赋值,会导致类型不匹配(expr期望ExprNode*类型)。
修改后的语法规则
移除冗余的fulloperation规则,直接在stmt的expr分支添加结果输出逻辑,同时保留递归表达式的解析能力:
%union{ IntNode intnode; RealNode realnode; StrNode strnode; ExprNode * exprNodePtr; int linenum; } %token <linenum> tADD %token <linenum> tSUB %token <linenum> tMUL %token <linenum> tDIV %token <strnode> tSTRING %token <intnode> tNUMI %token <realnode> tNUMR %token tPRINT tGET tSET tFUNCTION tRETURN tIDENT tEQUALITY tIF tGT tLT tGEQ tLEQ tINC tDEC %type <exprNodePtr> operation; %type <exprNodePtr> expr; %start prog %% prog: '[' stmtlst ']' ; ; stmtlst: stmtlst stmt | ; // 当expr作为顶层语句执行时,直接输出计算结果 stmt: setStmt | if | print | unaryOperation | expr { printres($1); } | returnStmt ; getExpr: '[' tGET ',' tIDENT ',' '[' exprList ']' ']' | '[' tGET ',' tIDENT ',' '[' ']' ']' | '[' tGET ',' tIDENT ']' ; setStmt: '[' tSET ',' tIDENT ',' expr ']' ; if: '[' tIF ',' condition ',' '[' stmtlst ']' ']' | '[' tIF ',' condition ',' '[' stmtlst ']' '[' stmtlst ']' ']' ; print: '[' tPRINT ',' expr ']' ; // operation直接作为expr的一部分,支持嵌套递归解析 operation: '[' tADD ',' expr ',' expr']' { $$ = SumExpr($4, $6); } | '[' tSUB ',' expr',' expr']'{ $$ = SubExpr($4, $6); } | '[' tMUL ',' expr ',' expr ']'{ $$ = MulExpr($4, $6); } | '[' tDIV ',' expr ',' expr ']'{ $$ = DivExpr($4, $6); } ; unaryOperation: '[' tINC ',' tIDENT ']' | '[' tDEC ',' tIDENT ']' ; expr: tNUMI {$$ = makeExpressionNodeFromInt($1);} | tNUMR {$$ = makeExpressionNodeFromReal($1);} | tSTRING {$$ = makeExpressionNodeFromStr($1);} | getExpr | function | operation {$$ = $1;} | condition ; function: '[' tFUNCTION ',' '[' parametersList ']' ',' '[' stmtlst ']' ']' | '[' tFUNCTION ',' '[' ']' ',' '[' stmtlst ']' ']' ; condition: '[' tEQUALITY ',' expr ',' expr ']' | '[' tGT ',' expr ',' expr ']' | '[' tLT ',' expr ',' expr ']' | '[' tGEQ ',' expr ',' expr ']' | '[' tLEQ ',' expr ',' expr ']' ; returnStmt: '[' tRETURN ',' expr ']' | '[' tRETURN ']' ; parametersList: parametersList ',' tIDENT | tIDENT ; exprList: exprList ',' expr | expr ;
关键修改说明
- 删除
fulloperation规则:将operation直接并入expr的可选分支,简化语法结构,消除冗余逻辑。 - 在
stmt的expr分支添加输出动作:所有作为顶层语句的表达式(包括递归嵌套的operation)执行时,都会调用printres($1)输出计算结果,解决单独表达式无输出的问题。 - 修复类型匹配问题:原规则中未赋值
$$的分支被移除,确保expr始终能获取到合法的ExprNode*类型值。
效果验证
输入单独的递归表达式(如[ [ADD, [MUL, 2, 3], 4] ])时,stmt会识别为expr并触发printres输出计算结果;当表达式后跟随其他语句(如[ [ADD, 1, 2], [PRINT, "hello"] ]),表达式结果正常输出的同时,后续语句也能正确执行。
内容的提问来源于stack exchange,提问作者abdullah ahmad
相关产品推荐
相关产品推荐

