You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 16:10:39