#ifndef WONKY_TOKEN_C
#define WONKY_TOKEN_C WONKY_TOKEN_C
#include <token.h>
struct token* get_small_token(enum LEXER_TYPE type,struct Source_Location *current_location,struct Source_Location *previous_location)
{
struct token_identifier *ret;
ret=wonky_malloc(sizeof(struct token_identifier));
ret->type=type;
ret->delta=get_source_location_delta(previous_location,current_location);
return (struct token*)ret;
}
struct token* get_id_token(struct identifier *id,struct Source_Location *current_location,struct Source_Location *previous_location)
{
struct token_identifier *ret;
ret=wonky_malloc(sizeof(struct token_identifier));
ret->type=KW_ID;
ret->delta=get_source_location_delta(previous_location,current_location);
ret->id=id;
return (struct token*)ret;
}
struct token* get_keyword_token(enum LEXER_TYPE type,struct Source_Location *current_location,struct Source_Location *previous_location,struct identifier *id)
{
struct token_keyword *ret;
ret=wonky_malloc(sizeof(struct token_keyword));
ret->type=type;
ret->delta=get_source_location_delta(previous_location,current_location);
ret->id=id;
return (struct token*)ret;
}
struct token* get_punctuator_token(enum LEXER_TYPE type,struct Source_Location *current_location,struct Source_Location *previous_location)
{
struct token_punctuator *ret;
ret=wonky_malloc(sizeof(struct token_punctuator));
ret->type=type;
ret->delta=get_source_location_delta(previous_location,current_location);
ret->punctuator_type=PUNCTUATOR_NORMAL;/*TODO*/
return (struct token*)ret;
}
struct token* get_constant_token(enum LEXER_TYPE bare_type,struct Source_Location *current_location,struct Source_Location *previous_location,char *data,size_t size)
{
struct token_constant *ret;
ret=wonky_malloc(sizeof(struct token_constant));
ret->delta=get_source_location_delta(previous_location,current_location);
ret->type=KW_CONSTANT;
switch(bare_type)
{
case KW_HEXADECIMAL_CONSTANT:
ret->constant=extract_literal_integer_hex(data,size,TC_NONE,TSIGN_SIGNED);
break;
case KW_DECIMAL_CONSTANT:
ret->constant=extract_literal_integer_dec(data,size,TC_NONE,TSIGN_SIGNED);
break;
case KW_OCTAL_CONSTANT:
ret->constant=extract_literal_integer_octal(data,size,TC_NONE,TSIGN_SIGNED);
break;
case KW_UNSIGNED_DECIMAL_CONSTANT:
ret->constant=extract_literal_integer_dec(data,size,TC_NONE,TSIGN_UNSIGNED);
break;
case KW_UNSIGNED_OCTAL_CONSTANT:
ret->constant=extract_literal_integer_octal(data,size,TC_NONE,TSIGN_UNSIGNED);
break;
case KW_UNSIGNED_HEXADECIMAL_CONSTANT:
ret->constant=extract_literal_integer_hex(data,size,TC_NONE,TSIGN_UNSIGNED);
break;
case KW_UNSIGNED_LONG_HEXADECIMAL_CONSTANT:
ret->constant=extract_literal_integer_hex(data,size,TC_LONG,TSIGN_UNSIGNED);
break;
case KW_UNSIGNED_LONG_OCTAL_CONSTANT:
ret->constant=extract_literal_integer_octal(data,size,TC_LONG,TSIGN_UNSIGNED);
break;
case KW_UNSIGNED_LONG_DECIMAL_CONSTANT:
ret->constant=extract_literal_integer_dec(data,size,TC_LONG,TSIGN_UNSIGNED);
break;
case KW_UNSIGNED_LONG_LONG_DECIMAL_CONSTANT:
ret->constant=extract_literal_integer_dec(data,size,TC_LONG_LONG,TSIGN_UNSIGNED);
break;
case KW_UNSIGNED_LONG_LONG_HEXADECIMAL_CONSTANT:
ret->constant=extract_literal_integer_hex(data,size,TC_LONG_LONG,TSIGN_UNSIGNED);
break;
case KW_UNSIGNED_LONG_LONG_OCTAL_CONSTANT:
ret->constant=extract_literal_integer_octal(data,size,TC_LONG_LONG,TSIGN_UNSIGNED);
break;
case KW_LONG_HEXADECIMAL_CONSTANT:
ret->constant=extract_literal_integer_hex(data,size,TC_LONG,TSIGN_SIGNED);
break;
case KW_LONG_OCTAL_CONSTANT:
ret->constant=extract_literal_integer_octal(data,size,TC_LONG,TSIGN_SIGNED);
break;
case KW_LONG_DECIMAL_CONSTANT:
ret->constant=extract_literal_integer_dec(data,size,TC_LONG,TSIGN_SIGNED);
break;
case KW_LONG_LONG_HEXADECIMAL_CONSTANT:
ret->constant=extract_literal_integer_hex(data,size,TC_LONG_LONG,TSIGN_SIGNED);
break;
case KW_LONG_LONG_OCTAL_CONSTANT:
ret->constant=extract_literal_integer_hex(data,size,TC_LONG_LONG,TSIGN_SIGNED);
break;
case KW_LONG_LONG_DECIMAL_CONSTANT:
ret->constant=extract_literal_integer_dec(data,size,TC_LONG_LONG,TSIGN_SIGNED);
break;
case KW_DOUBLE_DECIMAL_CONSTANT:
ret->constant=extract_literal_double_dec(data,size,TC_NONE);
break;
case KW_LONG_DOUBLE_DECIMAL_CONSTANT:
ret->constant=extract_literal_double_dec(data,size,TC_LONG);
break;
case KW_FLOAT_DECIMAL_CONSTANT:
ret->constant=extract_literal_float_dec(data,size);
break;
case KW_DOUBLE_HEXADECIMAL_CONSTANT:
ret->constant=extract_literal_double_hex(data,size,TC_NONE);
break;
case KW_LONG_DOUBLE_HEXADECIMAL_CONSTANT:
ret->constant=extract_literal_double_hex(data,size,TC_LONG);
break;
case KW_FLOAT_HEXADECIMAL_CONSTANT:
ret->constant=extract_literal_float_hex(data,size);
break;
case KW_CHAR_CONSTANT:
ret->constant=extract_literal_char(data,size);
break;
case KW_WIDE_CHAR_CONSTANT:
ret->constant=extract_literal_wide_char(data,size);
break;
default:
wonky_assert(SHOULD_NOT_REACH_HERE);
}
return (struct token*)ret;
}
struct token* get_constant_long_long_int_token(struct Source_Location *current_location,struct Source_Location *previous_location,long long int number)
{
struct token_constant *ret;
ret=wonky_malloc(sizeof(struct token_constant));
ret->delta=get_source_location_delta(previous_location,current_location);
ret->type=KW_CONSTANT;
ret->constant=get_long_long_int_constant(number);
return (struct token*)ret;
}
struct token* get_string_token(enum LEXER_TYPE bare_type,struct Source_Location *current_location,struct Source_Location *previous_location,char *data,size_t size)
{
struct token_string *ret;
ret=wonky_malloc(sizeof(struct token_string));
ret->type=bare_type;
ret->delta=get_source_location_delta(previous_location,current_location);
if(bare_type==KW_STRING)
{
ret->constant=extract_literal_string(data,size);
}else if(bare_type==KW_WIDE_STRING)
{
ret->constant=extract_literal_wide_string(data,size);
}else
{
wonky_assert(SHOULD_NOT_REACH_HERE);
}
return (struct token*)ret;
}
struct token* get_include_directive_token(struct Source_Location *current_location,struct Source_Location *previous_location,struct Queue *tokens)
{
struct token_include_directive *ret;
ret=wonky_malloc(sizeof(struct token_string));
ret->delta=get_source_location_delta(previous_location,current_location);
ret->tokens=tokens;
ret->type=PKW_INCLUDE;
return (struct token*)ret;
}
struct token* get_hashtag_hashtag_operator(struct Source_Location *current_location,struct Source_Location *previous_location,struct Queue *operands)
{
struct token_hashtag_hastag_operator *ret;
ret=wonky_malloc(sizeof(struct token_hashtag_hastag_operator));
ret->type=PKW_HASHTAG_HASHTAG_OP;
ret->delta=get_source_location_delta(previous_location,current_location);
ret->operands=operands;
return (struct token*)ret;
}
struct token* get_error_token(const char *msg,struct Source_Location *current_location,struct Source_Location *previous_location,struct Program *program,...)
{
struct token_error *ret;
va_list args;
struct wonky_str hold_err;
hold_err=wonky_string_make();
va_start(args,program);
wonky_string_vprintf(&hold_err,msg,args);
va_end(args);
ret=wonky_malloc(sizeof(struct token_error));
ret->type=LT_ERROR;
ret->delta=get_source_location_delta(previous_location,current_location);
ret->error=get_wonky_message(WONKY_MESSAGE_TYPE_ERROR,WONKY_MESSAGE_SOURCE_PREPROCESSING,current_location->line,current_location->column,current_location->src->src_name->name,current_location->src->src_name->name_size,"%s",hold_err.cs);
return (struct token*)ret;
}
struct token* get_eof_token()
{
struct token *ret;
ret=wonky_malloc(sizeof(struct token));
ret->type=LT_EOF;
ret->delta=wonky_malloc(sizeof(struct Source_Location_Delta));
ret->delta->line_offset=0;
ret->delta->column=0;
ret->delta->location=&start_of_file;
return ret;
}
struct token* get_token_from_two_adjacent_strings(struct token_string *first,struct token_string *second)
{
struct token_string *ret;
ret=wonky_malloc(sizeof(struct token_string));
ret->type=KW_STRING;
ret->delta=first->delta;
ret->constant=concatenate_string_literals(first->constant,second->constant);
return (struct token*)ret;
}
struct token* get_token_from_two_strings_with_a_space_between(struct token_string *first,struct token_string *second)
{
struct token_string *ret;
ret=wonky_malloc(sizeof(struct token_string));
ret->type=KW_STRING;
ret->delta=first->delta;
ret->constant=concatenate_string_literals_with_space_between(first->constant,second->constant);
return (struct token*)ret;
}
struct token* get_file_macro_token(struct Source_Location *current_location,struct Source_Location *previous_location)
{
struct token *ret;
ret=wonky_malloc(sizeof(struct token));
ret->type=PKW_FILE_MACRO;
ret->delta=get_source_location_delta(previous_location,current_location);
return ret;
}
static char *ascdate(const struct tm *timeptr)
{
static const char mon_name[12][3] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
static char result[30];
if(timeptr==NULL || timeptr->tm_mday>=33 || timeptr->tm_mon>=12 || timeptr->tm_year>=9999)
{
wonky_assert(SHOULD_NOT_REACH_HERE);
return "Could not determine the date";
}
sprintf(result, "%.3s %s%d %d",
mon_name[timeptr->tm_mon],
(timeptr->tm_mday<10?" ":""),
timeptr->tm_mday,
1900 + timeptr->tm_year);
return result;
}
struct token* get_date_macro_token(struct Source_Location *current_location,struct Source_Location *previous_location)
{
struct tm *tm;
time_t t;
char *ret;
size_t size;
t=time(NULL);
if((time_t)(-1)==t)
goto error;
tm=gmtime(&t);
if(tm==NULL)
goto error;
ret=ascdate(tm);
size=gstrnlen(ret,27);
return (struct token*)get_string_token(KW_STRING,current_location,previous_location,ret,size);
error:
return (struct token*)get_string_token(
KW_STRING,
current_location,
current_location,
"Time could not be determined",
sizeof("Time could not be determined"));
}
struct token* get_line_macro_token(struct Source_Location *current_location,struct Source_Location *previous_location)
{
struct token *ret;
ret=wonky_malloc(sizeof(struct token));
ret->type=PKW_LINE_MACRO;
ret->delta=get_source_location_delta(previous_location,current_location);;
return ret;
}
struct token* get_stdc_macro_token(struct Source_Location *current_location,struct Source_Location *previous_location)
{
struct token *ret;
ret=wonky_malloc(sizeof(struct token));
ret->type=PKW_STDC_MACRO;
ret->delta=get_source_location_delta(previous_location,current_location);;
return ret;
}
struct token* get_stdc_hosted_macro_token(struct Source_Location *current_location,struct Source_Location *previous_location)
{
struct token *ret;
ret=wonky_malloc(sizeof(struct token));
ret->type=PKW_STDC_HOSTED_MACRO;
ret->delta=get_source_location_delta(previous_location,current_location);;
return ret;
}
struct token* get_stdc_version_macro_token(struct Source_Location *current_location,struct Source_Location *previous_location)
{
struct token *ret;
ret=wonky_malloc(sizeof(struct token));
ret->type=PKW_STDC_VERSION_MACRO;
ret->delta=get_source_location_delta(previous_location,current_location);;
return ret;
}
static char *asctime_for_macro(const struct tm *timeptr)
{
static char result[30];
if(timeptr==NULL || timeptr->tm_hour>24 || timeptr->tm_sec>60 || timeptr->tm_min>60)
{
wonky_assert(SHOULD_NOT_REACH_HERE);
return "Could not determine the date";
}
sprintf(result, "%.2d:%.2d:%.2d",
timeptr->tm_hour,
timeptr->tm_min,
timeptr->tm_sec
);
return result;
}
struct token* get_time_macro_token(struct Source_Location *current_location,struct Source_Location *previous_location)
{
struct tm *tm;
time_t t;
char *ret;
size_t size;
t=time(NULL);
if((time_t)(-1)==t)
goto error;
tm=gmtime(&t);
if(tm==NULL)
goto error;
ret=asctime_for_macro(tm);
size=gstrnlen(ret,27);
return (struct token*)get_string_token(
KW_STRING,
current_location,
previous_location,
ret,size);
error:
return (struct token*)get_string_token(KW_STRING,current_location,current_location,"Time could not be determined",sizeof("Time could not be determined"));
}
char* get_string_from_token(struct token* token,size_t *size)
{
char *ret;
if(token->type==KW_ID)
{
ret=((struct token_identifier*)token)->id->data;
*size=((struct token_identifier*)token)->id->size;
}else if(token_is_keyword(token))
{
ret=((struct token_keyword*)token)->id->data;
*size=((struct token_keyword*)token)->id->size;
}else if(token->type==KW_CONSTANT)
{
ret=="constant";
*size=sizeof("constant")-1;
}else
{
#warning hack
ret=(char*)lexer_type_to_string_map[token->type];
if(ret==NULL) ret="";
*size=gstrnlen(ret,100);
}
return ret;
}
void delete_token(struct token* token)
{
wonky_free(token);
}
_Bool token_is_keyword(struct token *token)
{
switch(token->type)
{
case KW_AUTO:
case KW_DO:
case KW_DOUBLE:
case KW_INT:
case KW_STRUCT:
case KW_BREAK:
case KW_ELSE:
case KW_LONG:
case KW_SWITCH:
case KW_CASE:
case KW_ENUM:
case KW_REGISTER:
case KW_TYPEDEF:
case KW_CHAR:
case KW_EXTERN:
case KW_RETURN:
case KW_UNION:
case KW_CONST:
case KW_FLOAT:
case KW_SHORT:
case KW_UNSIGNED:
case KW_CONTINUE:
case KW_FOR:
case KW_SIGNED:
case KW_VOID:
case KW_DEFAULT:
case KW_GOTO:
case KW_SIZEOF:
case KW_VOLATILE:
case KW_IF:
case KW_STATIC:
case KW_WHILE:
case KW_INLINE:
case KW_RESTRICT:
case KW_BOOL:
case KW_COMPLEX:
case KW_IMAGINARY:
return 1;
default:
return 0;
}
}
struct token* get_normal_define_directive_token(struct Source_Location *current_location,struct Source_Location *previous_location,struct identifier *id)
{
struct token_normal_define_directive *ret;
ret=wonky_malloc(sizeof(struct token_normal_define_directive));
ret->type=PKW_DEFINE;
ret->delta=get_source_location_delta(previous_location,current_location);
ret->define=get_normal_define_directive(id);
return (struct token*)ret;
}
struct token* get_functionlike_define_directive_token(struct Source_Location *current_location,struct Source_Location *previous_location,struct identifier *id)
{
struct token_functionlike_define_directive *ret;
ret->type=PKW_FUNCTIONLIKE_DEFINE;
ret->delta=get_source_location_delta(previous_location,current_location);
ret->define=get_functionlike_define_directive(id);
return (struct token*)ret;
}
struct token* get_functionlike_define_directive_argument_token(struct Source_Location *current_location,struct Source_Location *previous_location,struct functionlike_define_directive_argument *argument)
{
struct token_functionlike_define_argument *ret;
ret=wonky_malloc(sizeof(struct token_functionlike_define_argument));
ret->type=PKW_MACRO_ARGUMENT;
ret->delta=get_source_location_delta(previous_location,current_location);
ret->argument=argument;
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 translation_unit_number)
{
wonky_assert(token!=NULL);
if(token->type==KW_ID)
return id_is_a_macro(((struct token_identifier*)token)->id,translation_unit_number);
else if(token_is_keyword(token))
return id_is_a_macro(((struct token_keyword*)token)->id,translation_unit_number);
else
return token_is_a_special_macro(token) || token_is_keyword(token);
}
#endif