F diff --git a/src/frontend/lex/lex_preprocessing_directive.c b/src/frontend/lex/lex_preprocessing_directive.c --- a/src/frontend/lex/lex_preprocessing_directive.c +++ b/src/frontend/lex/lex_preprocessing_directive.ccase PKW_IF:return preprocessing_lex_if_directive(lexer_data,token_location);case PKW_IFDEF:- return get_error_token("PREPROCESSING IFDEF NOT DONE",token_location,lexer_data->previous_token_location,lexer_data->program);+ return preprocessing_lex_ifdef_directive(lexer_data,token_location);case PKW_IFNDEF:- return get_error_token("PREPROCESSING IFNDEF NOT DONE",token_location,lexer_data->previous_token_location,lexer_data->program);+ return preprocessing_lex_ifndef_directive(lexer_data,token_location);case PKW_ELIF:return preprocessing_lex_if_directive(lexer_data,token_location);case PKW_ELSE:struct token* preprocessing_lex_if_directive(struct Lexer_Data *lexer_data,struct Source_Location *where){struct token_if_directive *ret;- struct token *hold_token;ret=wonky_malloc(sizeof(struct token_if_directive));ret->type=PKW_IF;while(!preprocessing_eol(lexer_data))Queue_Push(ret->controlling_expression,preprocessing_extract_next_token(lexer_data));+ preprocessing_lex_finish_iflike_directive(lexer_data,ret->if_true,ret->if_false);++ return (struct token*)ret;+ }+ struct token* preprocessing_lex_ifdef_directive(struct Lexer_Data *lexer_data,struct Source_Location *where)+ {+ return preprocessing_lex_ifdefndef_directive(lexer_data,where,PKW_IFDEF);+ }+ struct token* preprocessing_lex_ifndef_directive(struct Lexer_Data *lexer_data,struct Source_Location *where)+ {+ return preprocessing_lex_ifdefndef_directive(lexer_data,where,PKW_IFNDEF);+ }+ struct token* preprocessing_lex_ifdefndef_directive(struct Lexer_Data *lexer_data,struct Source_Location *where,enum LEXER_TYPE type)+ {+ struct token_ifdefndef_directive *ret;+ struct token *hold_token;++ wonky_assert(type==PKW_IFNDEF || type==PKW_IFDEF);++ ret=wonky_malloc(sizeof(struct token_ifdefndef_directive));+ ret->type=type;+ ret->delta=get_source_location_delta(lexer_data->previous_token_location,where);++ ret->if_defined=wonky_malloc(sizeof(struct Queue));+ ret->if_undefined=wonky_malloc(sizeof(struct Queue));++ Queue_Init(ret->if_defined);+ Queue_Init(ret->if_undefined);++ if(!preprocessing_eol(lexer_data))+ hold_token=preprocessing_extract_next_token(lexer_data);+ else+ hold_token==NULL;++ if(hold_token==NULL || !token_is_identifier_in_preprocessing(hold_token))+ {+ push_lexing_error("Expected id in #ifdef directive",lexer_data);+ ret->id=NULL;+ }else+ {+ ret->id=hold_token;+ if(type==PKW_IFDEF)+ preprocessing_lex_finish_iflike_directive(lexer_data,ret->if_defined,ret->if_undefined);+ else+ preprocessing_lex_finish_iflike_directive(lexer_data,ret->if_undefined,ret->if_defined);+ }+ return (struct token*)ret;+ }+ void preprocessing_lex_finish_iflike_directive(struct Lexer_Data *lexer_data,struct Queue *if_true,struct Queue *if_false)+ {+ struct token *hold_token;while((hold_token=lexer_extract_next_token(lexer_data))!=NULL){if(hold_token->type==PKW_ELSE)if(hold_token->type==PKW_ENDIF)break;else- Queue_Push(ret->if_false,hold_token);+ Queue_Push(if_false,hold_token);}if(hold_token==NULL)push_lexing_error("Reached end of file before reaching a #endif",lexer_data);break;}else if(hold_token->type==PKW_ELIF){- Queue_Push(ret->if_false,hold_token);+ Queue_Push(if_false,hold_token);break;}else if(hold_token->type==PKW_ENDIF){break;}else{- Queue_Push(ret->if_true,hold_token);+ Queue_Push(if_true,hold_token);}}- return ret;}struct token* preprocessing_lex_define_directive(struct Lexer_Data *lexer_data,struct Source_Location *where){F diff --git a/src/frontend/lex/lex_preprocessing_directive.h b/src/frontend/lex/lex_preprocessing_directive.h --- a/src/frontend/lex/lex_preprocessing_directive.h +++ b/src/frontend/lex/lex_preprocessing_directive.hstruct token* preprocessing_lex_if_directive(struct Lexer_Data *lexer_data,struct Source_Location *where);struct token* preprocessing_lex_ifdef_directive(struct Lexer_Data *lexer_data,struct Source_Location *where);struct token* preprocessing_lex_ifndef_directive(struct Lexer_Data *lexer_data,struct Source_Location *where);+ struct token* preprocessing_lex_ifdefndef_directive(struct Lexer_Data *lexer_data,struct Source_Location *where,enum LEXER_TYPE type);++ void preprocessing_lex_finish_iflike_directive(struct Lexer_Data *lexer_data,struct Queue *if_true,struct Queue *if_false);struct token* preprocessing_lex_define_directive(struct Lexer_Data *lexer_data,struct Source_Location *where);struct token* preprocessing_lex_normal_define_directive(struct Lexer_Data *lexer_data,struct Source_Location *where,struct identifier *id,struct token *first_replacement_token);F diff --git a/src/semantics/program/translation_unit.c b/src/semantics/program/translation_unit.c --- a/src/semantics/program/translation_unit.c +++ b/src/semantics/program/translation_unit.cstruct Translation_Data *dummy_data;struct Scope *dummy_scope;- #warning not done yettoken_ptr_goto_next_token(ptr);token_ptr_jump_to_first(ptr,if_directive->controlling_expression);delete_translation_data(dummy_data);delete_scope(dummy_scope);}- void token_ptr_execute_ifdef_directive(struct Token_Pointer *ptr,struct token_ifdef_directive *ifdef_directive)+ void token_ptr_execute_ifdef_directive(struct Token_Pointer *ptr,struct token_ifdefndef_directive *ifdef_directive){token_ptr_goto_next_token(ptr);+ if(token_is_a_macro(ifdef_directive->id,ptr->macro_expansion_number,ptr->program->current_translation_unit_number))+ token_ptr_jump_to_first(ptr,ifdef_directive->if_defined);+ else+ token_ptr_jump_to_first(ptr,ifdef_directive->if_undefined);}- void token_ptr_execute_ifndef_directive(struct Token_Pointer *ptr,struct token_ifndef_directive *ifndef_directive)+ void token_ptr_execute_ifndef_directive(struct Token_Pointer *ptr,struct token_ifdefndef_directive *ifndef_directive){- //++ptr->number_of_last_expanded_macro;token_ptr_goto_next_token(ptr);+ if(token_is_a_macro(ifndef_directive->id,ptr->macro_expansion_number,ptr->program->current_translation_unit_number))+ token_ptr_jump_to_first(ptr,ifndef_directive->if_defined);+ else+ token_ptr_jump_to_first(ptr,ifndef_directive->if_undefined);}void token_ptr_execute_normal_define_directive(struct Token_Pointer *ptr,struct token_normal_define_directive *define_directive){token_ptr_execute_if_directive(token_pointer,(struct token_if_directive*)token);return 1;case PKW_IFDEF:- token_ptr_execute_ifdef_directive(token_pointer,(struct token_ifdef_directive*)token);+ token_ptr_execute_ifdef_directive(token_pointer,(struct token_ifdefndef_directive*)token);return 1;case PKW_IFNDEF:- token_ptr_execute_ifndef_directive(token_pointer,(struct token_ifndef_directive*)token);+ token_ptr_execute_ifndef_directive(token_pointer,(struct token_ifdefndef_directive*)token);return 1;case PKW_ELSE:wonky_assert(SHOULD_NOT_REACH_HERE);F diff --git a/src/semantics/program/translation_unit.h b/src/semantics/program/translation_unit.h --- a/src/semantics/program/translation_unit.h +++ b/src/semantics/program/translation_unit.hvoid token_ptr_execute_include_directive(struct Token_Pointer *ptr,struct token_include_directive *include_directive);void token_ptr_execute_if_directive(struct Token_Pointer *ptr,struct token_if_directive *if_directive);- void token_ptr_execute_ifdef_directive(struct Token_Pointer *ptr,struct token_ifdef_directive *ifdef_directive);- void token_ptr_execute_ifndef_directive(struct Token_Pointer *ptr,struct token_ifndef_directive *ifndef_directive);+ void token_ptr_execute_ifdef_directive(struct Token_Pointer *ptr,struct token_ifdefndef_directive *ifdef_directive);+ void token_ptr_execute_ifndef_directive(struct Token_Pointer *ptr,struct token_ifdefndef_directive *ifndef_directive);void token_ptr_execute_normal_define_directive(struct Token_Pointer *ptr,struct token_normal_define_directive *define_directive);void token_ptr_execute_functionlike_define_directive(struct Token_Pointer *ptr,struct token_functionlike_define_directive *define_directive);void token_ptr_execute_undef_directive(struct Token_Pointer *ptr,struct token_undef_directive *undef_directive);F diff --git a/src/syntax/automatas/generator/keyword_list.c b/src/syntax/automatas/generator/keyword_list.c --- a/src/syntax/automatas/generator/keyword_list.c +++ b/src/syntax/automatas/generator/keyword_list.c.data_string="NULL"},{+ .keyword="ifndef",+ .preprocessing_kw_string="PKW_IFNDEF",+ .kw_string="KW_ID",+ .action_string="AUTOMATA_ACTION_DISPENSE_TOKEN",+ .data_string="NULL"+ },+ {.keyword="elif",.preprocessing_kw_string="PKW_ELIF",.kw_string="KW_ID",F diff --git a/src/syntax/token/token.c b/src/syntax/token/token.c --- a/src/syntax/token/token.c +++ b/src/syntax/token/token.creturn (struct token*)ret;}+ _Bool token_is_identifier_in_preprocessing(struct token *token)+ {+ wonky_assert(token!=NULL);+ return token->type==KW_ID || token_is_a_special_macro(token) || token_is_keyword(token);+ }+ _Bool token_is_a_special_macro(struct token *token)+ {+ enum LEXER_TYPE type;++ wonky_assert(token!=NULL);++ type=token->type;+ return type==PKW_FILE_MACRO || type==PKW_DATE_MACRO || type==PKW_LINE_MACRO || type==PKW_STDC_MACRO || type==PKW_STDC_HOSTED_MACRO || type==PKW_STDC_VERSION_MACRO ||+ type==PKW_TIME_MACRO;+ }+ _Bool token_is_a_macro(struct token *token,size_t macro_expansion_number,size_t translation_unit_number)+ {+ wonky_assert(token!=NULL);++ if(token->type==KW_ID)+ return id_is_a_macro(((struct token_identifier*)token)->id,macro_expansion_number,translation_unit_number);+ else+ return token_is_a_special_macro(token) || token_is_keyword(token);+ }#endifF diff --git a/src/syntax/token/token.h b/src/syntax/token/token.h --- a/src/syntax/token/token.h +++ b/src/syntax/token/token.hstruct Queue *if_true;struct Queue *if_false;};- struct token_ifdef_directive+ struct token_ifdefndef_directive{enum LEXER_TYPE type;struct Source_Location_Delta *delta;- struct identifier *id;- struct Queue_Node *if_defined;- struct Queue_Node *if_undefined;- struct Queue_Node *end_of_ifdef_directive;- };- struct token_ifndef_directive- {- enum LEXER_TYPE type;- struct Source_Location_Delta *delta;- struct identifier *id;- struct Queue_Node *if_undefined;- struct Queue_Node *if_defined;- struct Queue_Node *end_of_ifndef_directive;+ struct token *id; /*keywords are also identifiers in preprocessing*/+ struct Queue *if_defined;+ struct Queue *if_undefined;};struct token_normal_define_directive{struct token* get_stdc_version_macro_token(struct Source_Location *current_location,struct Source_Location *previous_location);struct token* get_time_macro_token(struct Source_Location *current_location,struct Source_Location *previous_location);char* get_string_from_token(struct token* token);- void delete_token(struct token* token);_Bool token_is_keyword(struct token *token);+ _Bool token_is_identifier_in_preprocessing(struct token *token);+ _Bool token_is_a_special_macro(struct token *token);++ _Bool token_is_a_macro(struct token *token,size_t macro_expansion_number,size_t translation_unit_number);++++ void delete_token(struct token* token);#endifF diff --git a/src/syntax/token/token.hh b/src/syntax/token/token.hh --- a/src/syntax/token/token.hh +++ b/src/syntax/token/token.hhstruct token_string;struct token_include_directive;struct token_if_directive;- struct token_ifdef_directive;- struct token_ifndef_directive;+ struct token_ifdefndef_directive;struct token_normal_define_directive;struct token_functionlike_define_directive;struct token_functionlike_define_argument;