0

我必须为课堂上的实验室制作一个 flex/bison 计算器,并且我必须添加计算平方根或绝对值的功能,它们放在 sqrt(x) 或 abs(x) 中。我导入了数学库,如果它的命令由一个字符组成,我可以让计算器工作。这就是我的意思:

expr:
......
| '(' expr ')' { $$ = fabs($2); } //for abs
| '[' expr ']' {$$ = sqrt($2); } //for sqrt
.......

现在,这工作正常,如果我输入 (-2),我得到 2,或 [4] = 2。问题很明显,我需要让它命令是 abs(x) 和 sqrt(x)。如果我切换代码说

| "abs(" expr ')' { $$ = fabs($2); } //for abs
| "sqrt" expr ']' {$$ = sqrt($2); } //for sqrt

这不起作用,因为它看到 a 然后 b,并试图用它做点什么。这可能是因为我的计算器还支持分配变量值(如 x=2),所以它认为 a 和 b 之间应该有一个运算符。不幸的是,我不知道如何解决这个问题。我将不胜感激任何帮助。如果有帮助,这是我的代码:

hexcalc.y

%{
#include <stdio.h>
#include <math.h>
#include <stdlib.h> // often required

// A simple error message to move things along
void yyerror(const char *msg)
{
printf("ERROR(PARSER): %s\n", msg);
}

// Storage for variables: yes Virginia, only 26 variables possible in this langu$
long variables[26];
%}

%union {
float nvalue;
int ivalue;
int varindex;
}

%token <nvalue> NUMBER
%token <ivalue> INT
%token <varindex> NAME
%type <nvalue> expr
%type <nvalue> term
%type <nvalue> varOrNum
%%
statementList : statement '\n'
| statement '\n' statementList
;

statement : NAME '=' expr { variables[$1] = $3; }
| expr { printf("RESULT: %f\n", $1); }
;

expr: expr '+' term { $$ = $1 + $3; }
| expr '-' term { $$ = $1 - $3; }
| '-' term { $$ = 0 - $2; }

| "abs(" expr ')' { $$ = $2; }
| "sqrt(" expr ')' { $$ = sqrt($2); }
| expr '/' term { $$ = $1 / $3; }

| term { $$ = $1; }
;

term : term '*' varOrNum { $$ = $1 * $3; }

| varOrNum { $$ = $1; }
;

varOrNum : NUMBER { $$ = $1; }
| NAME { $$ = variables[$1]; }
;

%%

main() {
int i;
for (i=0; i<26; i++) variables[i] = 0;
yyparse();
}

hexcalc.l

%{
#include <stdlib.h>
#include <math.h>
#include "hexcalc.h"
#define BASE 10
char* endptr;

%}

%%

[a-z] { yylval.varindex = yytext[0] - 'a'; $
}
[0-9]+ { yylval.nvalue = atof(yytext);
return NUMBER;
}
[0-9]+"."[0-9]+?|"."[0-9]+? {yylval.nvalue = atof(yytext);

return NUMBER;
}

[ \t] ;
\n|. { return yytext[0];
}
%%

int yywrap() {
return 1;
}
4

3 回答 3

3

您需要将词法分析器中的多字符名称识别为单个标记,然后在语法中使用它们。简单的方法是将它们添加到您的词法分析器中:

abs    { return ABS; }
sqrt   { return SQRT; }

然后你可以添加到你的解析器:

%token ABS SQRT

%%

expr: ABS  '(' expr ')' { $$ = fabs($3); }
    | SQRT '(' expr ')' { $$ = sqrt($3); }
于 2013-04-01T02:26:20.200 回答
0

您需要在 .l 文件中为“abs”和“sqrt”创建规则;声明他们将通过 %token 返回的令牌;并在语法规则中使用这些标记名称: ABS "(" expr ")" : ...

于 2013-04-01T02:58:47.807 回答
0

您应该查看 Bison 的文档,其中给出了针对预定义函数的更具可扩展性的解决方案(使用符号表)。

http://www.gnu.org/software/bison/manual/html_node/Multi_002dfunction-Calc.html

于 2013-04-03T04:30:13.373 回答