Добавление функций abs(x) и sqrt(x) в калькулятор flex/bison

Я должен сделать калькулятор в flex/bison для лаборатории в классе, и я должен добавить функциональность для вычисления квадратных корней или абсолютных значений, которые они помещают в sqrt (x) или abs (x). Я импортировал математическую библиотеку, и я заставил caculator работать, если КОМАНДА ДЛЯ ЭТОГО СОСТОИТ ИЗ ОДНОГО СИМВОЛА. Вот что я имею в виду:

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;
}

person Khalil Norman    schedule 31.03.2013    source источник


Ответы (3)


Вам нужно распознавать многосимвольные имена в лексере как отдельные токены, а затем использовать их в своей грамматике. Самый простой способ — просто добавить их в свой лексер:

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

Затем вы можете добавить в свой парсер:

%token ABS SQRT

%%

expr: ABS  '(' expr ')' { $$ = fabs($3); }
    | SQRT '(' expr ')' { $$ = sqrt($3); }
person Chris Dodd    schedule 01.04.2013

Вам нужно создать правила в файле .l для «abs» и «sqrt»; объявить токены, каждый из которых будет возвращать через %token; и используйте эти имена токенов в правилах грамматики: ABS "(" expr ")" : ...

person user207421    schedule 01.04.2013

Вы должны взглянуть на документацию Bison, где дается более масштабируемое решение для предопределенных функций (с использованием таблицы символов).

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

person akim    schedule 03.04.2013