lundi 19 juillet 2021

If/Then statement and switch statement in Bison/Flex

I've been trying to implement an if-then statement and switch statement in Bison/Flex compiler. I'm very confused as to why the evaluteIfThen() in values.cc isn't working, as well as how to even begin approaching making the switch statements work. For the if-then statements, it's currently only recognizing the first result (the "if" block) no matter how the condition has satisfied. As in, in the below test input, it returns 10 no matter what the parameter a is.

Please help! Thank you very much!

Here's the test input with an if-then statement written in the language:

-- Function with parameters

function main a: integer returns integer;
   c: integer is 5;
begin
   if a = 1 then
    c + 5;
   else 
    c + 10;
   endif;
end;

Test input with switch statements:

-- Function with parameters

function main a: integer returns integer;
   c: integer is 5;
begin
   case a is
      when 1 => 3;
      when 2 => 4;
      others => c;
   endcase;
end;

Here's my parser.y:

%{

#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <math.h>

using namespace std;

#include "values.h"
#include "listing.h"
#include "symbols.h"
#include "stdlib.h"
#include <stdio.h>

int yylex();
void yyerror(const char* message);

Symbols<int> symbols;
double *parameter;
int result;
vector<int> case_statements;

%}

%define parse.error verbose

%union
{
    CharPtr iden;
    Operators oper;
    int value;
}

%token <iden> IDENTIFIER
%token <value> INT_LITERAL REAL_LITERAL BOOL_LITERAL CASE CASES TRUE FALSE ARROW

%token <oper> ADDOP MULOP RELOP EXPOP REMOP NOTOP OROP
%token ANDOP

%token BEGIN_ BOOLEAN END ENDREDUCE FUNCTION INTEGER IS REDUCE RETURNS THEN WHEN ELSE ENDCASE IF ENDIF OTHERS REAL

%type <value> body statement_ statement reductions expression relation term binary factor primary exponent unary case cases
%type <oper> operator

%%

function:   
    function_header optional_variable body {result = $3;} ;
    
function_header:    
    FUNCTION IDENTIFIER parameters RETURNS type ';' |
    FUNCTION IDENTIFIER RETURNS type ';' |
    error ';' ;

optional_variable:
    optional_variable variable |
    error ';' | %empty 
    ;

variable:   
    IDENTIFIER ':' type IS statement_ {symbols.insert($1, $5);} ;

parameters:
    parameter optional_parameter;

optional_parameter:
    optional_parameter ',' parameter | %empty 
    ;

parameter:
    IDENTIFIER ':' type {symbols.insert($1, parameter[0]);} ;

type:
    INTEGER |
    REAL |
    BOOLEAN ;

body:
    BEGIN_ statement_ END ';' {$$ = $2;} ;
    
statement_:
    statement ';' |
    error ';' {$$ = 0;} ;

statement:
    expression |
    REDUCE operator reductions ENDREDUCE {$$ = $3;} |
    IF expression THEN statement_ ELSE statement_ ENDIF {$$ = evaluateIfThen($2, $4, $6); } |
    CASE expression IS cases OTHERS ARROW statement_ ENDCASE
    ;

cases:
    cases case {$$ = $2;} | %empty 
    ;

case:
    WHEN INT_LITERAL ARROW statement_ {$$ = $4;} ;
    

operator:
    ADDOP |
    MULOP |
    RELOP |
    EXPOP ;

reductions:
    reductions statement_ {$$ = evaluateReduction($<oper>0, $1, $2);} |
     %empty {$$ = $<oper>0 == ADD ? 0 : 1;} ;

expression:
    expression OROP binary {$$ = $1 || $3;} |    
    binary ;

binary:
    binary ANDOP relation {$$ = $1 && $3;} |
    relation;

relation:
    relation RELOP term {$$ = evaluateRelational($1, $2, $3);} |
    term ;

term:
    term ADDOP factor {$$ = evaluateArithmetic($1, $2, $3);} |
    factor ;
      
factor:
    factor MULOP primary {$$ = evaluateArithmetic($1, $2, $3);} |
    factor REMOP exponent {$$ = evaluateArithmetic($1, $2, $3);} |
    exponent ;

exponent:
    unary | 
    unary EXPOP exponent {$$ = evaluateArithmetic($1, $2, $3);} ;

unary:
    NOTOP primary {$$ = $2;} |
    primary ;

primary:
    '(' expression ')' {$$ = $2;} |
    INT_LITERAL |
    REAL_LITERAL |
    BOOL_LITERAL |
    IDENTIFIER {if (!symbols.find($1, $$)) appendError(UNDECLARED, $1);} ;

%%

void yyerror(const char* message)
{
    appendError(SYNTAX, message);
}

int main(int argc, char *argv[])    
{
    parameter = new double[argc-1];
    for (int i = 1; i < argc; i++) {
        parameter[i-1] = atof(argv[i]);
        }
    firstLine();
    yyparse();
    if (lastLine() == 0)
        cout << "Result = " << result << endl;
    return 0;
} 

and here's my values.cc:

#include <string>
#include <vector>
#include <cmath>
#include <iostream>

using namespace std;

#include "values.h"
#include "listing.h"

int evaluateReduction(Operators operator_, int head, int tail)
{
    if (operator_ == ADD)
        return head + tail;
    return head * tail;
}


int evaluateRelational(int left, Operators operator_, int right)
{
    int result;
    switch (operator_)
    {
        case LESS:
            result = left < right;
            break;
        case LESS_EQUAL:
            result = left <= right;
            break;
        case GREATER:
            result = left > right;
            break;
        case GREATER_EQUAL:
            result = left >= right;
            break;
        case EQUAL:
            result = left = right;
            break;
        case NOT_EQUAL:
            result = left /= right;
            break;
    }
    return result;
}

int evaluateArithmetic(int left, Operators operator_, int right)
{
    int result;
    switch (operator_)
    {
        case ADD:
            result = left + right;
            break;
        case MULTIPLY:
            result = left * right;
            break;
        case SUBTRACT:
            result = left - right;
            break;
        case DIVIDE:
            result = left / right;
            break;
        case REM:
            result = left % right;
            break;
        case EXP:
            result = pow(left, right);
            break;
    }
    return result;
}

int evaluateIfThen(int ifStatement, int resultOne, int resultTwo) {
    if (ifStatement != 0) {
        return resultOne;
    }
    else {
        return resultTwo;
    }
}

Aucun commentaire:

Enregistrer un commentaire