diff --git a/src/exec.c b/src/exec.c index a28a8e3..7457ef1 100644 --- a/src/exec.c +++ b/src/exec.c @@ -32,6 +32,11 @@ ASTNumData exec_call(AST* ast) { ASTNumData n2 = exec_expr(calldata->argv[1]); return n1 + n2; + } else if (!strcmp(calldata->to, "-") && calldata->argc == 2) { + ASTNumData n1 = exec_expr(calldata->argv[0]); + ASTNumData n2 = exec_expr(calldata->argv[1]); + + return n1 - n2; } return -1000; } diff --git a/src/grammar.y b/src/grammar.y index 32dd406..862a6d9 100644 --- a/src/grammar.y +++ b/src/grammar.y @@ -22,6 +22,7 @@ %define parse.error verbose %token NUM +%token NEG %token CALL %token PLUS %token NL @@ -36,11 +37,30 @@ input: exp: NUM { $$ = ast_init(AST_TYPE_NUM, ast_num_data_init($1)); } + | NEG NUM { $$ = ast_init(AST_TYPE_NUM, ast_num_data_init(-$2)); } | NUM PLUS NUM { AST** argv = calloc(2, sizeof(AST*)); argv[0] = ast_init(AST_TYPE_NUM, ast_num_data_init($1)); argv[1] = ast_init(AST_TYPE_NUM, ast_num_data_init($3)); $$ = ast_init(AST_TYPE_CALL, ast_call_data_init("+", 2, argv)); } + | NEG NUM PLUS NUM { + AST** argv = calloc(2, sizeof(AST*)); + argv[0] = ast_init(AST_TYPE_NUM, ast_num_data_init(-$2)); + argv[1] = ast_init(AST_TYPE_NUM, ast_num_data_init($4)); + $$ = ast_init(AST_TYPE_CALL, ast_call_data_init("+", 2, argv)); + } + | NUM NEG NUM { + AST** argv = calloc(2, sizeof(AST*)); + argv[0] = ast_init(AST_TYPE_NUM, ast_num_data_init($1)); + argv[1] = ast_init(AST_TYPE_NUM, ast_num_data_init($3)); + $$ = ast_init(AST_TYPE_CALL, ast_call_data_init("-", 2, argv)); + } + | NEG NUM NEG NUM { + AST** argv = calloc(2, sizeof(AST*)); + argv[0] = ast_init(AST_TYPE_NUM, ast_num_data_init(-$2)); + argv[1] = ast_init(AST_TYPE_NUM, ast_num_data_init($4)); + $$ = ast_init(AST_TYPE_CALL, ast_call_data_init("-", 2, argv)); + } %% diff --git a/src/lexer.c b/src/lexer.c index 73ead29..9313c75 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -65,6 +65,7 @@ int yylex() { switch (c) { case '+': return PLUS; case '\n': return NL; + case '-': return NEG; default: return CALL; }