print_builtin_symbol((const builtin_symbol_expression_t*) expression);
break;
+ case EXPR_CONDITIONAL:
case EXPR_OFFSETOF:
case EXPR_STATEMENT:
case EXPR_SELECT:
EXPR_CALL,
EXPR_UNARY,
EXPR_BINARY,
+ EXPR_CONDITIONAL,
EXPR_SELECT,
EXPR_ARRAY_ACCESS,
EXPR_SIZEOF,
#include "symbol_table_t.h"
#include "adt/error.h"
#include "adt/strset.h"
+#include "adt/util.h"
#include <assert.h>
#include <errno.h>
//static FILE **input_stack;
//static char **buf_stack;
-static
-void error_prefix_at(const char *input_name, unsigned linenr)
+static void error_prefix_at(const char *input_name, unsigned linenr)
{
fprintf(stderr, "%s:%u: Error: ", input_name, linenr);
}
-static
-void error_prefix(void)
+static void error_prefix(void)
{
error_prefix_at(lexer_token.source_position.input_name,
lexer_token.source_position.linenr);
}
-static
-void parse_error(const char *msg)
+static void parse_error(const char *msg)
{
error_prefix();
fprintf(stderr, "%s\n", msg);
}
-static inline
-void next_char(void)
+static inline void next_real_char(void)
{
bufpos++;
if(bufpos >= bufend) {
bufend = buf + MAX_PUTBACK + s;
}
c = *(bufpos);
-#ifdef DEBUG_CHARS
- printf("nchar '%c'\n", c);
-#endif
}
-static inline
-void put_back(int pc)
+static inline void put_back(int pc)
{
char *p = (char*) bufpos - 1;
bufpos--;
#endif
}
+static inline void next_char(void);
-static
-int replace_trigraph(void)
-{
-#define MATCH_TRIGRAPH(ch,replacement) \
- case ch: \
- c = replacement; \
- return 1;
+#define MATCH_NEWLINE(code) \
+ case '\r': \
+ next_char(); \
+ if(c == '\n') { \
+ next_char(); \
+ } \
+ lexer_token.source_position.linenr++; \
+ code; \
+ case '\n': \
+ next_char(); \
+ lexer_token.source_position.linenr++; \
+ code;
+static void maybe_concat_lines(void)
+{
+ next_char();
switch(c) {
- MATCH_TRIGRAPH('=', '#')
- MATCH_TRIGRAPH('(', '[')
- MATCH_TRIGRAPH('/', '\\')
- MATCH_TRIGRAPH(')', ']')
- MATCH_TRIGRAPH('\'', '^')
- MATCH_TRIGRAPH('<', '{')
- MATCH_TRIGRAPH('!', '|')
- MATCH_TRIGRAPH('>', '}')
- MATCH_TRIGRAPH('-', '~')
+ MATCH_NEWLINE(return;)
+
default:
break;
}
- return 0;
+ put_back(c);
+ c = '\\';
}
-#define SKIP_TRIGRAPHS(custom_putback, no_trigraph_code) \
- case '?': \
- next_char(); \
- if(c != '?') { \
- custom_putback; \
- put_back(c); \
- c = '?'; \
- no_trigraph_code; \
- } \
- next_char(); \
- if(replace_trigraph()) { \
- break; \
- } \
- custom_putback; \
- put_back('?'); \
- put_back(c); \
- c = '?'; \
- no_trigraph_code;
-
-#define EAT_NEWLINE(newline_code) \
- if(c == '\r') { \
- next_char(); \
- if(c == '\n') \
- next_char(); \
- lexer_token.source_position.linenr++; \
- newline_code; \
- } else if(c == '\n') { \
- next_char(); \
- lexer_token.source_position.linenr++; \
- newline_code; \
+static inline void next_char(void)
+{
+ next_real_char();
+
+ /* filter trigraphs */
+ if(UNLIKELY(c == '\\')) {
+ maybe_concat_lines();
+ goto end_of_next_char;
+ }
+
+ if(LIKELY(c != '?'))
+ goto end_of_next_char;
+
+ next_real_char();
+ if(LIKELY(c != '?')) {
+ put_back(c);
+ c = '?';
+ goto end_of_next_char;
+ }
+
+ next_real_char();
+ switch(c) {
+ case '=': c = '#'; break;
+ case '(': c = '['; break;
+ case '/': c = '\\'; maybe_concat_lines(); break;
+ case ')': c = ']'; break;
+ case '\'': c = '^'; break;
+ case '<': c = '{'; break;
+ case '!': c = '|'; break;
+ case '>': c = '}'; break;
+ case '-': c = '~'; break;
+ default:
+ put_back('?');
+ put_back(c);
+ c = '?';
+ break;
}
+end_of_next_char:
+#ifdef DEBUG_CHARS
+ printf("nchar '%c'\n", c);
+#else
+ ;
+#endif
+}
+
#define SYMBOL_CHARS \
case 'a': \
case 'b': \
case '8': \
case '9':
-static
-void parse_symbol(void)
+static void parse_symbol(void)
{
symbol_t *symbol;
char *string;
while(1) {
switch(c) {
- case '\\':
- next_char();
- EAT_NEWLINE(break;)
- goto end_symbol;
-
DIGITS
SYMBOL_CHARS
obstack_1grow(&symbol_obstack, c);
next_char();
break;
- case '?':
- next_char();
- if(c != '?') {
- put_back(c);
- c = '?';
- goto end_symbol;
- }
- next_char();
- if(replace_trigraph())
- break;
- put_back('?');
- put_back(c);
- c = '?';
- goto end_symbol;
-
default:
goto end_symbol;
}
}
+
end_symbol:
obstack_1grow(&symbol_obstack, '\0');
}
}
-static
-void parse_number_hex(void)
+static void parse_number_hex(void)
{
assert(c == 'x' || c == 'X');
next_char();
}
}
-static
-void parse_number_oct(void)
+static void parse_number_oct(void)
{
- assert(c == 'o' || c == 'O');
- next_char();
-
int value = 0;
while(1) {
if ('0' <= c && c <= '7') {
value = 8 * value + c - '0';
+ } else if (c == '8' || c == '9') {
+ parse_error("invalid octal number");
+ lexer_token.type = T_ERROR;
+ return;
} else {
lexer_token.type = T_INTEGER;
lexer_token.v.intvalue = value;
}
}
-static
-void parse_number_dec(int first_char)
+static void parse_number_dec(void)
{
int value = 0;
- if(first_char > 0) {
- assert(first_char >= '0' && first_char <= '9');
- value = first_char - '0';
- }
for(;;) {
if (isdigit(c)) {
}
}
-static
-void parse_number(void)
+static void parse_integer_suffix(void)
{
- // TODO check for overflow
- // TODO check for various invalid inputs sequences
-
- if (c == '0') {
- next_char();
- switch (c) {
- case 'X':
- case 'x': parse_number_hex(); break;
- case 'o':
- case 'O': parse_number_oct(); break;
- default: parse_number_dec('0');
- }
- } else {
- parse_number_dec(0);
- }
if(c == 'U' || c == 'U') {
/* TODO do something with the suffixes... */
next_char();
}
}
+static void parse_number(void)
+{
+ if (c == '0') {
+ next_char();
+ switch (c) {
+ case 'X':
+ case 'x': parse_number_hex(); break;
+ default: parse_number_oct(); break;
+ }
+ } else {
+ parse_number_dec();
+ }
+
+ parse_integer_suffix();
+}
+
static int parse_octal_sequence(void)
{
int value = 0;
next_char();
switch(ec) {
- case '"': return '"';
+ case '"': return '"';
case '\'': return'\'';
- case '\\':
- EAT_NEWLINE(break;)
- return '\\';
+ case '\\': return '\\';
+ case '?': return '\?';
case 'a': return '\a';
case 'b': return '\b';
case 'f': return '\f';
case '6':
case '7':
return parse_octal_sequence();
- case '?':
- if(c != '?') {
- return '?';
- }
- /* might be a trigraph */
- next_char();
- if(replace_trigraph()) {
- break;
- }
- put_back(c);
- c = '?';
- return '?';
-
case EOF:
parse_error("reached end of file while parsing escape sequence");
return EOF;
return result;
}
-static
-void parse_string_literal(void)
+static void parse_string_literal(void)
{
unsigned start_linenr = lexer_token.source_position.linenr;
char *string;
while(1) {
switch(c) {
- SKIP_TRIGRAPHS(,
- obstack_1grow(&symbol_obstack, '?');
- next_char();
- break;
- )
-
case '\\':
next_char();
- EAT_NEWLINE(break;)
int ec = parse_escape_sequence();
obstack_1grow(&symbol_obstack, ec);
break;
lexer_token.v.string = result;
}
-#define MATCH_NEWLINE(code) \
- case '\r': \
- next_char(); \
- if(c == '\n') { \
- next_char(); \
- } \
- lexer_token.source_position.linenr++; \
- code; \
- case '\n': \
- next_char(); \
- lexer_token.source_position.linenr++; \
- code;
-
-static
-void parse_character_constant(void)
+static void parse_character_constant(void)
{
assert(c == '\'');
next_char();
int found_char = 0;
while(1) {
switch(c) {
- SKIP_TRIGRAPHS(,
- next_char();
- found_char = '?';
- break;
- )
-
case '\\':
next_char();
- EAT_NEWLINE(break;)
found_char = parse_escape_sequence();
break;
lexer_token.v.intvalue = found_char;
}
-static
-void skip_multiline_comment(void)
+static void skip_multiline_comment(void)
{
unsigned start_linenr = lexer_token.source_position.linenr;
- int had_star = 0;
while(1) {
switch(c) {
case '*':
next_char();
- had_star = 1;
- break;
-
- case '/':
- next_char();
- if(had_star) {
+ if(c == '/') {
+ next_char();
return;
}
- had_star = 0;
break;
- case '\\':
- next_char();
- EAT_NEWLINE(break;)
- had_star = 0;
- break;
-
- case '?':
- next_char();
- if(c != '?') {
- had_star = 0;
- break;
- }
- next_char();
- if(replace_trigraph())
- break;
- put_back(c);
- c = '?';
- had_star = 0;
- /* we don't put back the 2nd ? as the comment text is discarded
- * anyway */
- break;
-
- MATCH_NEWLINE(had_star = 0; break;)
+ MATCH_NEWLINE(break;)
case EOF:
error_prefix_at(lexer_token.source_position.input_name,
start_linenr);
fprintf(stderr, "at end of file while looking for comment end\n");
return;
+
default:
- had_star = 0;
next_char();
break;
}
}
}
-static
-void skip_line_comment(void)
+static void skip_line_comment(void)
{
while(1) {
switch(c) {
- case '?':
- next_char();
- if(c != '?')
- break;
- next_char();
- if(replace_trigraph())
- break;
- put_back('?');
- /* we don't put back the 2nd ? as the comment text is discarded
- * anyway */
- break;
-
- case '\\':
- next_char();
- if(c == '\n') {
- next_char();
- lexer_token.source_position.linenr++;
- }
- break;
-
case EOF:
- case '\r':
+ return;
+
case '\n':
+ case '\r':
return;
default:
static token_t pp_token;
-static inline
-void next_pp_token(void)
+static inline void next_pp_token(void)
{
lexer_next_preprocessing_token();
pp_token = lexer_token;
}
-static
-void eat_until_newline(void)
+static void eat_until_newline(void)
{
while(pp_token.type != '\n' && pp_token.type != T_EOF) {
next_pp_token();
}
}
-static
-void error_directive(void)
+static void error_directive(void)
{
error_prefix();
fprintf(stderr, "#error directive: \n");
/* parse pp-tokens until new-line */
}
-static
-void define_directive(void)
+static void define_directive(void)
{
lexer_next_preprocessing_token();
if(lexer_token.type != T_IDENTIFIER) {
}
}
-static
-void ifdef_directive(int is_ifndef)
+static void ifdef_directive(int is_ifndef)
{
(void) is_ifndef;
lexer_next_preprocessing_token();
//extect_newline();
}
-static
-void endif_directive(void)
+static void endif_directive(void)
{
//expect_newline();
}
-static
-void parse_line_directive(void)
+static void parse_line_directive(void)
{
if(pp_token.type != T_INTEGER) {
parse_error("expected integer");
eat_until_newline();
}
-static
-void parse_preprocessor_identifier(void)
+static void parse_preprocessor_identifier(void)
{
assert(pp_token.type == T_IDENTIFIER);
symbol_t *symbol = pp_token.v.symbol;
}
}
-static
-void parse_preprocessor_directive()
+static void parse_preprocessor_directive()
{
next_pp_token();
return;
#define ELSE_CODE(code) \
- SKIP_TRIGRAPHS(, \
- code; \
- ) \
- \
- case '\\': \
- next_char(); \
- EAT_NEWLINE(break;) \
- /* fallthrough */ \
default: \
code; \
} \
parse_character_constant();
return;
- case '\\':
- next_char();
- if(c == '\n') {
- next_char();
- lexer_token.source_position.linenr++;
- break;
- } else {
- parse_error("unexpected '\\' found");
- lexer_token.type = T_ERROR;
- }
- return;
-
case '.':
MAYBE_PROLOG
case '.':
ELSE('#')
case '?':
- next_char();
- /* just a simple ? */
- if(c != '?') {
- lexer_token.type = '?';
- return;
- }
- /* might be a trigraph */
- next_char();
- if(replace_trigraph()) {
- break;
- }
- put_back(c);
- c = '?';
- lexer_token.type = '?';
- return;
-
case '[':
case ']':
case '(':
case '~':
case ';':
case ',':
+ case '\\':
lexer_token.type = c;
next_char();
return;
void lexer_open_stream(FILE *stream, const char *input_name)
{
input = stream;
- lexer_token.source_position.linenr = 0;
+ lexer_token.source_position.linenr = 1;
lexer_token.source_position.input_name = input_name;
- /* we place a virtual '\n' at the beginning so the lexer knows we're at the
- * beginning of a line */
- c = '\n';
+ next_char();
}
void exit_lexer(void)
c'
'd\
??/
-\'
-'??/\'
-'\\'
+'
+'??/\''\\'
'??/??/'
'\??/'
-'newline'
integer number 97
'newline'
integer number 98
'newline'
integer number 99
'newline'
-integer number 92
-'newline'
-integer number 92
+integer number 100
'newline'
-integer number 92
+integer number 39
+integer number 39
'newline'
-integer number 92
+integer number 39
'newline'
-integer number 92
+integer number 39
'newline'
'newline'
end of file
'newline'
'newline'
'newline'
-'newline'
end of file
-'newline'
symbol 'hohohohohohoho'
'newline'
symbol 'ho'
-'newline'
'++'
'++'
'+'
'<<='
'newline'
'<<'
-'<'
-'='
+'<='
'newline'
'<<='
'newline'
'>>='
'newline'
'>>'
-'>'
-'='
+'>='
'newline'
'>>='
'newline'
-'newline'
string 'bla?'
'newline'
string 'bla??'
-'newline'
symbol 't'
'newline'
symbol 'tt'
'newline'
'newline'
symbol 'one'
+'\'
symbol 'two'
'newline'
end of file
-'newline'
'?'
'newline'
'?'
static declaration_t *last_declaration = NULL;
static struct obstack temp_obst;
+static type_t *type_int = NULL;
+static type_t *type_const_char = NULL;
+static type_t *type_string = NULL;
+static type_t *type_void = NULL;
+static type_t *type_size_t = NULL;
+
static statement_t *parse_compound_statement(void);
static statement_t *parse_statement(void);
* called when we find a 2nd declarator for an identifier we already have a
* declarator for
*/
-static int is_compatible_declaration (declaration_t *declaration,
+static bool is_compatible_declaration (declaration_t *declaration,
declaration_t *previous)
{
/* TODO: not correct yet */
return NULL;
}
-static type_t *parse_compound_type_specifier(int is_struct)
+static type_t *parse_compound_type_specifier(bool is_struct)
{
if(is_struct) {
eat(T_struct);
/* TODO: if type != NULL for the following rules issue an error */
case T_struct:
- type = parse_compound_type_specifier(1);
+ type = parse_compound_type_specifier(true);
break;
case T_union:
- type = parse_compound_type_specifier(0);
+ type = parse_compound_type_specifier(false);
break;
case T_enum:
type = parse_enum_specifier();
{
string_literal_t *cnst = allocate_ast_zero(sizeof(cnst[0]));
- cnst->expression.type = EXPR_STRING_LITERAL;
- cnst->value = parse_string_literals();
+ cnst->expression.type = EXPR_STRING_LITERAL;
+ cnst->expression.datatype = type_string;
+ cnst->value = parse_string_literals();
return (expression_t*) cnst;
}
{
const_t *cnst = allocate_ast_zero(sizeof(cnst[0]));
- cnst->expression.type = EXPR_CONST;
- cnst->value = token.v.intvalue;
+ cnst->expression.type = EXPR_CONST;
+ cnst->expression.datatype = type_int;
+ cnst->value = token.v.intvalue;
next_token();
parser_print_error_prefix();
fprintf(stderr, "unknown symbol '%s' found.\n", ref->symbol->string);
}
- ref->declaration = ref->symbol->declaration;
+ ref->declaration = ref->symbol->declaration;
+ ref->expression.datatype = ref->declaration->type;
next_token();
return (expression_t*) ref;
}
+static void check_cast_allowed(expression_t *expression, type_t *dest_type)
+{
+ (void) expression;
+ (void) dest_type;
+ /* TODO check if cast is allowed and issue warnings/errors */
+}
+
static expression_t *parse_cast(void)
{
unary_expression_t *cast = allocate_ast_zero(sizeof(cast[0]));
expect(')');
expression_t *value = parse_sub_expression(20);
+ check_cast_allowed(value, type);
+
cast->expression.datatype = type;
cast->value = value;
expression->expression.type = EXPR_STATEMENT;
expression->statement = parse_compound_statement();
+ /* find last statement and use it's type */
+ const statement_t *last_statement = NULL;
+ const statement_t *statement = expression->statement;
+ for( ; statement != NULL; statement = statement->next) {
+ last_statement = statement;
+ }
+
+ if(last_statement->type == STATEMENT_EXPRESSION) {
+ const expression_statement_t *expression_statement =
+ (const expression_statement_t*) last_statement;
+ expression->expression.datatype
+ = expression_statement->expression->datatype;
+ } else {
+ expression->expression.datatype = type_void;
+ }
+
expect(')');
return (expression_t*) expression;
/* TODO */
string_literal_t *expression = allocate_ast_zero(sizeof(expression[0]));
- expression->expression.type = EXPR_FUNCTION;
- expression->value = "TODO: FUNCTION";
+ expression->expression.type = EXPR_FUNCTION;
+ expression->expression.datatype = type_string;
+ expression->value = "TODO: FUNCTION";
return (expression_t*) expression;
}
/* TODO */
string_literal_t *expression = allocate_ast_zero(sizeof(expression[0]));
- expression->expression.type = EXPR_PRETTY_FUNCTION;
- expression->value = "TODO: PRETTY FUNCTION";
+ expression->expression.type = EXPR_PRETTY_FUNCTION;
+ expression->expression.datatype = type_string;
+ expression->value = "TODO: PRETTY FUNCTION";
return (expression_t*) expression;
}
offsetof_expression_t *expression
= allocate_ast_zero(sizeof(expression[0]));
- expression->expression.type = EXPR_OFFSETOF;
+ expression->expression.type = EXPR_OFFSETOF;
+ expression->expression.datatype = type_size_t;
expect('(');
expression->type = parse_typename();
= allocate_ast_zero(sizeof(expression[0]));
expression->expression.type = EXPR_BUILTIN_SYMBOL;
+ /* TODO: set datatype */
+
expression->symbol = token.v.symbol;
next_token();
}
static expression_t *parse_array_expression(unsigned precedence,
- expression_t *array_ref)
+ expression_t *array_ref)
{
(void) precedence;
array_access_expression_t *array_access
= allocate_ast_zero(sizeof(array_access[0]));
- array_access->expression.type = EXPR_ARRAY_ACCESS;
- array_access->array_ref = array_ref;
- array_access->index = parse_expression();
+ array_access->expression.type = EXPR_ARRAY_ACCESS;
+ array_access->array_ref = array_ref;
+ array_access->index = parse_expression();
+
+ type_t *array_type = array_ref->datatype;
+ if(array_type != NULL) {
+ if(array_type->type == TYPE_POINTER) {
+ pointer_type_t *pointer = (pointer_type_t*) array_type;
+ array_access->expression.datatype = pointer->points_to;
+ } else {
+ parse_error("array access on non-pointer type");
+ }
+ }
if(token.type != ']') {
parse_error_expected("Problem while parsing array access", ']', 0);
return (expression_t*) array_access;
}
-static type_t *get_expression_type(const expression_t *expression)
-{
- (void) expression;
- /* TODO */
- return NULL;
-}
-
-static int is_declaration_specifier(const token_t *token,
- int only_type_specifiers)
+static bool is_declaration_specifier(const token_t *token,
+ bool only_type_specifiers)
{
declaration_t *declaration;
sizeof_expression_t *sizeof_expression
= allocate_ast_zero(sizeof(sizeof_expression[0]));
- sizeof_expression->expression.type = EXPR_SIZEOF;
+ sizeof_expression->expression.type = EXPR_SIZEOF;
+ sizeof_expression->expression.datatype = type_size_t;
- if(token.type == '(' && is_declaration_specifier(look_ahead(1), 1)) {
+ if(token.type == '(' && is_declaration_specifier(look_ahead(1), true)) {
next_token();
sizeof_expression->type = parse_typename();
expect(')');
} else {
expression_t *expression = parse_sub_expression(precedence);
- sizeof_expression->type = get_expression_type(expression);
+ sizeof_expression->type = expression->datatype;
sizeof_expression->size_expression = expression;
}
select->expression.type = EXPR_SELECT;
select->compound = compound;
+ /* TODO: datatype */
+
if(token.type != T_IDENTIFIER) {
- parse_error_expected("Problem while parsing compound select",
- T_IDENTIFIER, 0);
+ parse_error_expected("Problem while parsing select", T_IDENTIFIER, 0);
return NULL;
}
select->symbol = token.v.symbol;
(void) precedence;
call_expression_t *call = allocate_ast_zero(sizeof(call[0]));
- call->expression.type = EXPR_CALL;
- call->method = expression;
+ call->expression.type = EXPR_CALL;
+ call->method = expression;
/* parse arguments */
eat('(');
}
expect(')');
+ type_t *type = expression->datatype;
+ if(type != NULL && type->type != TYPE_METHOD) {
+ parser_print_error_prefix();
+ fprintf(stderr, "expected a method type for call but found type ");
+ print_type(expression->datatype);
+ fprintf(stderr, "\n");
+ } else {
+ method_type_t *method_type = (method_type_t*) type;
+ call->expression.datatype = method_type->result_type;
+ }
+
return (expression_t*) call;
}
+static void type_error(const char *msg, const source_position_t source_position,
+ const type_t *type)
+{
+ parser_print_error_prefix_pos(source_position);
+ fprintf(stderr, "%s, but found type ", msg);
+ print_type(type);
+ fputc('\n', stderr);
+}
+
+static void type_error_incompatible(const char *msg,
+ const source_position_t source_position, const type_t *type1,
+ const type_t *type2)
+{
+ parser_print_error_prefix_pos(source_position);
+ fprintf(stderr, "%s, incompatible types: ", msg);
+ print_type(type1);
+ fprintf(stderr, " - ");
+ print_type(type2);
+ fprintf(stderr, ")\n");
+}
+
+static type_t *get_type_after_conversion(const type_t *type1,
+ const type_t *type2)
+{
+ /* TODO... */
+ (void) type2;
+ return (type_t*) type1;
+}
+
static expression_t *parse_conditional_expression(unsigned precedence,
expression_t *expression)
{
conditional_expression_t *conditional
= allocate_ast_zero(sizeof(conditional[0]));
+ conditional->expression.type = EXPR_CONDITIONAL;
conditional->condition = expression;
+ /* 6.5.15.2 */
+ type_t *condition_type = conditional->condition->datatype;
+ if(condition_type != NULL) {
+ if(!is_type_scalar(condition_type)) {
+ type_error("expected a scalar type", expression->source_position,
+ condition_type);
+ }
+ }
+
conditional->true_expression = parse_expression();
expect(':');
conditional->false_expression = parse_sub_expression(precedence);
+ type_t *true_type = conditional->true_expression->datatype;
+ if(true_type == NULL)
+ return (expression_t*) conditional;
+ type_t *false_type = conditional->false_expression->datatype;
+ if(false_type == NULL)
+ return (expression_t*) conditional;
+
+ /* 6.4.15.3 */
+ if(true_type == false_type) {
+ conditional->expression.datatype = true_type;
+ } else if(is_type_arithmetic(true_type) && is_type_arithmetic(false_type)) {
+ type_t *result = get_type_after_conversion(true_type, false_type);
+ /* TODO: create implicit convs if necessary */
+ conditional->expression.datatype = result;
+ } else if(true_type->type == TYPE_POINTER &&
+ false_type->type == TYPE_POINTER &&
+ true /* TODO compatible points_to types */) {
+ /* TODO */
+ } else if(/* (is_null_ptr_const(true_type) && false_type->type == TYPE_POINTER)
+ || (is_null_ptr_const(false_type) &&
+ true_type->type == TYPE_POINTER) TODO*/ false) {
+ /* TODO */
+ } else if(/* 1 is pointer to object type, other is void* */ false) {
+ /* TODO */
+ } else {
+ type_error_incompatible("problem while parsing conditional",
+ expression->source_position, true_type,
+ false_type);
+ }
+
return (expression_t*) conditional;
}
} else {
left = parse_primary_expression();
}
- if(left != NULL)
- left->source_position = source_position;
+ assert(left != NULL);
+ assert(left->type != EXPR_INVALID);
+ left->source_position = source_position;
while(true) {
if(token.type < 0) {
break;
left = parser->infix_parser(parser->infix_precedence, left);
- if(left != NULL)
- left->source_position = source_position;
+
+ assert(left != NULL);
+ assert(left->type != EXPR_INVALID);
+ left->source_position = source_position;
}
return left;
set_context(&statement->context);
if(token.type != ';') {
- if(is_declaration_specifier(&token, 0)) {
+ if(is_declaration_specifier(&token, false)) {
parse_declaration();
} else {
statement->initialisation = parse_expression();
{
init_expression_parsers();
obstack_init(&temp_obst);
+
+ type_int = make_atomic_type(ATOMIC_TYPE_INT, 0);
+ type_size_t = make_atomic_type(ATOMIC_TYPE_UINT, 0);
+ type_const_char = make_atomic_type(ATOMIC_TYPE_CHAR, TYPE_QUALIFIER_CONST);
+ type_void = make_atomic_type(ATOMIC_TYPE_VOID, 0);
+ type_string = make_pointer_type(type_const_char, 0);
}
void exit_parser(void)
#include <stdio.h>
#include <assert.h>
#include "type_t.h"
+#include "type_hash.h"
#include "adt/error.h"
static struct obstack _type_obst;
}
}
-int type_valid(const type_t *type)
+bool type_valid(const type_t *type)
{
return type->type != TYPE_INVALID;
}
-int is_type_int(const type_t *type)
+bool is_type_int(const type_t *type)
{
if(type->type != TYPE_ATOMIC)
return 0;
}
}
+bool is_type_arithmetic(const type_t *type)
+{
+ if(type->type != TYPE_ATOMIC)
+ return 0;
+
+ atomic_type_t *atomic_type = (atomic_type_t*) type;
+ switch(atomic_type->atype) {
+ case ATOMIC_TYPE_CHAR:
+ case ATOMIC_TYPE_SCHAR:
+ case ATOMIC_TYPE_UCHAR:
+ case ATOMIC_TYPE_SHORT:
+ case ATOMIC_TYPE_USHORT:
+ case ATOMIC_TYPE_INT:
+ case ATOMIC_TYPE_UINT:
+ case ATOMIC_TYPE_LONG:
+ case ATOMIC_TYPE_ULONG:
+ case ATOMIC_TYPE_LONGLONG:
+ case ATOMIC_TYPE_ULONGLONG:
+ case ATOMIC_TYPE_FLOAT:
+ case ATOMIC_TYPE_DOUBLE:
+ case ATOMIC_TYPE_LONG_DOUBLE:
+#ifdef PROVIDE_COMPLEX
+ case ATOMIC_TYPE_FLOAT_COMPLEX:
+ case ATOMIC_TYPE_DOUBLE_COMPLEX:
+ case ATOMIC_TYPE_LONG_DOUBLE_COMPLEX:
+#endif
+#ifdef PROVIDE_IMAGINARY
+ case ATOMIC_TYPE_FLOAT_IMAGINARY:
+ case ATOMIC_TYPE_DOUBLE_IMAGINARY:
+ case ATOMIC_TYPE_LONG_DOUBLE_IMAGINARY:
+#endif
+ return 1;
+ case ATOMIC_TYPE_INVALID:
+ case ATOMIC_TYPE_VOID:
+ case ATOMIC_TYPE_BOOL:
+ return 0;
+ }
+
+ return 0;
+}
+
+bool is_type_scalar(const type_t *type)
+{
+ if(type->type == TYPE_POINTER)
+ return 1;
+
+ return is_type_arithmetic(type);
+}
+
+static type_t *identify_new_type(type_t *type)
+{
+ type_t *result = typehash_insert(type);
+ if(result != type) {
+ obstack_free(type_obst, type);
+ }
+ return result;
+}
+
+type_t *make_atomic_type(atomic_type_type_t type, unsigned qualifiers)
+{
+ atomic_type_t *atomic_type
+ = obstack_alloc(type_obst, sizeof(atomic_type[0]));
+ memset(atomic_type, 0, sizeof(atomic_type[0]));
+ atomic_type->type.type = TYPE_ATOMIC;
+ atomic_type->type.qualifiers = qualifiers;
+ atomic_type->atype = type;
+
+ return identify_new_type((type_t*) atomic_type);
+}
+
+type_t *make_pointer_type(type_t *points_to, unsigned qualifiers)
+{
+ pointer_type_t *pointer_type
+ = obstack_alloc(type_obst, sizeof(pointer_type[0]));
+ memset(pointer_type, 0, sizeof(pointer_type[0]));
+ pointer_type->type.type = TYPE_POINTER;
+ pointer_type->type.qualifiers = qualifiers;
+ pointer_type->points_to = points_to;
+
+ return identify_new_type((type_t*) pointer_type);
+}
+
static __attribute__((unused))
void dbg_type(const type_t *type)
{
#define TYPE_H
#include <stdio.h>
+#include <stdbool.h>
#include "symbol.h"
typedef struct type_t type_t;
void type_set_output(FILE *out);
/**
- * returns 1 if type contains integer numbers
+ * returns true if type contains integer numbers
*/
-int is_type_int(const type_t *type);
+bool is_type_integer(const type_t *type);
/**
- * returns 1 if the type is valid. A type is valid if it contains no unresolved
- * references anymore and is not of TYPE_INVALID.
+ * returns true if the type is valid. A type is valid if it contains no
+ * unresolved references anymore and is not of TYPE_INVALID.
*/
-int type_valid(const type_t *type);
+bool type_valid(const type_t *type);
+
+/**
+ * returns true if the type is an arithmetic type (6.2.18)
+ */
+bool is_type_arithmetic(const type_t *type);
+
+/**
+ * returns true if the type is a scalar type (6.2.21)
+ */
+bool is_type_scalar(const type_t *type);
#endif
static unsigned hash_atomic_type(const atomic_type_t *type)
{
unsigned some_prime = 27644437;
+ unsigned result = type->atype * some_prime;
- return type->atype * some_prime;
+ return result;
}
static unsigned hash_pointer_type(const pointer_type_t *type)
compound_type_t *next;
};
+type_t *make_atomic_type(atomic_type_type_t type, unsigned qualifiers);
+type_t *make_pointer_type(type_t *points_to, unsigned qualifiers);
+
#endif