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.c
case 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.h
struct 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.c
struct Translation_Data *dummy_data;
struct Scope *dummy_scope;
- #warning not done yet
token_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.h
void 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.c
return (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);
+ }
#endif
F 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.h
struct 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);
#endif
F 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.hh
struct 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;