0

我正在尝试评估和表达形式

#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 将返回 n*m 的值,它仍然是 nm。这会导致无限循环吗?我应该如何解析这样的表达式。

不要扔石头。野牛新手

后来的编辑 我设法清理并测试了 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] node / node K m^4 node K m^4 这样的 expr,此语法失败

4

2 回答 2

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
$ 

我无法完全弄清楚你不喜欢你的第一个语法,但我希望这能给你一些想法。更像这样的东西肯定是要开始的。您的语法具有与运算符无关的相邻表达式这一事实有点奇怪。终端符号更常见,例如字符串在某些语言中的连接方式。有些人会发明一个运算符来消除这种情况。

于 2009-10-12T01:34:38.110 回答
0

From your description, you expect "^2" to be a valid expr, but your lex rule returns FUNC for '^' and NUMBER for '2', but in your grammar, FUNC must be followed by '[' in the only rule you have for it, and you have no rule for NUMBER. You probably want a rule "expr : NUMBER", but then you'll also need a rule "expr: FUNC expr" to then match "^2", so it seems like you might instead want to have '^' return some other token.

于 2009-10-12T02:07:22.257 回答