#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
+#include <ctype.h>
#include "adt/error.h"
static int indent;
static void print_statement(const statement_t *statement);
+static void print_declaration(const declaration_t *declaration);
static void print_indent(void)
{
fprintf(out, "\t");
}
-static
-void print_const(const const_t *cnst)
+static void print_const(const const_t *cnst)
{
fprintf(out, "%d", cnst->value);
}
-static
-void print_string_literal(const string_literal_t *string_literal)
+static void print_string_literal(const string_literal_t *string_literal)
{
- /* TODO escape " and non-printable chars */
- fprintf(out, "\"%s\"", string_literal->value);
+ fputc('"', out);
+ for(const char *c = string_literal->value; *c != '\0'; ++c) {
+ switch(*c) {
+ case '\"': fputs("\\\"", out); break;
+ case '\\': fputs("\\\\", out); break;
+ case '\a': fputs("\\a", out); break;
+ case '\b': fputs("\\b", out); break;
+ case '\f': fputs("\\f", out); break;
+ case '\n': fputs("\\n", out); break;
+ case '\r': fputs("\\r", out); break;
+ case '\t': fputs("\\t", out); break;
+ case '\v': fputs("\\v", out); break;
+ case '\?': fputs("\\?", out); break;
+ default:
+ if(!isprint(*c)) {
+ fprintf(out, "\\x%x", *c);
+ break;
+ }
+ fputc(*c, out);
+ break;
+ }
+ }
+ fputc('"', out);
}
-static
-void print_call_expression(const call_expression_t *call)
+static void print_call_expression(const call_expression_t *call)
{
print_expression(call->method);
fprintf(out, "(");
fprintf(out, ")");
}
-static
-void print_binary_expression(const binary_expression_t *binexpr)
+static void print_binary_expression(const binary_expression_t *binexpr)
{
fprintf(out, "(");
print_expression(binexpr->left);
fprintf(out, " ");
switch(binexpr->type) {
- case BINEXPR_INVALID:
- fprintf(out, "INVOP");
- break;
- case BINEXPR_ASSIGN:
- fprintf(out, "<-");
- break;
- case BINEXPR_ADD:
- fprintf(out, "+");
- break;
- case BINEXPR_SUB:
- fprintf(out, "-");
- break;
- case BINEXPR_NOTEQUAL:
- fprintf(out, "/=");
- break;
- case BINEXPR_EQUAL:
- fprintf(out, "=");
- break;
- case BINEXPR_LESS:
- fprintf(out, "<");
- break;
- case BINEXPR_LESSEQUAL:
- fprintf(out, "<=");
- break;
- case BINEXPR_GREATER:
- fprintf(out, ">");
- break;
- case BINEXPR_GREATEREQUAL:
- fprintf(out, ">=");
- break;
- default:
- /* TODO: add missing ops */
- fprintf(out, "op%d", binexpr->type);
- break;
+ case BINEXPR_INVALID: fputs("INVOP", out); break;
+ case BINEXPR_COMMA: fputs(",", out); break;
+ case BINEXPR_ASSIGN: fputs("=", out); break;
+ case BINEXPR_ADD: fputs("+", out); break;
+ case BINEXPR_SUB: fputs("-", out); break;
+ case BINEXPR_MUL: fputs("*", out); break;
+ case BINEXPR_MOD: fputs("%", out); break;
+ case BINEXPR_DIV: fputs("/", out); break;
+ case BINEXPR_BITWISE_OR: fputs("|", out); break;
+ case BINEXPR_BITWISE_AND: fputs("&", out); break;
+ case BINEXPR_BITWISE_XOR: fputs("^", out); break;
+ case BINEXPR_LOGICAL_OR: fputs("||", out); break;
+ case BINEXPR_LOGICAL_AND: fputs("&&", out); break;
+ case BINEXPR_NOTEQUAL: fputs("!=", out); break;
+ case BINEXPR_EQUAL: fputs("==", out); break;
+ case BINEXPR_LESS: fputs("<", out); break;
+ case BINEXPR_LESSEQUAL: fputs("<=", out); break;
+ case BINEXPR_GREATER: fputs(">", out); break;
+ case BINEXPR_GREATEREQUAL: fputs(">=", out); break;
+ case BINEXPR_SHIFTLEFT: fputs("<<", out); break;
+ case BINEXPR_SHIFTRIGHT: fputs(">>", out); break;
+
+ case BINEXPR_ADD_ASSIGN: fputs("+=", out); break;
+ case BINEXPR_SUB_ASSIGN: fputs("-=", out); break;
+ case BINEXPR_MUL_ASSIGN: fputs("*=", out); break;
+ case BINEXPR_MOD_ASSIGN: fputs("%=", out); break;
+ case BINEXPR_DIV_ASSIGN: fputs("/=", out); break;
+ case BINEXPR_BITWISE_OR_ASSIGN: fputs("|=", out); break;
+ case BINEXPR_BITWISE_AND_ASSIGN: fputs("&=", out); break;
+ case BINEXPR_BITWISE_XOR_ASSIGN: fputs("^=", out); break;
+ case BINEXPR_SHIFTLEFT_ASSIGN: fputs("<<=", out); break;
+ case BINEXPR_SHIFTRIGHT_ASSIGN: fputs(">>=", out); break;
}
fprintf(out, " ");
print_expression(binexpr->right);
fprintf(out, ")");
}
+static void print_unary_expression(const unary_expression_t *unexpr)
+{
+ switch(unexpr->type) {
+ case UNEXPR_NEGATE: fputs("-", out); break;
+ case UNEXPR_PLUS: fputs("+", out); break;
+ case UNEXPR_NOT: fputs("!", out); break;
+ case UNEXPR_BITWISE_NEGATE: fputs("~", out); break;
+ case UNEXPR_PREFIX_INCREMENT: fputs("++", out); break;
+ case UNEXPR_PREFIX_DECREMENT: fputs("--", out); break;
+ case UNEXPR_DEREFERENCE: fputs("*", out); break;
+ case UNEXPR_TAKE_ADDRESS: fputs("&", out); break;
+
+ case UNEXPR_POSTFIX_INCREMENT:
+ fputs("(", out);
+ print_expression(unexpr->value);
+ fputs(")", out);
+ fputs("++", out);
+ return;
+ case UNEXPR_POSTFIX_DECREMENT:
+ fputs("(", out);
+ print_expression(unexpr->value);
+ fputs(")", out);
+ fputs("--", out);
+ return;
+ case UNEXPR_CAST:
+ fputs("(", out);
+ print_type(unexpr->expression.datatype);
+ fputs(")", out);
+ break;
+ case UNEXPR_INVALID:
+ fprintf(out, "unop%d", unexpr->type);
+ break;
+ }
+ fputs("(", out);
+ print_expression(unexpr->value);
+ fputs(")", out);
+}
+
static void print_reference_expression(const reference_expression_t *ref)
{
fprintf(out, "%s", ref->declaration->symbol->string);
}
+static void print_array_expression(const array_access_expression_t *expression)
+{
+ fputs("(", out);
+ print_expression(expression->array_ref);
+ fputs(")[", out);
+ print_expression(expression->index);
+ fputs("]", out);
+}
+
+static void print_sizeof_expression(const sizeof_expression_t *expression)
+{
+ fputs("sizeof", out);
+ if(expression->size_expression != NULL) {
+ fputc('(', out);
+ print_expression(expression->size_expression);
+ fputc(')', out);
+ } else {
+ fputc('(', out);
+ print_type(expression->type);
+ fputc(')', out);
+ }
+}
+
void print_expression(const expression_t *expression)
{
switch(expression->type) {
case EXPR_CONST:
print_const((const const_t*) expression);
break;
+ case EXPR_FUNCTION:
+ case EXPR_PRETTY_FUNCTION:
case EXPR_STRING_LITERAL:
print_string_literal((const string_literal_t*) expression);
break;
case EXPR_REFERENCE:
print_reference_expression((const reference_expression_t*) expression);
break;
- case EXPR_UNARY:
- case EXPR_SELECT:
case EXPR_ARRAY_ACCESS:
+ print_array_expression((const array_access_expression_t*) expression);
+ break;
+ case EXPR_UNARY:
+ print_unary_expression((const unary_expression_t*) expression);
+ break;
case EXPR_SIZEOF:
+ print_sizeof_expression((const sizeof_expression_t*) expression);
+ break;
+
+ case EXPR_STATEMENT:
+ case EXPR_SELECT:
/* TODO */
fprintf(out, "some expression of type %d", expression->type);
break;
}
}
-static
-void print_compound_statement(const compound_statement_t *block)
+static void print_compound_statement(const compound_statement_t *block)
{
fputs("{\n", out);
indent++;
fputs("}\n", out);
}
-static
-void print_return_statement(const return_statement_t *statement)
+static void print_return_statement(const return_statement_t *statement)
{
fprintf(out, "return ");
if(statement->return_value != NULL)
fputs(";\n", out);
}
-static
-void print_expression_statement(const expression_statement_t *statement)
+static void print_expression_statement(const expression_statement_t *statement)
{
print_expression(statement->expression);
+ fputs(";\n", out);
}
-static
-void print_goto_statement(const goto_statement_t *statement)
+static void print_goto_statement(const goto_statement_t *statement)
{
fprintf(out, "goto ");
if(statement->label != NULL) {
fputs(";\n", out);
}
-static
-void print_label_statement(const label_statement_t *statement)
+static void print_label_statement(const label_statement_t *statement)
{
fprintf(out, "%s:\n", statement->symbol->string);
}
-static
-void print_if_statement(const if_statement_t *statement)
+static void print_if_statement(const if_statement_t *statement)
{
- fprintf(out, "if(");
+ fputs("if(", out);
print_expression(statement->condition);
- fprintf(out, ") ");
+ fputs(") ", out);
if(statement->true_statement != NULL) {
print_statement(statement->true_statement);
}
if(statement->false_statement != NULL) {
print_indent();
- fprintf(out, "else ");
+ fputs("else ", out);
print_statement(statement->false_statement);
}
}
-static
-void print_declaration_statement(const declaration_statement_t *statement)
+static void print_switch_statement(const switch_statement_t *statement)
+{
+ fputs("switch(", out);
+ print_expression(statement->expression);
+ fputs(") ", out);
+ print_statement(statement->body);
+}
+
+static void print_case_label(const case_label_statement_t *statement)
{
- (void) statement;
- fprintf(out, "*declaration statement*");
+ if(statement->expression == NULL) {
+ fputs("default:\n", out);
+ } else {
+ fputs("case ", out);
+ print_expression(statement->expression);
+ fputs(":\n", out);
+ }
+}
+
+static void print_declaration_statement(
+ const declaration_statement_t *statement)
+{
+ declaration_t *declaration = statement->declarations_begin;
+ for( ; declaration != statement->declarations_end->next;
+ declaration = declaration->next) {
+ print_declaration(declaration);
+ }
+}
+
+static void print_while_statement(const while_statement_t *statement)
+{
+ fputs("while(", out);
+ print_expression(statement->condition);
+ fputs(") ", out);
+ print_statement(statement->body);
+}
+
+static void print_do_while_statement(const do_while_statement_t *statement)
+{
+ fputs("do ", out);
+ print_statement(statement->body);
+ print_indent();
+ fputs("while(", out);
+ print_expression(statement->condition);
+ fputs(");\n", out);
+}
+
+static void print_for_statemenet(const for_statement_t *statement)
+{
+ fprintf(out, "for(TODO) ");
+ print_statement(statement->body);
}
void print_statement(const statement_t *statement)
case STATEMENT_GOTO:
print_goto_statement((const goto_statement_t*) statement);
break;
+ case STATEMENT_CONTINUE:
+ fputs("continue;\n", out);
+ break;
+ case STATEMENT_BREAK:
+ fputs("break;\n", out);
+ break;
case STATEMENT_IF:
print_if_statement((const if_statement_t*) statement);
break;
+ case STATEMENT_SWITCH:
+ print_switch_statement((const switch_statement_t*) statement);
+ break;
+ case STATEMENT_CASE_LABEL:
+ print_case_label((const case_label_statement_t*) statement);
+ break;
case STATEMENT_DECLARATION:
print_declaration_statement((const declaration_statement_t*) statement);
break;
+ case STATEMENT_WHILE:
+ print_while_statement((const while_statement_t*) statement);
+ break;
+ case STATEMENT_DO_WHILE:
+ print_do_while_statement((const do_while_statement_t*) statement);
+ break;
+ case STATEMENT_FOR:
+ print_for_statemenet((const for_statement_t*) statement);
+ break;
case STATEMENT_INVALID:
- default:
fprintf(out, "*invalid statement*");
break;
-
- }
-}
-
-#if 0
-static
-void print_method_parameters(const method_parameter_t *parameters,
- const method_type_t *method_type)
-{
- fprintf(out, "(");
-
- int first = 1;
- const method_parameter_t *parameter = parameters;
- const method_parameter_type_t *parameter_type
- = method_type->parameter_types;
- while(parameter != NULL && parameter_type != NULL) {
- if(!first) {
- fprintf(out, ", ");
- } else {
- first = 0;
- }
-
- print_type(parameter_type->type);
- fprintf(out, " %s", parameter->symbol->string);
-
- parameter = parameter->next;
- parameter_type = parameter_type->next;
}
- assert(parameter == NULL && parameter_type == NULL);
-
- fprintf(out, ")");
}
-#endif
-static
-void print_storage_class(storage_class_t storage_class)
+static void print_storage_class(storage_class_t storage_class)
{
switch(storage_class) {
+ case STORAGE_CLASS_ENUM_ENTRY:
case STORAGE_CLASS_NONE:
break;
case STORAGE_CLASS_TYPEDEF: fputs("typedef ", out); break;
}
}
-static
-void print_declaration(const declaration_t *declaration)
+static void print_declaration(const declaration_t *declaration)
{
print_storage_class(declaration->storage_class);
- print_type(declaration->type, declaration->symbol);
+ print_type_ext(declaration->type, declaration->symbol,
+ &declaration->context);
if(declaration->statement != NULL) {
fputs("\n", out);
print_statement(declaration->statement);
+ } else if(declaration->initializer != NULL) {
+ fputs(" = ", out);
+ print_expression(declaration->initializer);
+ fprintf(out, ";\n");
} else {
fprintf(out, ";\n");
}
typedef struct conditional_expression_t conditional_expression_t;
typedef struct expression_list_element_t expression_list_element_t;
typedef struct comma_expression_t comma_expression_t;
+typedef struct statement_expression_t statement_expression_t;
typedef struct declaration_t declaration_t;
typedef struct compound_statement_t compound_statement_t;
typedef struct return_statement_t return_statement_t;
typedef struct if_statement_t if_statement_t;
+typedef struct switch_statement_t switch_statement_t;
typedef struct declaration_statement_t declaration_statement_t;
typedef struct expression_statement_t expression_statement_t;
typedef struct goto_statement_t goto_statement_t;
typedef struct label_statement_t label_statement_t;
+typedef struct case_label_statement_t case_label_statement_t;
+typedef struct while_statement_t while_statement_t;
+typedef struct do_while_statement_t do_while_statement_t;
+typedef struct for_statement_t for_statement_t;
typedef struct translation_unit_t translation_unit_t;
typedef struct method_t method_t;
EXPR_SELECT,
EXPR_ARRAY_ACCESS,
EXPR_SIZEOF,
+
+ EXPR_FUNCTION,
+ EXPR_PRETTY_FUNCTION,
+ EXPR_STATEMENT
} expresion_type_t;
struct context_t {
declaration_t *declarations;
compound_type_t *structs;
compound_type_t *unions;
- compound_type_t *enums;
+ enum_type_t *enums;
};
struct expression_t {
BINEXPR_SHIFTRIGHT_ASSIGN,
BINEXPR_BITWISE_AND_ASSIGN,
BINEXPR_BITWISE_XOR_ASSIGN,
- BINEXPR_BITWISE_OR_ASSIGN
+ BINEXPR_BITWISE_OR_ASSIGN,
+ BINEXPR_COMMA
} binary_expression_type_t;
struct binary_expression_t {
struct sizeof_expression_t {
expression_t expression;
type_t *type;
+ expression_t *size_expression;
};
struct conditional_expression_t {
expression_t *false_expression;
};
-struct expression_list_element_t {
- expression_t *expression;
- expression_t *next;
-};
-
-struct comma_expression_t {
- expression_t expression;
- expression_list_element_t *expressions;
+struct statement_expression_t {
+ expression_t expression;
+ statement_t *statement;
};
typedef enum {
STORAGE_CLASS_EXTERN,
STORAGE_CLASS_STATIC,
STORAGE_CLASS_AUTO,
- STORAGE_CLASS_REGISTER
+ STORAGE_CLASS_REGISTER,
+ STORAGE_CLASS_ENUM_ENTRY
} storage_class_t;
struct declaration_t {
STATEMENT_RETURN,
STATEMENT_DECLARATION,
STATEMENT_IF,
+ STATEMENT_SWITCH,
STATEMENT_EXPRESSION,
STATEMENT_CONTINUE,
+ STATEMENT_BREAK,
STATEMENT_GOTO,
- STATEMENT_LABEL
+ STATEMENT_LABEL,
+ STATEMENT_CASE_LABEL,
+ STATEMENT_WHILE,
+ STATEMENT_DO_WHILE,
+ STATEMENT_FOR
} statement_type_t;
struct statement_t {
struct declaration_statement_t {
statement_t statement;
- declaration_t declaration;
+ declaration_t *declarations_begin;
+ declaration_t *declarations_end;
int value_number; /**< filled in by semantic phase */
int refs;
statement_t *false_statement;
};
+struct switch_statement_t {
+ statement_t statement;
+ expression_t *expression;
+ statement_t *body;
+};
+
struct goto_statement_t {
statement_t statement;
symbol_t *label_symbol;
label_statement_t *label;
};
+struct case_label_statement_t {
+ statement_t statement;
+ expression_t *expression;
+};
+
struct label_statement_t {
statement_t statement;
symbol_t *symbol;
expression_t *expression;
};
+struct while_statement_t {
+ statement_t statement;
+ expression_t *condition;
+ statement_t *body;
+};
+
+struct do_while_statement_t {
+ statement_t statement;
+ expression_t *condition;
+ statement_t *body;
+};
+
+struct for_statement_t {
+ statement_t statement;
+ expression_t *initialisation;
+ expression_t *condition;
+ expression_t *step;
+ statement_t *body;
+ context_t context;
+};
+
struct translation_unit_t {
context_t context;
};
static
void error_prefix_at(const char *input_name, unsigned linenr)
{
- fprintf(stderr, "%s:%d: Error: ", input_name, linenr);
+ fprintf(stderr, "%s:%u: Error: ", input_name, linenr);
}
static
}
int value = 0;
- for(;;) {
+ while(1) {
if (isdigit(c)) {
value = 16 * value + c - '0';
} else if ('A' <= c && c <= 'F') {
next_char();
int value = 0;
- for(;;) {
+ while(1) {
if ('0' <= c && c <= '7') {
value = 8 * value + c - '0';
} else {
} else {
parse_number_dec(0);
}
+ if(c == 'U' || c == 'U') {
+ /* TODO do something with the suffixes... */
+ next_char();
+ if(c == 'L' || c == 'l') {
+ next_char();
+ if(c == 'L' || c == 'l') {
+ next_char();
+ }
+ }
+ } else if(c == 'l' || c == 'L') {
+ next_char();
+ if(c == 'l' || c == 'L') {
+ next_char();
+ if(c == 'u' || c == 'U') {
+ next_char();
+ }
+ } else if(c == 'u' || c == 'U') {
+ next_char();
+ }
+ }
}
-static
-int parse_escape_sequence(void)
+static int parse_octal_sequence(void)
+{
+ int value = 0;
+ while(1) {
+ if(c < '0' || c > '7')
+ break;
+ value = 8 * value + c - '0';
+ next_char();
+ }
+
+ return value;
+}
+
+static int parse_hex_sequence(void)
+{
+ int value = 0;
+ while(1) {
+ if (c >= '0' && c <= '9') {
+ value = 16 * value + c - '0';
+ } else if ('A' <= c && c <= 'F') {
+ value = 16 * value + c - 'A' + 10;
+ } else if ('a' <= c && c <= 'f') {
+ value = 16 * value + c - 'a' + 10;
+ } else {
+ break;
+ }
+ next_char();
+ }
+
+ return value;
+}
+
+static int parse_escape_sequence(void)
{
while(1) {
int ec = c;
case 'r': return '\r';
case 't': return '\t';
case 'v': return '\v';
- case 'x': /* TODO parse hex number ... */
- parse_error("hex escape sequences not implemented yet");
- return EOF;
+ case 'x':
+ return parse_hex_sequence();
case '0':
case '1':
case '2':
case '5':
case '6':
case '7':
- /* TODO parse octal number ... */
- parse_error("octal escape sequences not implemented yet");
- return EOF;
+ return parse_octal_sequence();
case '?':
if(c != '?') {
return '?';
while(1) {
switch(c) {
SKIP_TRIGRAPHS(,
+ next_char();
found_char = '?';
break;
)
case '\\':
next_char();
EAT_NEWLINE(break;)
- found_char = '\\';
+ found_char = parse_escape_sequence();
break;
MATCH_NEWLINE(
ELSE('+')
case '-':
MAYBE_PROLOG
+ MAYBE('>', T_MINUSGREATER)
MAYBE('-', T_MINUSMINUS)
MAYBE('=', T_MINUSEQUAL)
ELSE('-')
MAYBE_PROLOG
MAYBE(':', T_LESSCOLON)
MAYBE('%', T_LESSPERCENT)
+ MAYBE('=', T_LESSEQUAL)
case '<':
MAYBE_PROLOG
MAYBE('=', T_LESSLESSEQUAL)
ELSE('<')
case '>':
MAYBE_PROLOG
+ MAYBE('=', T_GREATEREQUAL)
case '>':
MAYBE_PROLOG
MAYBE('=', T_GREATERGREATEREQUAL)
#include "symbol_table_t.h"
#include "token_t.h"
-token_t lexer_token;
+extern token_t lexer_token;
void lexer_next_token(void);
parser_print_error_prefix_pos(declaration->source_position);
fprintf(stderr, "definition of symbol '%s' with type ",
declaration->symbol->string);
- print_type(declaration->type, NULL);
+ print_type(declaration->type);
fputc('\n', stderr);
parser_print_error_prefix_pos(
previous_declaration->source_position);
fprintf(stderr, "is incompatible with previous declaration "
"of type ");
- print_type(previous_declaration->type, NULL);
+ print_type(previous_declaration->type);
fputc('\n', stderr);
}
return previous_declaration;
static expression_t *parse_constant_expression(void)
{
- /* TODO: not correct yet */
- return parse_expression();
+ /* start parsing at precedence 7 (conditional expression) */
+ return parse_sub_expression(7);
}
static expression_t *parse_assignment_expression(void)
{
- /* TODO: not correct yet */
- return parse_expression();
+ /* start parsing at precedence 2 (assignment expression) */
+ return parse_sub_expression(2);
}
static void parse_compound_type_entries(void);
}
} else if(token.type != '{') {
if(is_struct) {
- parse_error_expected("problem while parsing struct type specifiers",
+ parse_error_expected("problem while parsing struct type specifier",
T_IDENTIFIER, '{', 0);
} else {
- parse_error_expected("problem while parsing union type specifiers",
+ parse_error_expected("problem while parsing union type specifier",
T_IDENTIFIER, '{', 0);
}
return (type_t*) compound_type;
}
-static enum_entry_t *parse_enum_type_entries(void)
+static void parse_enum_entries(void)
{
eat('{');
if(token.type == '}') {
next_token();
parse_error("empty enum not allowed");
- return NULL;
+ return;
}
- enum_entry_t *result = NULL;
- enum_entry_t *last_entry = NULL;
do {
- enum_entry_t *entry = allocate_ast_zero(sizeof(entry[0]));
+ declaration_t *entry = allocate_ast_zero(sizeof(entry[0]));
+
if(token.type != T_IDENTIFIER) {
parse_error_expected("problem while parsing enum entry",
T_IDENTIFIER, 0);
eat_block();
- return result;
+ return;
}
- entry->symbol = token.v.symbol;
+ entry->storage_class = STORAGE_CLASS_ENUM_ENTRY;
+ entry->symbol = token.v.symbol;
+ entry->source_position = token.source_position;
next_token();
if(token.type == '=') {
next_token();
- entry->value = parse_constant_expression();
+ entry->initializer = parse_constant_expression();
}
- if(last_entry != NULL) {
- last_entry->next = entry;
- } else {
- result = entry;
- }
- last_entry = entry;
+ record_declaration(entry);
if(token.type != ',')
break;
next_token();
} while(token.type != '}');
- expect('}');
- return result;
+ expect_void('}');
+}
+
+static enum_type_t *find_enum_type(enum_type_t *types, const symbol_t *symbol)
+{
+ enum_type_t *type = types;
+ for( ; type != NULL; type = type->next) {
+ if(type->symbol == symbol)
+ return type;
+ }
+
+ return NULL;
}
static type_t *parse_enum_specifier(void)
{
eat(T_enum);
- enum_type_t *enum_type = allocate_type_zero(sizeof(enum_type[0]));
- enum_type->type.type = TYPE_ENUM;
- enum_type->source_position = token.source_position;
-
- /* TODO: rewrite to the same style as struct/union above to handle
- * type identities correctly
- */
+ symbol_t *symbol = NULL;
+ enum_type_t *enum_type = NULL;
if(token.type == T_IDENTIFIER) {
- enum_type->symbol = token.v.symbol;
+ symbol = token.v.symbol;
next_token();
- if(token.type == '{') {
- enum_type->entries = parse_enum_type_entries();
+
+ if(context != NULL) {
+ enum_type = find_enum_type(context->enums, symbol);
}
- } else if(token.type == '{') {
- enum_type->entries = parse_enum_type_entries();
- } else {
- parse_error_expected("problem while parsing enum type specifiers",
- T_IDENTIFIER, '{');
+ } else if(token.type != '{') {
+ parse_error_expected("problem while parsing enum type specifier",
+ T_IDENTIFIER, '{', 0);
+ return NULL;
+ }
+
+ if(enum_type == NULL) {
+ enum_type = allocate_type_zero(sizeof(enum_type[0]));
+ enum_type->type.type = TYPE_ENUM;
+ enum_type->source_position = token.source_position;
+ enum_type->symbol = symbol;
+ }
+
+ if(token.type == '{') {
+ if(enum_type->defined) {
+ parser_print_error_prefix();
+ fprintf(stderr, "multiple definitions of enum %s\n",
+ symbol->string);
+ enum_type->entries_begin = NULL;
+ enum_type->entries_end = NULL;
+ }
+ enum_type->defined = 1;
+
+ declaration_t *before = last_declaration;
+
+ parse_enum_entries();
+
+ if(before == NULL) {
+ enum_type->entries_begin = context->declarations;
+ } else {
+ enum_type->entries_begin = before->next;
+ }
+ enum_type->entries_end = last_declaration;
}
return (type_t*) enum_type;
case T_const: \
case T_restrict: \
case T_volatile: \
- case T_inline: \
- case T___extension__:
+ case T_inline:
#ifdef PROVIDE_COMPLEX
#define COMPLEX_SPECIFIERS \
return declarations;
case T_IDENTIFIER:
+ case T___extension__:
DECLARATION_START
declaration = parse_parameter();
if(declaration->type->type != TYPE_METHOD) {
parser_print_error_prefix();
fprintf(stderr, "Declarator ");
- print_type(declaration->type, declaration->symbol);
+ print_type_ext(declaration->type, declaration->symbol, NULL);
fprintf(stderr, " is not a method type.\n");
}
return (expression_t*) cast;
}
+static
+expression_t *parse_statement_expression(void)
+{
+ statement_expression_t *expression
+ = allocate_ast_zero(sizeof(expression[0]));
+ expression->expression.type = EXPR_STATEMENT;
+ expression->statement = parse_compound_statement();
+
+ expect(')');
+
+ return (expression_t*) expression;
+}
+
static
expression_t *parse_brace_expression(void)
{
declaration_t *declaration;
switch(token.type) {
+ case '{':
+ /* gcc extension: a stement expression */
+ return parse_statement_expression();
+
TYPE_QUALIFIERS
TYPE_SPECIFIERS
return parse_cast();
case T_IDENTIFIER:
declaration = token.v.symbol->declaration;
if(declaration != NULL &&
- (declaration->storage_class & STORAGE_CLASS_TYPEDEF)) {
+ (declaration->storage_class == STORAGE_CLASS_TYPEDEF)) {
return parse_cast();
}
}
return result;
}
+static
+expression_t *parse_function_keyword(void)
+{
+ eat(T___FUNCTION__);
+ /* TODO */
+
+ string_literal_t *expression = allocate_ast_zero(sizeof(expression[0]));
+ expression->expression.type = EXPR_FUNCTION;
+ expression->value = "TODO: FUNCTION";
+
+ return (expression_t*) expression;
+}
+
+static
+expression_t *parse_pretty_function_keyword(void)
+{
+ eat(T___PRETTY_FUNCTION__);
+ /* TODO */
+
+ string_literal_t *expression = allocate_ast_zero(sizeof(expression[0]));
+ expression->expression.type = EXPR_PRETTY_FUNCTION;
+ expression->value = "TODO: PRETTY FUNCTION";
+
+ return (expression_t*) expression;
+}
+
static
expression_t *parse_primary_expression(void)
{
return parse_string_const();
case T_IDENTIFIER:
return parse_reference();
+ case T___FUNCTION__:
+ return parse_function_keyword();
+ case T___PRETTY_FUNCTION__:
+ return parse_pretty_function_keyword();
case '(':
return parse_brace_expression();
}
}
static
-int is_type_specifier(const token_t *token)
+int is_declaration_specifier(const token_t *token, int only_type_specifiers)
{
declaration_t *declaration;
if(declaration->storage_class != STORAGE_CLASS_TYPEDEF)
return 0;
return 1;
+ STORAGE_CLASSES
+ TYPE_QUALIFIERS
+ if(only_type_specifiers)
+ return 0;
+ return 1;
+
default:
return 0;
}
= allocate_ast_zero(sizeof(sizeof_expression[0]));
sizeof_expression->expression.type = EXPR_SIZEOF;
- if(token.type == '(' && is_type_specifier(look_ahead(1))) {
+ if(token.type == '(' && is_declaration_specifier(look_ahead(1), 1)) {
next_token();
sizeof_expression->type = parse_typename();
expect(')');
} else {
- expression_t *expression = parse_sub_expression(precedence);
- sizeof_expression->type = get_expression_type(expression);
+ expression_t *expression = parse_sub_expression(precedence);
+ sizeof_expression->type = get_expression_type(expression);
+ sizeof_expression->size_expression = expression;
}
return (expression_t*) sizeof_expression;
{
(void) precedence;
- assert(token.type == '.' || token.type == T_SELECT);
+ assert(token.type == '.' || token.type == T_MINUSGREATER);
next_token();
select_expression_t *select = allocate_ast_zero(sizeof(select[0]));
while(1) {
call_argument_t *argument = allocate_ast_zero(sizeof(argument[0]));
- argument->expression = parse_expression();
+ /* we start parsing at precedence 2 so we don't get comma operators
+ * parsed */
+ argument->expression = parse_sub_expression(2);
if(last_argument == NULL) {
call->arguments = argument;
} else {
return (expression_t*) conditional;
}
+static expression_t *parse_extension(unsigned precedence)
+{
+ eat(T___extension__);
+
+ /* TODO enable extensions */
+
+ return parse_sub_expression(precedence);
+}
+
#define CREATE_UNARY_EXPRESSION_PARSER(token_type, unexpression_type) \
static \
expression_t *parse_##unexpression_type(unsigned precedence) \
\
binary_expression_t *binexpr \
= allocate_ast_zero(sizeof(binexpr[0])); \
- binexpr->expression.type = EXPR_BINARY; \
- binexpr->type = binexpression_type; \
- binexpr->left = left; \
- binexpr->right = right; \
+ binexpr->expression.type = EXPR_BINARY; \
+ binexpr->type = binexpression_type; \
+ binexpr->left = left; \
+ binexpr->right = right; \
\
return (expression_t*) binexpr; \
}
+CREATE_BINEXPR_PARSER(',', BINEXPR_COMMA)
CREATE_BINEXPR_PARSER('*', BINEXPR_MUL)
CREATE_BINEXPR_PARSER('/', BINEXPR_DIV)
CREATE_BINEXPR_PARSER('+', BINEXPR_ADD)
CREATE_BINEXPR_PARSER(T_PIPEPIPE, BINEXPR_LOGICAL_OR)
CREATE_BINEXPR_PARSER(T_LESSLESS, BINEXPR_SHIFTLEFT)
CREATE_BINEXPR_PARSER(T_GREATERGREATER, BINEXPR_SHIFTRIGHT)
+CREATE_BINEXPR_PARSER(T_PLUSEQUAL, BINEXPR_ADD_ASSIGN)
+CREATE_BINEXPR_PARSER(T_MINUSEQUAL, BINEXPR_SUB_ASSIGN)
+CREATE_BINEXPR_PARSER(T_ASTERISKEQUAL, BINEXPR_MUL_ASSIGN)
+CREATE_BINEXPR_PARSER(T_SLASHEQUAL, BINEXPR_DIV_ASSIGN)
+CREATE_BINEXPR_PARSER(T_PERCENTEQUAL, BINEXPR_MOD_ASSIGN)
+CREATE_BINEXPR_PARSER(T_LESSLESSEQUAL, BINEXPR_SHIFTLEFT_ASSIGN)
+CREATE_BINEXPR_PARSER(T_GREATERGREATEREQUAL, BINEXPR_SHIFTRIGHT_ASSIGN)
+CREATE_BINEXPR_PARSER(T_ANDEQUAL, BINEXPR_BITWISE_AND_ASSIGN)
+CREATE_BINEXPR_PARSER(T_PIPEEQUAL, BINEXPR_BITWISE_OR_ASSIGN)
+CREATE_BINEXPR_PARSER(T_CARETEQUAL, BINEXPR_BITWISE_XOR_ASSIGN)
static
expression_t *parse_sub_expression(unsigned precedence)
T_LESSLESS, 16);
register_expression_infix_parser(parse_BINEXPR_SHIFTRIGHT,
T_GREATERGREATER, 16);
- register_expression_infix_parser(parse_BINEXPR_ADD, '+', 15);
- register_expression_infix_parser(parse_BINEXPR_SUB, '-', 15);
- register_expression_infix_parser(parse_BINEXPR_LESS, '<', 14);
- register_expression_infix_parser(parse_BINEXPR_GREATER, '>', 14);
- register_expression_infix_parser(parse_BINEXPR_LESSEQUAL, T_LESSEQUAL, 14);
+ register_expression_infix_parser(parse_BINEXPR_ADD, '+', 15);
+ register_expression_infix_parser(parse_BINEXPR_SUB, '-', 15);
+ register_expression_infix_parser(parse_BINEXPR_LESS, '<', 14);
+ register_expression_infix_parser(parse_BINEXPR_GREATER, '>', 14);
+ register_expression_infix_parser(parse_BINEXPR_LESSEQUAL, T_LESSEQUAL, 14);
register_expression_infix_parser(parse_BINEXPR_GREATEREQUAL,
- T_GREATEREQUAL, 14);
+ T_GREATEREQUAL, 14);
register_expression_infix_parser(parse_BINEXPR_EQUAL, T_EQUALEQUAL, 13);
register_expression_infix_parser(parse_BINEXPR_NOTEQUAL,
- T_EXCLAMATIONMARKEQUAL, 13);
+ T_EXCLAMATIONMARKEQUAL, 13);
register_expression_infix_parser(parse_BINEXPR_BITWISE_AND, '&', 12);
register_expression_infix_parser(parse_BINEXPR_BITWISE_XOR, '^', 11);
register_expression_infix_parser(parse_BINEXPR_BITWISE_OR, '|', 10);
register_expression_infix_parser(parse_BINEXPR_LOGICAL_AND, T_ANDAND, 9);
register_expression_infix_parser(parse_BINEXPR_LOGICAL_OR, T_PIPEPIPE, 8);
register_expression_infix_parser(parse_conditional_expression, '?', 7);
- register_expression_infix_parser(parse_BINEXPR_ASSIGN, T_EQUAL, 2);
+ register_expression_infix_parser(parse_BINEXPR_ASSIGN, '=', 2);
+ register_expression_infix_parser(parse_BINEXPR_ADD_ASSIGN, T_PLUSEQUAL, 2);
+ register_expression_infix_parser(parse_BINEXPR_SUB_ASSIGN, T_MINUSEQUAL, 2);
+ register_expression_infix_parser(parse_BINEXPR_MUL_ASSIGN,
+ T_ASTERISKEQUAL, 2);
+ register_expression_infix_parser(parse_BINEXPR_DIV_ASSIGN, T_SLASHEQUAL, 2);
+ register_expression_infix_parser(parse_BINEXPR_MOD_ASSIGN,
+ T_PERCENTEQUAL, 2);
+ register_expression_infix_parser(parse_BINEXPR_SHIFTLEFT_ASSIGN,
+ T_LESSLESSEQUAL, 2);
+ register_expression_infix_parser(parse_BINEXPR_SHIFTRIGHT_ASSIGN,
+ T_GREATERGREATEREQUAL, 2);
+ register_expression_infix_parser(parse_BINEXPR_BITWISE_AND_ASSIGN,
+ T_ANDEQUAL, 2);
+ register_expression_infix_parser(parse_BINEXPR_BITWISE_OR_ASSIGN,
+ T_PIPEEQUAL, 2);
+ register_expression_infix_parser(parse_BINEXPR_BITWISE_XOR_ASSIGN,
+ T_CARETEQUAL, 2);
+
+ register_expression_infix_parser(parse_BINEXPR_COMMA, ',', 1);
register_expression_infix_parser(parse_array_expression, '[', 30);
register_expression_infix_parser(parse_call_expression, '(', 30);
register_expression_infix_parser(parse_select_expression, '.', 30);
- register_expression_infix_parser(parse_select_expression, T_SELECT, 30);
+ register_expression_infix_parser(parse_select_expression,
+ T_MINUSGREATER, 30);
register_expression_infix_parser(parse_UNEXPR_POSTFIX_INCREMENT,
T_PLUSPLUS, 30);
register_expression_infix_parser(parse_UNEXPR_POSTFIX_DECREMENT,
register_expression_parser(parse_UNEXPR_PREFIX_INCREMENT, T_PLUSPLUS, 25);
register_expression_parser(parse_UNEXPR_PREFIX_DECREMENT, T_MINUSMINUS, 25);
register_expression_parser(parse_sizeof, T_sizeof, 25);
+ register_expression_parser(parse_extension, T___extension__, 25);
}
statement_t *parse_case_statement(void)
{
eat(T_case);
- parse_expression();
+ case_label_statement_t *label = allocate_ast_zero(sizeof(label[0]));
+ label->statement.type = STATEMENT_CASE_LABEL;
+ label->statement.source_position = token.source_position;
+
+ label->expression = parse_expression();
+
expect(':');
- parse_statement();
+ label->statement.next = parse_statement();
- return NULL;
+ return (statement_t*) label;
}
static
statement_t *parse_default_statement(void)
{
eat(T_default);
+
+ case_label_statement_t *label = allocate_ast_zero(sizeof(label[0]));
+ label->statement.type = STATEMENT_CASE_LABEL;
+ label->statement.source_position = token.source_position;
+
expect(':');
- parse_statement();
+ label->statement.next = parse_statement();
- return NULL;
+ return (statement_t*) label;
}
static
eat(T_if);
if_statement_t *statement = allocate_ast_zero(sizeof(statement[0]));
- statement->statement.type = STATEMENT_IF;
+ statement->statement.type = STATEMENT_IF;
+ statement->statement.source_position = token.source_position;
expect('(');
statement->condition = parse_expression();
statement_t *parse_switch(void)
{
eat(T_switch);
+
+ switch_statement_t *statement = allocate_ast_zero(sizeof(statement[0]));
+ statement->statement.type = STATEMENT_SWITCH;
+ statement->statement.source_position = token.source_position;
+
expect('(');
- parse_expression();
+ statement->expression = parse_expression();
expect(')');
- parse_statement();
+ statement->body = parse_statement();
- return NULL;
+ return (statement_t*) statement;
}
static
statement_t *parse_while(void)
{
eat(T_while);
+
+ while_statement_t *statement = allocate_ast_zero(sizeof(statement[0]));
+ statement->statement.type = STATEMENT_WHILE;
+ statement->statement.source_position = token.source_position;
+
expect('(');
- parse_expression();
+ statement->condition = parse_expression();
expect(')');
- parse_statement();
+ statement->body = parse_statement();
- return NULL;
+ return (statement_t*) statement;
}
static
statement_t *parse_do(void)
{
eat(T_do);
- parse_statement();
+
+ do_while_statement_t *statement = allocate_ast_zero(sizeof(statement[0]));
+ statement->statement.type = STATEMENT_DO_WHILE;
+ statement->statement.source_position = token.source_position;
+
+ statement->body = parse_statement();
expect(T_while);
expect('(');
- parse_expression();
+ statement->condition = parse_expression();
expect(')');
+ expect(';');
- return NULL;
+ return (statement_t*) statement;
}
static
statement_t *parse_for(void)
{
eat(T_for);
+
+ for_statement_t *statement = allocate_ast_zero(sizeof(statement[0]));
+ statement->statement.type = STATEMENT_FOR;
+ statement->statement.source_position = token.source_position;
+
expect('(');
+
+ int top = environment_top();
+ context_t *last_context = context;
+ set_context(&statement->context);
+
if(token.type != ';') {
- /* TODO not correct... this could also be a declaration */
- parse_expression();
+ if(is_declaration_specifier(&token, 0)) {
+ parse_declaration();
+ } else {
+ statement->initialisation = parse_expression();
+ expect(';');
+ }
+ } else {
+ expect(';');
}
- expect(';');
+
if(token.type != ';') {
- parse_expression();
+ statement->condition = parse_expression();
}
expect(';');
if(token.type != ')') {
- parse_expression();
+ statement->step = parse_expression();
}
expect(')');
- parse_statement();
+ statement->body = parse_statement();
- return NULL;
+ assert(context == &statement->context);
+ set_context(last_context);
+ environment_pop_to(top);
+
+ return (statement_t*) statement;
}
static
eat(T_break);
expect(';');
- return NULL;
+ statement_t *statement = allocate_ast_zero(sizeof(statement[0]));
+ statement->source_position = token.source_position;
+ statement->type = STATEMENT_BREAK;
+
+ return statement;
}
static
eat(T_return);
return_statement_t *statement = allocate_ast_zero(sizeof(statement[0]));
- statement->statement.type = STATEMENT_RETURN;
+
+ statement->statement.type = STATEMENT_RETURN;
+ statement->statement.source_position = token.source_position;
if(token.type != ';') {
statement->return_value = parse_expression();
}
static
statement_t *parse_declaration_statement(void)
{
- parse_declaration();
- return NULL;
+ declaration_t *before = last_declaration;
+
+ declaration_statement_t *statement
+ = allocate_ast_zero(sizeof(statement[0]));
+ statement->statement.type = STATEMENT_DECLARATION;
+ statement->statement.source_position = token.source_position;
+
+ declaration_specifiers_t specifiers;
+ memset(&specifiers, 0, sizeof(specifiers));
+ parse_declaration_specifiers(&specifiers);
+
+ if(token.type == ';') {
+ eat(';');
+ } else {
+ parse_init_declarators(&specifiers);
+ }
+
+ if(before == NULL) {
+ statement->declarations_begin = context->declarations;
+ } else {
+ statement->declarations_begin = before->next;
+ }
+ statement->declarations_end = last_declaration;
+
+ return (statement_t*) statement;
}
static
statement_t *parse_expression_statement(void)
{
- parse_expression();
- return NULL;
+ expression_statement_t *statement = allocate_ast_zero(sizeof(statement[0]));
+ statement->statement.type = STATEMENT_EXPRESSION;
+ statement->statement.source_position = token.source_position;
+
+ statement->expression = parse_expression();
+
+ expect(';');
+
+ return (statement_t*) statement;
}
static
statement = parse_expression_statement();
break;
+ case T___extension__:
+ /* this can be a prefix to a declaration or an expression statement */
+ /* we simply eat it now and parse the rest with tail recursion */
+ do {
+ next_token();
+ } while(token.type == T___extension__);
+ statement = parse_statement();
+ break;
+
DECLARATION_START
statement = parse_declaration_statement();
break;
break;
}
+ assert(statement == NULL || statement->source_position.input_name != NULL);
+
return statement;
}
compound_statement_t *compound_statement
= allocate_ast_zero(sizeof(compound_statement[0]));
- compound_statement->statement.type = STATEMENT_COMPOUND;
+ compound_statement->statement.type = STATEMENT_COMPOUND;
+ compound_statement->statement.source_position = token.source_position;
int top = environment_top();
context_t *last_context = context;
while(token.type != '}' && token.type != T_EOF) {
statement_t *statement = parse_statement();
+ if(statement == NULL)
+ continue;
if(last_statement != NULL) {
last_statement->next = statement;
} else {
compound_statement->statements = statement;
}
+
+ while(statement->next != NULL)
+ statement = statement->next;
+
last_statement = statement;
}
S(__extension__)
S(__attribute__)
S(__builtin_va_list)
+S(__PRETTY_FUNCTION__)
+S(__FUNCTION__)
+S(__alignof__)
+S(__real__)
+S(__imag__)
#undef S
T(const, "__const",)
T(inline, "inline",)
T(__inline, "__inline", = T_inline)
-T(SELECT, "->",)
+T(MINUSGREATER, "->",)
T(PLUSPLUS, "++",)
T(MINUSMINUS, "--",)
T(LESSLESS, "<<",)
#include <config.h>
+#include <stdio.h>
+#include <assert.h>
#include "type_t.h"
#include "adt/error.h"
-static struct obstack _type_obst;
-struct obstack *type_obst = &_type_obst;
-static FILE *out;
+static struct obstack _type_obst;
+struct obstack *type_obst = &_type_obst;
+static FILE *out;
static void intern_print_type_pre(const type_t *type);
static void intern_print_type_post(const type_t *type);
fputs("volatile ", out);
}
if(qualifiers & TYPE_QUALIFIER_RESTRICT) {
- fputs("restrict ", out);
+ fputs("__restrict ", out);
}
if(qualifiers & TYPE_QUALIFIER_INLINE) {
fputs("inline ", out);
}
static
-void print_method_type_post(const method_type_t *type)
+void print_method_type_post(const method_type_t *type, const context_t *context)
{
/* TODO: don't emit braces if we're the toplevel type... */
intern_print_type_post(type->result_type);
fputc('(', out);
- method_parameter_t *parameter = type->parameters;
int first = 1;
- for( ; parameter != NULL; parameter = parameter->next) {
- if(first) {
- first = 0;
- } else {
- fputs(", ", out);
+ if(context == NULL) {
+ method_parameter_t *parameter = type->parameters;
+ for( ; parameter != NULL; parameter = parameter->next) {
+ if(first) {
+ first = 0;
+ } else {
+ fputs(", ", out);
+ }
+ print_type(parameter->type);
+ }
+ } else {
+ declaration_t *parameter = context->declarations;
+ for( ; parameter != NULL; parameter = parameter->next) {
+ if(first) {
+ first = 0;
+ } else {
+ fputs(", ", out);
+ }
+ print_type_ext(parameter->type, parameter->symbol,
+ ¶meter->context);
}
- print_type(parameter->type, NULL);
}
if(type->variadic) {
if(first) {
} else {
fprintf(out, "enum {\n");
- enum_entry_t *entry = type->entries;
- for( ; entry != NULL; entry = entry->next) {
+ declaration_t *entry = type->entries_begin;
+ for( ; entry != type->entries_end->next; entry = entry->next) {
fprintf(out, "\t%s", entry->symbol->string);
- if(entry->value != NULL) {
+ if(entry->initializer != NULL) {
fprintf(out, " = ");
- print_expression(entry->value);
+ print_expression(entry->initializer);
}
fprintf(out, ",\n");
}
{
switch(type->type) {
case TYPE_METHOD:
- print_method_type_post((const method_type_t*) type);
+ print_method_type_post((const method_type_t*) type, NULL);
return;
case TYPE_POINTER:
print_pointer_type_post((const pointer_type_t*) type);
}
}
-void print_type(const type_t *type, const symbol_t *symbol)
+void print_type(const type_t *type)
+{
+ print_type_ext(type, NULL, NULL);
+}
+
+void print_type_ext(const type_t *type, const symbol_t *symbol,
+ const context_t *context)
{
if(type == NULL) {
fputs("nil type", out);
fputc(' ', out);
fputs(symbol->string, out);
}
- intern_print_type_post(type);
+ if(type->type == TYPE_METHOD) {
+ print_method_type_post((const method_type_t*) type, context);
+ } else {
+ intern_print_type_post(type);
+ }
}
int type_valid(const type_t *type)
{
FILE *old_out = out;
out = stderr;
- print_type(type, NULL);
+ print_type(type);
puts("\n");
fflush(stderr);
out = old_out;
typedef struct method_parameter_t method_parameter_t;
typedef struct method_type_t method_type_t;
typedef struct compound_type_t compound_type_t;
-typedef struct enum_entry_t enum_entry_t;
typedef struct enum_type_t enum_type_t;
typedef struct builtin_type_t builtin_type_t;
void init_types(void);
void exit_types(void);
+void print_type(const type_t *type);
+
/**
* prints a human readable form of @p type. prints an abstract typename
* if symbol is NULL
*/
-void print_type(const type_t *type, const symbol_t *symbol);
+void print_type_ext(const type_t *type, const symbol_t *symbol,
+ const context_t *context);
/**
* set output stream for the type printer
/* TODO: ^= is a bad way of combining hashes since most addresses are very
* similar */
-static
-unsigned hash_ptr(const void *ptr)
+static unsigned hash_ptr(const void *ptr)
{
unsigned ptr_int = ((char*) ptr - (char*) NULL);
return ptr_int >> 3;
}
-static
-unsigned hash_atomic_type(const atomic_type_t *type)
+static unsigned hash_atomic_type(const atomic_type_t *type)
{
unsigned some_prime = 27644437;
return type->atype * some_prime;
}
-static
-unsigned hash_pointer_type(const pointer_type_t *type)
+static unsigned hash_pointer_type(const pointer_type_t *type)
{
return hash_ptr(type->points_to);
}
-static
-unsigned hash_compound_type(const compound_type_t *type)
+static unsigned hash_compound_type(const compound_type_t *type)
{
unsigned result = hash_ptr(type->symbol);
return result;
}
-static
-unsigned hash_type(const type_t *type);
+static unsigned hash_type(const type_t *type);
-static
-unsigned hash_method_type(const method_type_t *type)
+static unsigned hash_method_type(const method_type_t *type)
{
unsigned result = hash_ptr(type->result_type);
return result;
}
-static
-unsigned hash_enum_type(const enum_type_t *type)
+static unsigned hash_enum_type(const enum_type_t *type)
{
unsigned result = hash_ptr(type->symbol);
- /* TODO */
-
return result;
}
-static
-unsigned hash_type(const type_t *type)
+static unsigned hash_type(const type_t *type)
{
unsigned hash;
return hash;
}
-static
-int atomic_types_equal(const atomic_type_t *type1, const atomic_type_t *type2)
+static int atomic_types_equal(const atomic_type_t *type1,
+ const atomic_type_t *type2)
{
return type1->atype == type2->atype;
}
-static
-int compound_types_equal(const compound_type_t *type1,
- const compound_type_t *type2)
+static int compound_types_equal(const compound_type_t *type1,
+ const compound_type_t *type2)
{
if(type1->type.type != type2->type.type)
return 0;
if(type1->symbol != type2->symbol)
return 0;
+ /* anonymous types? */
if(type1->symbol == NULL) {
/* previous tests should already have checked for this */
assert(type1 != type2);
/* anonymous types are only equal if they are the very same type */
return 0;
- } else {
- /* non-anonymous types are equal if they have the same symbol */
- /* TODO: is this correct */
- return 1;
}
-#if 0
- declaration_t *entry1 = type1->context.declarations;
- declaration_t *entry2 = type2->context.declarations;
+ /* non-anonymous types with same symbol are equal */
+ return 1;
+}
- while(entry1 != NULL && entry2 != NULL) {
- if(entry1->type != entry2->type)
- return 0;
- if(entry1->symbol != entry2->symbol)
- return 0;
- entry1 = entry1->next;
- entry2 = entry2->next;
- }
- if(entry1 != NULL || entry2 != NULL)
+static int enum_types_equal(const enum_type_t *type1, const enum_type_t *type2)
+{
+ if(type1->symbol != type2->symbol)
return 0;
-#endif
+ /* anonymous types? */
+ if(type1->symbol == NULL) {
+ /* previous tests should already have checked for this */
+ assert(type1 != type2);
+ /* 2 anonymous enums are never equal */
+ return 0;
+ }
+
+ /* non-anonymous types with same symbol are equal */
return 1;
}
-static
-int method_types_equal(const method_type_t *type1, const method_type_t *type2)
+static int method_types_equal(const method_type_t *type1,
+ const method_type_t *type2)
{
if(type1->result_type != type2->result_type)
return 0;
return 1;
}
-static
-int pointer_types_equal(const pointer_type_t *type1,
- const pointer_type_t *type2)
+static int pointer_types_equal(const pointer_type_t *type1,
+ const pointer_type_t *type2)
{
return type1->points_to == type2->points_to;
}
-static
-int enum_types_equal(const enum_type_t *type1, const enum_type_t *type2)
-{
- if(type1->symbol != NULL && type1->symbol == type2->symbol)
- return 1;
-
- enum_entry_t *entry1 = type1->entries;
- enum_entry_t *entry2 = type2->entries;
- while(entry1 != NULL && entry2 != NULL) {
- if(entry1->symbol != entry2->symbol)
- return 0;
- /* TODO: compare expressions */
- entry1 = entry1->next;
- entry2 = entry2->next;
- }
- if(entry1 != NULL || entry2 != NULL)
- return 0;
-
- return 1;
-}
-
-static
-int builtin_types_equal(const builtin_type_t *type1,
- const builtin_type_t *type2)
+static int builtin_types_equal(const builtin_type_t *type1,
+ const builtin_type_t *type2)
{
return type1->symbol == type2->symbol;
}
-static
-int types_equal(const type_t *type1, const type_t *type2)
+static int types_equal(const type_t *type1, const type_t *type2)
{
if(type1 == type2)
return 1;
symbol_t *symbol;
};
-struct enum_entry_t {
- symbol_t *symbol;
- expression_t *value;
- enum_entry_t *next;
-};
-
struct enum_type_t {
type_t type;
symbol_t *symbol;
- enum_entry_t *entries;
source_position_t source_position;
enum_type_t *next;
+ declaration_t *entries_begin;
+ declaration_t *entries_end;
+ int defined;
};
struct pointer_type_t {
/* first: search for a matching typedef in the global type... */
declaration_t *declaration = global_context->declarations;
while(declaration != NULL) {
- if(! (declaration->storage_class & STORAGE_CLASS_TYPEDEF)) {
+ if(! (declaration->storage_class == STORAGE_CLASS_TYPEDEF)) {
declaration = declaration->next;
continue;
}
{
fprintf(out, "enum %s:\n", symbol->string);
- const enum_entry_t *entry = type->entries;
- for ( ; entry != NULL; entry = entry->next) {
+ declaration_t *entry = type->entries_begin;
+ for ( ; entry != type->entries_end->next; entry = entry->next) {
fprintf(out, "\t%s", entry->symbol->string);
- if(entry->value != NULL) {
+ if(entry->initializer != NULL) {
fprintf(out, " <- ");
- write_expression(entry->value);
+ write_expression(entry->initializer);
}
fputc('\n', out);
}
declaration_t *declaration = unit->context.declarations;
for( ; declaration != NULL; declaration = declaration->next) {
//fprintf(out, "// Decl: %s\n", declaration->symbol->string);
- if(! (declaration->storage_class & STORAGE_CLASS_TYPEDEF)) {
+ if(! (declaration->storage_class == STORAGE_CLASS_TYPEDEF)) {
continue;
}
type_t *type = declaration->type;
/* write global variables */
declaration = unit->context.declarations;
for( ; declaration != NULL; declaration = declaration->next) {
- if(declaration->storage_class & STORAGE_CLASS_TYPEDEF)
+ if(declaration->storage_class == STORAGE_CLASS_TYPEDEF
+ || declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY)
continue;
type_t *type = declaration->type;
/* write functions */
declaration = unit->context.declarations;
for( ; declaration != NULL; declaration = declaration->next) {
- if(declaration->storage_class & STORAGE_CLASS_TYPEDEF)
+ if(declaration->storage_class == STORAGE_CLASS_TYPEDEF
+ || declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY)
continue;
type_t *type = declaration->type;