interpreter, Linux, Mac, Raspberry Pi

Zbudujmy interpreter (4) – liczby rzeczywiste

Mój interpreter do tej pory wykonywał jedynie działania na liczbach całkowitych. Dzisiaj przyszedł czas na dodanie obsługi liczb rzeczywistych. Zacznijmy od modyfikacji leksera.

%{
#define YYSTYPE double
#include <stdio.h>
#include "parse.h"

void yyerror(char *s);
%}

%%
[a-z]   { 
                yylval = (double) (*yytext - 'a');
                return VARIABLE;
        }

[0-9]+ { 
                yylval =  atof (yytext);
                return NUM;
        }

(([0-9]+(\.[0-9]*)?)|([0-9]*\.[0-9]+))        {
                yylval = atof (yytext);
                return NUM;
        }

[-+()=/*\n]     return *yytext;

[ \t] ; /* skip whitespace */

.       yyerror("invalid character");
%%

Warto zwrócić uwagę na dodaną definicję typu YYSTYPE – domyślnie wskazuje on na typ int. Na potrzeby obsługi liczb rzeczywistych zmieniłem typ na double. Drugą ważną sprawą jest wyrażenie regularne wykrywające liczbę zmiennoprzecinkową (([0-9]+(\.[0-9]*)?)|([0-9]*\.[0-9]+)).

Ze względu na zmieniony typ YYSTYPE musimy dokonać również modyfikacji pliku parse.y.

%{
#define YYSTYPE double
#include <stdio.h>
int yylex(void);
void yyerror(char *s );

double vars[26];
%}
%start expression_list
%token NUM VARIABLE
%left '-' '+'
%left '*' '/'
%nonassoc UMINUS
%%
expression_list:
        expression_list statement '\n'{ printf(" = %f\n",$2); }
        | expression_list '\n'
        |
;
statement:
        expression
        | VARIABLE '=' expression { vars[(int)$1] = $3; }
;
expression:
        NUM
        | VARIABLE { $$ = vars[(int) $1]; }
        | '-' expression %prec UMINUS { $$ = -$2; }
        | '(' expression ')' { $$ = $2; }
        | expression '+' expression  { $$ = $1 + $3; }
        | expression '-' expression  { $$ = $1 - $3; }
        | expression '*' expression  { $$ = $1 * $3; }
        | expression '/' expression  { $$ = $1 / $3; }
;
%%
void yyerror(char *s )
{
     fprintf (stderr, "%s\n", s);
}
int main (int argc, char **argv) {
     return yyparse();
}
Standard

Dodaj komentarz