由flex / bison制作的计算器

时间:2018-03-15 12:54:24

标签: bison flex-lexer

我试图制作一个使用括号的抽象语法树计算器。 它的工作,但我有输出配方的问题。

enter image description here

这是我的parser.y

parser.y

/* declarations */
%{
#include <stdio.h>
#include "ast.h"

int yylex();
void yyerror(char *);
%}
%union {
  struct ast *node;
  int value;
}%token ADD SUB MUL DIV LPA RPA EOL 
%token <value> NUMBER
%type <node> exp factor term lpa rpa
%%
 /* rules & actions */
goal: 
 | goal exp EOL     { print_ast($2); printf("= %d\n", eval_ast($2)); 
free_ast($2); }
;
exp: term       { $$ = $1; }
| exp ADD term      { $$ = alloc_ast(ADD, $1, $3); }
| exp SUB term      { $$ = alloc_ast(SUB, $1, $3); }
;
term: factor        { $$ = $1; }
| term MUL factor   { $$ = alloc_ast(MUL, $1, $3); }
| term DIV factor   { $$ = alloc_ast(DIV, $1, $3); }
;
factor: NUMBER      { $$ = alloc_ast_leaf($1); }
| lpa exp rpa       { $$ = $2; }
;
lpa : LPA       { printf("("); }
;
rpa : RPA       { printf(")"); }
;
%%
 /* C code */
int main(void) {
    yyparse();
        return 0;
}void yyerror(char *s) {
    fprintf(stderr, "error: %s\n", s);
}

和scanner.l

scanner.l

 /* declarations */
%{
#include "parser.tab.h"
%}
%%
 /* patterns & actions */
"+" { return ADD; }
"-" { return SUB; }
"*" { return MUL; }
"/" { return DIV; }
"(" { return LPA; }
")" { return RPA; }
[0-9]+  { yylval.value = atoi(yytext); return NUMBER; }
[ \t]   {}
\n  { return EOL; }
.   { printf("Mystery character '%c'\n", *yytext); }
%%
 /* C code */

和ash.c

ast.c

#include <stdio.h>
#include <stdlib.h>
#include "ast.h"
#include "parser.tab.h"
void yyerror(char *);

/* build an AST node */
struct ast *alloc_ast(int type, struct ast *l, struct ast *r)
{
     struct ast *node = malloc(sizeof(struct ast));
     if (!node) {
        yyerror("out of space");
        exit(0);
    }
    node->type = type;
    node->l = l;
    node->r = r;
    return node;
}

struct ast *alloc_ast_leaf(int value)
{
    struct ast_leaf *node = malloc(sizeof(struct ast_leaf));
    if (!node) {
        yyerror("out of space");
        exit(0);
    }
    node->type = NUMBER;
    node->value = value;
    return (struct ast *)node;
}

/* evaluate an AST */
int eval_ast(struct ast *node)
{
    int result;

    switch(node->type) {
        case ADD:
            result = eval_ast(node->l) + eval_ast(node->r);
            break;
        case SUB:
            result = eval_ast(node->l) - eval_ast(node->r);
            break;
        case MUL:
            result = eval_ast(node->l) * eval_ast(node->r);
            break;
        case DIV:
            result = eval_ast(node->l) / eval_ast(node->r);
            break;
        case LPA:
            break;
        case RPA:
            break;
        case NUMBER:
            result = ((struct ast_leaf *)node)->value;
            break;
        default:
            printf("internal error: bad node %d\n", node->type);
    }
    return result;
}

/* delete and free an AST */
void free_ast(struct ast *node)
{
    switch(node->type) {
        case ADD:
        case SUB:
        case MUL:
        case DIV:
            free_ast(node->l);
            free_ast(node->r);
        case LPA:
        case RPA:
        case NUMBER:
            free(node);
            break;
        default:
            printf("internal error: free bad node %d\n", node->type);
    }
}

/* print an AST */
void print_ast(struct ast *node)
{
    switch(node->type) {
        case ADD:
            print_ast(node->l);
            printf("+");
            print_ast(node->r);
            break;
        case SUB:
            print_ast(node->l);
            printf("-");
            print_ast(node->r);
            break;
        case MUL:
            print_ast(node->l);
            printf("*");
            print_ast(node->r);
            break;
        case DIV:
            print_ast(node->l);
            printf("/");
            print_ast(node->r);
            break;
        case LPA:
            //printf("(");
            break;
        case RPA:
            //printf(")");
            break;
         case NUMBER:
            printf("%d", ((struct ast_leaf *)node)->value);
     }
}

我把公式分成了语素。

我尝试使用ast.c和parser.y来打印括号。

但括号在左侧输出。

有人解决了这个问题吗?

1 个答案:

答案 0 :(得分:1)

你需要在print_ast例程中打印parens,

现在,当解析器遇到它们时,你会打印出parens。