我试图制作一个使用括号的抽象语法树计算器。 它的工作,但我有输出配方的问题。
这是我的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来打印括号。
但括号在左侧输出。
有人解决了这个问题吗?
答案 0 :(得分:1)
你需要在print_ast例程中打印parens,
现在,当解析器遇到它们时,你会打印出parens。