I'm building a compliar for a specific language, I've made a lex scanner & yacc Parsar and a text file with some of the language, the goal is to build a proper AST and print it,

i already made the full yacc and lex files with all the rules i need, i run them use the code:

yacc -d test.y
lex test.l
cc -o test y.tab.c -ll -Ly
./test < file.t

The files are able to make a parser from the text file without any syntax problems, so scanning and parsing with the lex and yacc works.

I have prepared functions for the construction of the AST, to print it right i made a recursion function that scan in preorder to print the all tree.

*i removed most of the not relevant code

some of the yacc code:

%{
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    typedef struct node {
        char* token;
        struct node *left;
        struct node *middle; 
        struct node *right;
    }node;



    node *mknode(char *token,node *left,node *middle,node *right);

    void printTree(node *tree);

    void yyerror(const char *s);

    int yylex();

    #define printTree

    #define YYSTYPE struct node*
    extern char *yytext;

%}
%start start
%token MULTI DIVISION BOOL CHAR INT REAL STRING INTPTR CHARPTR REALPTR IF ELSE WHILE FOR VAR FUNC PROC RETURN ASSIGN AND EQUAL GREATER GREATEREQUAL LESS LESSEQUAL MINUS NOT NOTEQUAL OR PLUS ADDRESS DEREFERENCE ABSUOLUT NULLL SEMICOLON COLUMS COMMA NEGATIVE_NUM LEFTBRACE RIGHTBRACE LEFTBRACKET RIGHTBRACKET COOMMENT PRESENT MAIN BOOLTRUE LEFTPAREN RIGHTPAREN BOOLFALSE INTEGER_CONST CHAR_CONST REAL_CONST ID STRING_CONST HEX_CONST 
%right ASSIGN ELSE DIVISION
%left LEFTBRACE RIGHTBRACE LEFTPAREN RIGHTPAREN
%left EQUAL GREATER GREATEREQUAL LESSEQUAL LESS NOTEQUAL
%left PLUS MINUS AND OR 
%left MULTI 

%%
    start: Main                {printTree($1);};

    Main: proc Main            {$$=mknode("CODE",$1,$2,NULL);}  
         |empty                {$$=mknode("CODE",$1,NULL,NULL);};


    id: ID                                               {$$=mknode(yytext,NULL,NULL,NULL);};


    leftParen: LEFTPAREN                                       {$$=mknode("(",NULL,NULL,NULL);};

    rightParen: RIGHTPAREN                                     {$$=mknode(")",NULL,NULL,NULL);};

    empty:                                               {$$=mknode("",NULL,NULL,NULL);};

    proc: PROC id leftParen paramsList rightParen Problock {$$=mknode("PROC",mknode($2->token,$3,$4,$5),NULL,$6);}
         |FUNC id leftParen paramsList rightParen returnInsideFuncDeclaration Problock {$$=mknode("FUNC",mknode($2->token,$3,$4,$5),$6,$7);};


    paramsList: startparamsList SEMICOLON paramsList     {$$=mknode("start_params",$1,mknode(";",NULL,NULL,NULL),$3);}
                |startparamsList                         {$$=mknode("start_params",$1,NULL,NULL);}
                |empty                                   {$$=mknode("start_params",$1,NULL,NULL);}; 

    startparamsList: id next_param_in_proc               {$$=mknode("start_params",$1,$2,NULL);};

    next_param_in_proc: COMMA id next_param_in_proc      {$$=mknode(",",$2,$3,NULL);}
                        |COLUMS varType                  {$$=mknode(":",$2,NULL,NULL);};



    Problock: leftBrace Procbody rightBrace              {$$=mknode("PROC",$1,$2,$3);};

    Procbody: BlockBody                                  {$$=mknode("BODY",$1,NULL,NULL);}
              |BlockBody return                          {$$=mknode("BODY",$1,$2,NULL);} ; 


    HelpToStatement: ProcStatement HelpToStatement       {$$=mknode("help to statment",$1,$2,NULL);}
                     |empty                              {$$=mknode("help to statment",$1,NULL,NULL);};

    HelpToTheProcedure: proc HelpToTheProcedure          {$$=mknode("help proc",$1,$2,NULL);}
                        |empty                           {$$=mknode("help proc",$1,NULL,NULL);};

    HelpDeclare: Declaration HelpDeclare                 {$$=mknode("declartion",$1,$2,NULL);}
                 |empty                                  {$$=mknode("declartion",$1,NULL,NULL);};

    BlockBody: HelpToTheProcedure HelpDeclare HelpToStatement   {$$=mknode("Body",$1,$2,$3);};   


    ProcStatement:   exp SEMICOLON 
                     |structOfCond
                     |block;

%%
#include "lex.yy.c"

int main()
{
    return yyparse();
}

node *mknode(char *token, node *left, node *middle, node *right)
{
    node *newnode = (node*)malloc(sizeof(node));
    char *newstr = (char*)malloc(sizeof(token)+1);
    strcpy(newstr,token);
    newnode->left = left;
    newnode->middle = middle;
    newnode->right = right;
    newnode->token = newstr;
    return newnode;
}
void printtree(node *tree)
{
    printf("%s\n",tree->token);
    if(tree->left)
        printtree(tree->left);
    if(tree->middle)
        printtree(tree->middle);
    if(tree->right)
        printtree(tree->right);
}

void yyerror(const char *str)
{
    printf("%s - %s in line:%d \n",str,yytext,counter);
}

so I manage to build AST from the language, but not to print it, for some reason the function 'printTree' is doing nothing,

If I try to print like this: printf("%s", $1->token) or printf("%s", $1->left->token), then everything is fine and every token is in its rightful place, so why I cannot print them using a recursive function ?

1 Answers

1
sepp2k On Best Solutions

You're defining printTree to be nothing using #define printTree. So printTree($1); is macro-expanded to ($1);, which is a no-op. On the other hand your function printtree (no capital letters) is never called.

So you should remove the #define, forward-declare the printtree function and then call that in your action.