'pointer to incomplete class type "struct S_statement" is not allowed, C error

I have a C project which has one of the specification files as parser.h where in struct S_statement is defined and the same is implemented in the source file parser.c while the other definitions like S_expression and S_statement_list doesn't give me these errors only S_statement gives

incomplete type is not allowed
pointer to incomplete class type "struct S_statement" is not allowed

these errors, what can I resolve to do them?

parser.h

#ifndef PARSER_H 
#define PARSER_H 

#include <stdio.h> // to print any parsing errors
#include "lexer.h"

typedef struct S_statement_list* T_statement_list;
typedef struct S_statement* T_statement;
typedef struct S_expression* T_expression;

struct S_statement_list{
   T_statement statement;
   T_statement_list statement_list;
};

struct S_Statement{
    T_expression expression;
};

struct S_expression{
    T_token opreand1;
    T_token operator_;
    T_token opreand2;
};

T_statement_list parse_statement_list();
T_statement parse_statement();
T_expression parse_expression();

T_statement_list create_statement_list(T_statement statement, T_statement_list statement_list);
T_statement create_statement(T_expression expression);
T_expression create_expression(T_token opreand1, T_token operator_, T_token opreand2); // he did opreator twice 
T_token get_lookahed();
void next_token();
void parser_error();

#endif

Error occurrs in create_statement function while trying to create a statement struct on heap and initialization to a T_statement pointer

parser.c

#include "parser.h"

T_token lookahed_token;

T_token get_lookahed(){ // inspecting lookahead when needed beacuase we might want to look at the token multiple times before we consume it 
    return lookahed_token;
}

void next_token(){ // getting the token from lexer 
    lookahed_token = lex();
}



// parse statement 
// parse statement list recursivly 
// create and return statement list node 
T_statement_list parse_statement_list(){
    if(END!=get_lookahed()->kind){
        T_statement statement = parse_statement();
        T_statement_list statement_list = parse_statement_list();
        return create_statement_list(statement,statement_list);
    }else{
        return NULL;
    }
}

//parse an expresson 
// parse a semicolon 
// create statement node 
T_statement parse_statement(){
    T_statement expression = parse_expression();
    T_token semicolon = get_lookahed();
    if(SEMICOLON!=semicolon->kind) parser_error();
    next_token();
    return create_statement(expression);
}

T_expression parse_expression(){
    // read op1, opreator, op2 and make expr node
    T_token opreand1 = get_lookahed();
    if(opreand1->kind!=NUMBER) parser_error();
    next_token();

    T_token opreator_ = get_lookahed();
    if(opreator_->kind!=OPREATOR) parser_error();
    next_token();

    T_token opreand2 = get_lookahed();
    if(opreand2->kind!=NUMBER) parser_error();
    next_token();

    return create_expression(opreand1,opreator_,opreand2);
}


T_statement_list create_statement_list(T_statement statement, T_statement_list statement_list){
    T_statement_list new_list = malloc(sizeof(*new_list));
    new_list->statement = statement;
    new_list->statement_list = statement_list;
    return new_list;
}

T_statement create_statement(T_expression expression){
    T_statement new_statement = malloc(sizeof(*new_statement)); // errors here
    new_statement->expression = expression; // and here
    return new_statement;
}

T_expression create_expression(T_token opreand1,T_token opreator_, T_token opreand2){
    T_expression new_expression = malloc(sizeof(*new_expression));
    new_expression->opreand1 = opreand1;
    new_expression->opreand2 = opreand2;
    new_expression->operator_ = opreator_;
    return new_expression;
}

void parser_error(){
    printf("Error while parsing...");
}



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source