我正在尝试评估和表达表格
#SomeFunc[expr][expr]expr
expr可以是由某些字符组成的字符串,也可以是上述函数。所以这可能看起来像
#SomeFunc[#SomeFunc[#SomeFunc[nm^2][nn]][nm]][n]...
问题在于,如果我以
的形式制作代币"#"SomeFunc {yylval.fn=F_some; return FUNC;}
m|n|ms {return TEXT;}
"^" {yylval.fn=F_pow; return FUNC;}
[1-9]+ {yylval=atoi(yytext); return NUMBER;}
如果我有像
这样的东西,我就会遇到构建语法的问题#SomeFunc[#SomeFunc[nm^2][nn]][n]
calc:
| calc expr EOL { eval($2); }
expr: TEXT {$$= add it to ast-leaf }
| FUNC '[' expr ']' '[' expr ']' {$$= add ast(func,$3,$6) }
| expr expr {$$= add to ast('*',$1,$2 }
我不太确定语法是错误的还是我的AST实现。
我发现我的逻辑有缺陷,因为在nm expr的情况下将是expr expr,它将返回仍为nm的n * m的值。这会导致无限循环吗?我该如何解析这样的表达。
不要扔石头。野牛新手
稍后修改 我设法清理并测试了AST和一些链接列表背后的代码。唯一的问题仍然是语法。
%union { struct ast *a; char *strval; int ival; }
%type <a> exp fact
%token <strval> ISU
%token <ival> NUMBER
%token FUNC POW
%token EOL OP CP
%%
calclist: | calclist exp EOL { printf("result >",eval($2));};
exp: fact | exp fact {$$ = newast('*', $1,$2);} ;
fact: FUNC OP exp CP OP exp CP { $$ = newast('/',$3,$6);}
| ISU POW NUMBER { $$ = newnum($1, $3);}
| ISU { $$ = newnum($1,1);};
这个语法对于像Frac [m ^ 2] [m ^ 4]节点/节点K m ^ 4节点K m ^ 4
这样的expr失败了答案 0 :(得分:0)
我简化了语法来表达基本形式,而不一定是它们可能被组合的方式。 (为了简化实验,我也删除了生成的词法分析器,因此在我的所有函数中都称为'f',只要它是'2',你就可以得到任何你想要的数字。)
在各种测试用例中,这似乎对我很有用:请注意除了calc
之外的所有规则都是递归的,这就是你想要的yacc。
cat subcity.y && yacc subcity.y && cc -w y.tab.c -ly
%%
calc: | calc expr '\n';
expr: | expr form
| expr operator form;
form: mns | '[' expr ']' | digit | 'f';
mns: 'm' | 'n' | 's';
digit: '2';
operator: '^' | '+' | '-' | '*' | '/';
%%
int yylex(void) { int c; while ((c = getchar()) == ' ') continue; return c; }
int main(int ac, char **av) { if (yyparse() != 0) printf("parse error\n"); }
似乎有效:
$ ./a.out
f[ f[ f[nm^2] [nn]] [nm]] [n]
f[f[2]] [f[f[nm^2]f]]
f[f[nm^2][nn]][n]
f[m^2][m^2] n / n 2 m^2 n 2 n^2
$
我无法弄清楚你对你的第一个语法不喜欢什么,但我希望这会给你一些想法。更像这样的东西当然是 I 的开头。你的语法以运算符未连接的相邻表达式为特征这一事实有点奇怪。终端符号更常见,就像字符串在某些语言中连接的方式一样。有些人会发明一个操作员来消除这种情况。
答案 1 :(得分:0)
根据你的描述,你希望“^ 2”是一个有效的expr,但是你的lex规则返回FUNC代表'^'而NUMBER代表'2',但是在你的语法中,FUNC必须后跟'['in您拥有的唯一规则,并且您没有NUMBER规则。你可能想要一个规则“expr:NUMBER”,但是你还需要一个规则“expr:FUNC expr”然后匹配“^ 2”,所以看起来你可能想要'^'返回其他一些令牌。