Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
comp:
lex src/lex.l
yacc -d src/grammar.y
gcc -o bin/main y.tab.c lex.yy.c
gcc -o bin/main y.tab.c lex.yy.c src/summoner.c src/interpreter.c
34 changes: 20 additions & 14 deletions src/grammar.y
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
%{
#include <stdio.h>
#include <stdlib.h>
#include "src/summoner.h"
#include "src/interpreter.h"

int yylex();
int yyerror(const char *s);
%}

%union {
double double_value;
double double_value;
int int_value;
struct Expression* expression;
}

%token <double_value> DOUBLE_LITERAL
%token CR LP RP
%left ADD SUB
%left MUL DIV
%token <int_value> INT_LITERAL
%token '\n' '(' ')'
%left '+' '-'
%left '*' '/'
%nonassoc MINUS

%type <double_value> expr
%type <expression> expr

%%
stmt_list:
Expand All @@ -24,17 +30,17 @@ stmt_list:
;

stmt:
expr CR {
printf(">>%lf\n", $1);
}
expr '\n' { printExprValue(evalExpression($1)); }

expr:
DOUBLE_LITERAL { $$ = $1; }
| expr ADD expr { $$ = $1 + $3; }
| expr SUB expr { $$ = $1 - $3; }
| expr MUL expr { $$ = $1 * $3; }
| expr DIV expr { $$ = $1 / $3; }
| LP expr RP { $$ = $2; }
INT_LITERAL { $$ = allocIntExpression($1); }
| DOUBLE_LITERAL { $$ = allocDoubleExpression($1); }
| expr '+' expr { $$ = allocBinaryExpression(ADD_EXPRESSION, $1, $3); }
| expr '-' expr { $$ = allocBinaryExpression(SUB_EXPRESSION, $1, $3); }
| expr '*' expr { $$ = allocBinaryExpression(MUL_EXPRESSION, $1, $3); }
| expr '/' expr { $$ = allocBinaryExpression(DIV_EXPRESSION, $1, $3); }
| '(' expr ')' { $$ = $2; }
| '-' expr %prec MINUS { $$ = allocUnaryExpression(MINUS_EXPRESSION, $2); }
;
%%

Expand Down
113 changes: 113 additions & 0 deletions src/interpreter.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@

#include <stdio.h>
#include <stdlib.h>
#include "interpreter.h"
#include "summoner.h"

ExprValue evalIntBinaryExpression(ExpressionType type, int left, int right) {
ExprValue v;
v.type = EXPR_INT_VALUE;
switch (type) {
case ADD_EXPRESSION:
v.u.int_value = left + right;
break;
case SUB_EXPRESSION:
v.u.int_value = left - right;
break;
case MUL_EXPRESSION:
v.u.int_value = left * right;
break;
case DIV_EXPRESSION:
v.u.int_value = left / right;
break;
default:
printf("invalid expression type\n");
exit(1);
}
return v;
}

ExprValue evalDoubleBinaryExpression(ExpressionType type, double left, double right) {
ExprValue v;
v.type = EXPR_DOUBLE_VALUE;
switch (type) {
case ADD_EXPRESSION:
v.u.double_value = left + right;
break;
case SUB_EXPRESSION:
v.u.double_value = left - right;
break;
case MUL_EXPRESSION:
v.u.double_value = left * right;
break;
case DIV_EXPRESSION:
v.u.double_value = left / right;
break;
default:
printf("invalid expression type\n");
exit(1);
}
return v;
}

ExprValue evalBinaryExpression(ExpressionType type, BinaryExpression *binaryExpression) {
ExprValue leftVal = evalExpression(binaryExpression->left);
ExprValue rightVal = evalExpression(binaryExpression->right);
if (leftVal.type == EXPR_INT_VALUE && rightVal.type == EXPR_INT_VALUE) {
return evalIntBinaryExpression(type, leftVal.u.int_value, rightVal.u.int_value);
}

if (leftVal.type == EXPR_INT_VALUE && rightVal.type == EXPR_DOUBLE_VALUE) {
return evalDoubleBinaryExpression(type, leftVal.u.int_value, rightVal.u.double_value);
}

if (leftVal.type == EXPR_DOUBLE_VALUE && rightVal.type == EXPR_INT_VALUE) {
return evalDoubleBinaryExpression(type, leftVal.u.double_value, rightVal.u.int_value);
}

return evalDoubleBinaryExpression(type, leftVal.u.double_value, rightVal.u.double_value);
}

ExprValue evalExpression(Expression *expr) {
ExprValue v;
switch (expr->type) {
case INT_EXPRESSION:
v.type = EXPR_INT_VALUE;
v.u.int_value = expr->u.int_value;
return v;
case DOUBLE_EXPRESSION:
v.type = EXPR_DOUBLE_VALUE;
v.u.double_value = expr->u.double_value;
return v;
case MINUS_EXPRESSION:
v = evalExpression(expr->u.unary_expression);
if (v.type == EXPR_INT_VALUE) {
v.u.int_value = -v.u.int_value;
} else {
v.u.double_value = -v.u.double_value;
}
return v;
case ADD_EXPRESSION:
case SUB_EXPRESSION:
case MUL_EXPRESSION:
case DIV_EXPRESSION:
return evalBinaryExpression(expr->type, expr->u.binary_expression);
default:
printf("invalid expression type");
exit(1);
}
}

