0

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 ?

rici
  • 234,347
  • 28
  • 237
  • 341
  • How does the program text that you parse looks like? It seems that at the point you want to printTree it is just too early, the program is not fully parsed yet. You need to either printTree at the end of the parsing (for example [at EOF](https://stackoverflow.com/questions/1756275/bison-end-of-file)), or print nodes while they are constructed. – battlmonstr Apr 13 '19 at 11:45
  • the text i used is valid for the language and the parse part works, if i use at same line of 'printTree' the line ```printf("%s", $1->left->left->token)``` and so on..., it is print it! so i dont know if it is too early point... – 420Friendlly Apr 13 '19 at 12:19

1 Answers1

1

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.

sepp2k
  • 363,768
  • 54
  • 674
  • 675
  • thank you very much my friend!, i remembering changing it a lot so it went mismatch in the way..., its very hard to code flex&bison with no debugger..., – 420Friendlly Apr 13 '19 at 12:55
  • also got any idea how to print the blocks with Indentation ? – 420Friendlly Apr 13 '19 at 12:59
  • @420Friendlly Give the print function an integer argument that tells you how many spaces of indentation to print at the beginning of each statement. Then you increase that parameter when you're printing the contents of a block. – sepp2k Apr 13 '19 at 13:30
  • @420friendly: flex and bison both have options to generated code which includes statements to trace execution. Read the section Debugging Your Parser in the bison manual. – rici Apr 13 '19 at 13:40