我正在用野牛和Flex编写一个解析器来解析一个“自制”语言。该语言包含以下类型的某些常量表达式:
[OPERATOR, OPERAND1, OPERAND2]
其中,操作数可以是字符串、整数、真实的,也可以是另一个运算符表达式
[OPERATOR, [OPERATOR, OPERAND1, OPERAND2], OPERAND2]
或[OPERATOR, Int1, Int2]
等。
问题是我想返回主表达式的结果,它也调用了其他表达式。我已经制定了一个名为fulloperation
的规则来尝试处理这个问题,但它只在操作表达式后面跟着另一个语句时有效(表达式是一种语句)。这些是我的语法规则,你可以在fulloperation
规则下找到我的递归返回尝试(注意程序的开始和结束都在左右方括号之间):
%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;
%type <exprNodePtr> fulloperation;
%start prog
%%
prog: '[' stmtlst ']' ;
;
stmtlst: stmtlst stmt |
;
stmt: setStmt | if | print | unaryOperation | expr | 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: '[' 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 ']'
;
fulloperation:
operation stmt{printres($1);}|
operation {$$ = $1;}
;
expr: tNUMI {$$ = makeExpressionNodeFromInt($1);}
| tNUMR {$$ = makeExpressionNodeFromReal($1);}
| tSTRING {$$ = makeExpressionNodeFromStr($1);}
| getExpr | function | fulloperation {$$ = $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
;
1条答案
按热度按时间vm0i2vca1#
对于您的语言,它看起来非常像lisp,我会选择一个树,其中每个规则创建一个节点,然后返回。
例如,对于单分支
if
语句:对于节点本身,我将使用嵌入式节点来模拟类似C++的继承,其中顶部的基节点包含一个函数指针,该指针被初始化为一个指针来计算当前节点。
例如:
对于
if
语句:创建
if
语句节点的函数:全局
evaluate
函数接受函数指针并使用当前节点调用它:为所有的表达式和语句创建类似的节点结构、节点创建函数和节点求值函数,并且您的首要规则
prog
将简单地调用printf("Result of program: %d\n", evaluate($2));
来运行所有语句和表达式并打印最终结果。