Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
49 changes: 35 additions & 14 deletions src/grammar.y
Original file line number Diff line number Diff line change
@@ -1,21 +1,32 @@
%{
#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' '(' ')'

%type <double_value> expr
%left AND OR
%nonassoc EQ NE
%nonassoc '>' '<' LE GE
%left '+' '-'
%left '*' '/'
%nonassoc MINUS
%nonassoc NOT

%type <expression> expr

%%
stmt_list:
Expand All @@ -24,17 +35,27 @@ 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 '>' expr { $$ = allocBinaryExpression(GT_EXPRESSION, $1, $3); }
| expr GE expr { $$ = allocBinaryExpression(GE_EXPRESSION, $1, $3); }
| expr '<' expr { $$ = allocBinaryExpression(LT_EXPRESSION, $1, $3); }
| expr LE expr { $$ = allocBinaryExpression(LE_EXPRESSION, $1, $3); }
| expr EQ expr { $$ = allocBinaryExpression(EQ_EXPRESSION, $1, $3); }
| expr NE expr { $$ = allocBinaryExpression(NE_EXPRESSION, $1, $3); }
| expr AND expr { $$ = allocBinaryExpression(AND_EXPRESSION, $1, $3); }
| expr OR expr { $$ = allocBinaryExpression(OR_EXPRESSION, $1, $3); }
| '!' expr %prec NOT { $$ = allocUnaryExpression(NOT_EXPRESSION, $2); }
| '(' expr ')' { $$ = $2; }
| '-' expr %prec MINUS { $$ = allocUnaryExpression(MINUS_EXPRESSION, $2); }
;
%%

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

#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;
case LT_EXPRESSION:
v.type = EXPR_BOOL_VALUE;
v.u.boolean_value = left < right;
break;
case LE_EXPRESSION:
v.type = EXPR_BOOL_VALUE;
v.u.boolean_value = left <= right;
break;
case GT_EXPRESSION:
v.type = EXPR_BOOL_VALUE;
v.u.boolean_value = left > right;
break;
case GE_EXPRESSION:
v.type = EXPR_BOOL_VALUE;
v.u.boolean_value = left >= right;
break;
case EQ_EXPRESSION:
v.type = EXPR_BOOL_VALUE;
v.u.boolean_value = left == right;
break;
case NE_EXPRESSION:
v.type = EXPR_BOOL_VALUE;
v.u.boolean_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;
case LT_EXPRESSION:
v.type = EXPR_BOOL_VALUE;
v.u.boolean_value = left < right;
break;
case LE_EXPRESSION:
v.type = EXPR_BOOL_VALUE;
v.u.boolean_value = left <= right;
break;
case GT_EXPRESSION:
v.type = EXPR_BOOL_VALUE;
v.u.boolean_value = left > right;
break;
case GE_EXPRESSION:
v.type = EXPR_BOOL_VALUE;
v.u.boolean_value = left >= right;
break;
case EQ_EXPRESSION:
v.type = EXPR_BOOL_VALUE;
v.u.boolean_value = left == right;
break;
case NE_EXPRESSION:
v.type = EXPR_BOOL_VALUE;
v.u.boolean_value = left != right;
break;
default:
printf("invalid expression type\n");
exit(1);
}
return v;
}

ExprValue evalBoolBinaryExpression(ExpressionType type, bool left, bool right)
{
ExprValue v;
v.type = EXPR_BOOL_VALUE;
switch (type)
{
case AND_EXPRESSION:
v.u.boolean_value = left && right;
break;
case OR_EXPRESSION:
v.u.boolean_value = left || right;
break;
default:
printf("invalid expression type when eval bool value:%d\n", type);
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);
}

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

if (leftVal.type == EXPR_BOOL_VALUE && rightVal.type == EXPR_BOOL_VALUE)
{
return evalBoolBinaryExpression(type, leftVal.u.boolean_value, rightVal.u.boolean_value);
}

printf("invalid expression type, left:%d, right:%d", leftVal.type, rightVal.type);
exit(1);
}

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 NOT_EXPRESSION:
v = evalExpression(expr->u.unary_expression);
v.u.boolean_value = !v.u.boolean_value;
return v;
case ADD_EXPRESSION:
case SUB_EXPRESSION:
case MUL_EXPRESSION:
case DIV_EXPRESSION:
case LT_EXPRESSION:
case LE_EXPRESSION:
case GT_EXPRESSION:
case GE_EXPRESSION:
case EQ_EXPRESSION:
case NE_EXPRESSION:
case AND_EXPRESSION:
case OR_EXPRESSION:
return evalBinaryExpression(expr->type, expr->u.binary_expression);
default:
printf("invalid expression type when eval expression:%d\n", expr->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;
case EXPR_BOOL_VALUE:
printf(">>>%d\n", val.u.boolean_value);
break;
default:
printf("invalid expression type when print expr value:%d", val.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
29 changes: 20 additions & 9 deletions src/lex.l
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,32 @@
%}

%%
"+" 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;
}

">=" return GE;
"<=" return LE;
"==" return EQ;
"!=" return NE;
"&&" return AND;
"||" return OR;

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