0

I want to make a AST from a formula by bison with node-tree:

Here are the functions to make nodes and the struct of "Node":

typedef enum
{null, opera, var, val} NodeType;

 typedef struct Node {
 float val;
 char * name; // val_name
 char * opr; // operator
 NodeType node_type;
 struct Node * left;
 struct Node * right;
 } Node;

 Node create_op_node(char * op){
 Node node;
 node.opr = op;
 node.node_type = opera;
 return node;
 }

 Node create_var_node(char * op){
 Node node;
 node.name = op;
 node.node_type = var;
 return node;
 }

 Node create_val_node(float value){
 Node node;
 node.val = value;
 node.node_type = val;
 return node;
 }

the function to run through the tree:

void run_through_tree (Node *node){
    switch (node->node_type){
        case var:
            printf("varable name:%s\n",node->name);
            break;
        case val:
            printf("num value:%f\n",node->val);
            break;
        case opera:
            printf("\noperator:%s\n",node->opr);
            printf("LFS\n");
            run_through_tree(node->left);
            printf("RHS\n");
            run_through_tree(node->right);
    }

}

and the grammar rules and the way to create and connects is as the following codes:

S : S E T_NEWLINE { main_node = $2;run_through_tree(main_node);} // run through the node tree | {} ;

E    :  E T_ADD E {Node * op_node = (Node *) malloc(sizeof(Node));*op_node = create_op_node("+"); connect_node(op_node,$1,$3);$$ = op_node;}
     |  E T_SUB E {Node * op_node = (Node *) malloc(sizeof(Node));*op_node = create_op_node("-"); connect_node(op_node,$1,$3);$$ = op_node;}
     |  E T_MUL E {Node * op_node = (Node *) malloc(sizeof(Node));*op_node = create_op_node("*"); connect_node(op_node,$1,$3);$$ = op_node;}
     |  E T_DIV E {Node * op_node = (Node *) malloc(sizeof(Node));*op_node = create_op_node("/"); connect_node(op_node,$1,$3);$$ = op_node;} 
     | T_SUB E %prec NEG {
                        Node * op_node = (Node *) malloc(sizeof(Node));
                        Node * zero_node = (Node *) malloc(sizeof(Node));
                        * zero_node = create_val_node(0.0);
                        * op_node = create_op_node("-");
                        connect_node(op_node,zero_node,$2);
                        $$ = op_node;}
     | T_NUM {Node * val_node = (Node *) malloc(sizeof(Node));* val_node = create_val_node($1); $$ = val_node;}
     | T_VAR {Node * var_node = (Node *) malloc(sizeof(Node));* var_node = create_var_node($1); $$ = var_node;}
     | T_LPATH E T_RPATH {$$ = $2;}
     ;

the result of parsing the formula without variables is as expected: 2 * ( 3 + 2)

operator:*
LFS
num value:2.000000
RHS

operator:+
LFS
num value:3.000000
RHS
num value:2.000000

However, the parsing of the formulas with variables is not correct:

2 * a - a + 7 operator:+ LFS

operator:-
LFS

operator:*
LFS
num value:2.000000
RHS
varable name:a - a + 7

RHS
varable name:a + 7

RHS
num value:7.000000

It should be:

2 * a - a + 7 operator:+ LFS

operator:-
LFS

operator:*
LFS
num value:2.000000
RHS
varable name:a

RHS
varable name:a

RHS
num value:7.000000

How could I solve the problem?

Tan Kian-teng
  • 81
  • 1
  • 10
  • 1
    I suppose the problem is really in your flex file, where you don't copy the the identifier token before storing it in yylval. See, for example, https://stackoverflow.com/questions/33131787/character-by-character-description-of-flex-scanner/33133877#33133877 – rici May 20 '18 at 14:23
  • I've found that in the lex file: {var} {yylval.strVal = yytext; yycharno = yycharno + yyleng; printf("yyval.strVal = %s",yylval.strVal); It may cause the problem. Thank you. – Tan Kian-teng May 20 '18 at 15:37

0 Answers0