void printExprValue(ExprValue val) {
switch (val.type) {
case EXPR_INT_VALUE:
printf(">>>%d\n", val.u.int_value);
break;
case EXPR_DOUBLE_VALUE:
printf(">>>%lf\n", val.u.double_value);
break;
default:
printf("invalid expression type");
exit(1);
}
}
9 changes: 9 additions & 0 deletions src/interpreter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#ifndef _INTERPRETER_H_
#define _INTERPRETER_H_

#include "summoner.h"

ExprValue evalExpression(Expression *expr);
void printExprValue(ExprValue);

#endif
20 changes: 12 additions & 8 deletions src/lex.l
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,25 @@
%}

%%
"+" return ADD;
"-" return SUB;
"*" return MUL;
"/" return DIV;
"(" return LP;
")" return RP;
"\n" return CR;

([1-9][0-9]*)|0|([0-9]+\.[0-9]+) {
[+\-*/\(\)\n] {
return *yytext;
}

[0-9]+\.[0-9]+ {
double val;
sscanf(yytext, "%lf", &val);
yylval.double_value = val;
return DOUBLE_LITERAL;
}

([1-9][0-9]*)|0 {
int val;
sscanf(yytext, "%d", &val);
yylval.int_value = val;
return INT_LITERAL;
}

[ \t] ;

. {
Expand Down
42 changes: 42 additions & 0 deletions src/summoner.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#include <stdio.h>
#include <stdlib.h>
#include "summoner.h"

Expression *allocExpression(ExpressionType type) {
Expression *expr = malloc(sizeof(Expression));
expr->type = type;
return expr;
}

Expression *allocIntExpression(int value) {
Expression *expr = allocExpression(INT_EXPRESSION);
expr->u.int_value = value;
return expr;
}

Expression *allocDoubleExpression(double value) {
Expression *expr = allocExpression(DOUBLE_EXPRESSION);
expr->u.double_value = value;
return expr;
}

Expression *allocBoolExpression(bool value) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

grammer没定义bool expr吧

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

后面把所有的运算符都加上

Expression *expr = allocExpression(BOOL_EXPRESSION);
expr->u.boolean_value = value;
return expr;
}

Expression *allocUnaryExpression(ExpressionType type, Expression *unaryExpr) {
Expression *expr = allocExpression(type);
expr->u.unary_expression = unaryExpr;
return expr;
}

Expression *allocBinaryExpression(ExpressionType type, Expression *left, Expression *right) {
Expression *expr = allocExpression(type);
BinaryExpression *binary = malloc(sizeof(BinaryExpression));
binary->left = left;
binary->right = right;
expr->u.binary_expression = binary;
return expr;
}
74 changes: 74 additions & 0 deletions src/summoner.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#ifndef _SUMMONER_H_
#define _SUMMONER_H_

#include <stdbool.h>

typedef enum
{
EXPR_BOOL_VALUE = 1,
EXPR_INT_VALUE,
EXPR_DOUBLE_VALUE,
} ExprValueType;

typedef struct ExprValue
{
ExprValueType type;
union
{
bool boolean_value;
int int_value;
double double_value;
} u;

} ExprValue;

typedef enum
{
BOOL_EXPRESSION = 1,
INT_EXPRESSION,
DOUBLE_EXPRESSION,
ADD_EXPRESSION,
SUB_EXPRESSION,
MUL_EXPRESSION,
DIV_EXPRESSION,
MINUS_EXPRESSION,
MOD_EXPRESSION, /* % */
EQ_EXPRESSION, /* == */
NE_EXPRESSION, /* != */
GT_EXPRESSION, /* > */
GE_EXPRESSION, /* >= */
LT_EXPRESSION, /* < */
LE_EXPRESSION, /* <= */

} ExpressionType;

typedef struct BinaryExpression BinaryExpression;

typedef struct Expression
{
ExpressionType type;
union
{
bool boolean_value;
int int_value;
double double_value;
BinaryExpression *binary_expression;
struct Expression *unary_expression;
} u;

} Expression;

typedef struct BinaryExpression
{
Expression *left;
Expression *right;
} BinaryExpression;

Expression *allocExpression(ExpressionType type);
Expression *allocIntExpression(int value);
Expression *allocDoubleExpression(double value);
Expression *allocBoolExpression(bool value);
Expression *allocUnaryExpression(ExpressionType type, Expression *unaryExpr);
Expression *allocBinaryExpression(ExpressionType type, Expression *left, Expression *right);

#endif