Refactoring:
-- create an empty_statement_t and use that instead of a NULL pointer in places
- like if, loop bodys, statements after labels
- eliminate target_architecture.h and replace with stuff in lang_features.h
- redo storage classes: so we can separate real from declared storage class
switch(expression->kind) {
case EXPR_UNKNOWN:
case EXPR_INVALID:
- fprintf(out, "*invalid expression*");
+ fprintf(out, "$invalid expression$");
break;
case EXPR_CHARACTER_CONSTANT:
print_character_constant(&expression->conste);
{
fprintf(stderr, "(%p)", (void*) statement->label);
fprintf(out, "%s:\n", statement->label->symbol->string);
- if(statement->statement != NULL) {
- print_statement(statement->statement);
- }
+ print_statement(statement->statement);
}
/**
*/
static void print_if_statement(const if_statement_t *statement)
{
- fputs("if(", out);
+ fputs("if (", out);
print_expression(statement->condition);
fputs(") ", out);
if(statement->true_statement != NULL) {
*/
static void print_switch_statement(const switch_statement_t *statement)
{
- fputs("switch(", out);
+ fputs("switch (", out);
print_expression(statement->expression);
fputs(") ", out);
print_statement(statement->body);
*/
static void print_while_statement(const while_statement_t *statement)
{
- fputs("while(", out);
+ fputs("while (", out);
print_expression(statement->condition);
fputs(") ", out);
print_statement(statement->body);
fputs("do ", out);
print_statement(statement->body);
print_indent();
- fputs("while(", out);
+ fputs("while (", out);
print_expression(statement->condition);
fputs(");\n", out);
}
*/
static void print_for_statement(const for_statement_t *statement)
{
- fputs("for(", out);
+ fputs("for (", out);
if(statement->scope.declarations != NULL) {
assert(statement->initialisation == NULL);
print_declaration(statement->scope.declarations);
void print_statement(const statement_t *statement)
{
switch(statement->kind) {
+ case STATEMENT_EMPTY:
+ fputs(";\n", out);
+ break;
case STATEMENT_COMPOUND:
print_compound_statement(&statement->compound);
break;
print_asm_statement(&statement->asms);
break;
case STATEMENT_INVALID:
- fprintf(out, "*invalid statement*");
+ fprintf(out, "$invalid statement$");
break;
}
}
typedef struct declaration_t declaration_t;
typedef struct statement_base_t statement_base_t;
+typedef struct invalid_statement_t invalid_statement_t;
+typedef struct empty_statement_t empty_statement_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;
switch(statement->kind) {
case STATEMENT_INVALID:
panic("invalid statement found");
+ return;
+ case STATEMENT_EMPTY:
+ /* nothing */
+ return;
case STATEMENT_COMPOUND:
compound_statement_to_firm(&statement->compound);
return;
int count = 0;
for (; stmt != NULL; stmt = stmt->base.next) {
switch (stmt->kind) {
+ case STATEMENT_EMPTY:
+ break;
+
case STATEMENT_DECLARATION: {
const declaration_statement_t *const decl_stmt = &stmt->declaration;
count += count_local_declarations(decl_stmt->declarations_begin,
typedef enum {
STATEMENT_INVALID,
+ STATEMENT_EMPTY,
STATEMENT_COMPOUND,
STATEMENT_RETURN,
STATEMENT_DECLARATION,
source_position_t source_position;
};
+struct invalid_statement_t {
+ statement_base_t base;
+};
+
+struct empty_statement_t {
+ statement_base_t base;
+};
+
struct return_statement_t {
statement_base_t base;
expression_t *value;
return obstack_alloc(&ast_obstack, size);
}
+static inline
+bool is_invalid_expression(expression_t *expression)
+{
+ return expression->base.kind == EXPR_INVALID;
+}
+
+static inline
+bool is_invalid_statement(statement_t *statement)
+{
+ return statement->base.kind == STATEMENT_INVALID;
+}
+
+
#define allocate_ast(size) _allocate_ast(size)
#endif
const char *dumpfunction = NULL;
compile_mode_t mode = CompileAssembleLink;
int opt_level = 1;
+ int result = EXIT_SUCCESS;
obstack_init(&cppflags_obst);
obstack_init(&ldflags_obst);
FILE *preprocessed_in = preprocess(in, input);
translation_unit_t *const unit = do_parsing(preprocessed_in, input);
- int result = pclose(preprocessed_in);
- if(result != 0) {
- return result;
+ int res = pclose(preprocessed_in);
+ if(res != 0) {
+ return res;
}
- if(unit == NULL) {
+
+ if(error_count > 0) {
/* parsing failed because of errors */
fprintf(stderr, "%u error(s), %u warning(s)\n", error_count, warning_count);
- return EXIT_FAILURE;
- }
- if (warning_count > 0) {
+ result = EXIT_FAILURE;
+ } else if(warning_count > 0) {
fprintf(stderr, "%u warning(s)\n", warning_count);
}
if(mode == BenchmarkParser) {
- return 0;
+ return result;
}
+ /* prints the AST even if errors occurred */
if(mode == PrintAst) {
type_set_output(out);
ast_set_output(out);
print_ast(unit);
- return 0;
+ return result;
}
+
+ /* cannot handle other modes with errors */
+ if(result != EXIT_SUCCESS)
+ return result;
+
if(mode == PrintFluffy) {
type_set_output(out);
ast_set_output(out);
static size_t get_statement_struct_size(statement_kind_t kind)
{
static const size_t sizes[] = {
+ [STATEMENT_INVALID] = sizeof(invalid_statement_t),
+ [STATEMENT_EMPTY] = sizeof(empty_statement_t),
[STATEMENT_COMPOUND] = sizeof(compound_statement_t),
[STATEMENT_RETURN] = sizeof(return_statement_t),
[STATEMENT_DECLARATION] = sizeof(declaration_statement_t),
return res;
}
+/**
+ * Creates a new invalid statement.
+ */
+static statement_t *create_invalid_statement(void)
+{
+ statement_t *statement = allocate_statement_zero(STATEMENT_INVALID);
+ statement->base.source_position = token.source_position;
+ return statement;
+}
+
+/**
+ * Allocate a new empty statement.
+ */
+static statement_t *create_empty_statement(void)
+{
+ statement_t *statement = allocate_statement_zero(STATEMENT_EMPTY);
+ statement->base.source_position = token.source_position;
+ return statement;
+}
+
/**
* Returns the size of an expression node.
*
next_token();
}
+/**
+ * eat all token until a ';' is reached
+ * or a stop token is found.
+ */
static void eat_statement(void) {
eat_until_matching_token(';');
if(token.type == ';')
expect(';');
return statement;
end_error:
- return NULL;
+ return create_invalid_statement();
}
/**
return statement;
end_error:
- return NULL;
+ return create_invalid_statement();
}
/**
return statement;
end_error:
- return NULL;
+ return create_invalid_statement();
}
/**
if(token.type == '}') {
/* TODO only warn? */
- errorf(HERE, "label at end of compound statement");
+ if(false) {
+ warningf(HERE, "label at end of compound statement");
+ statement->label.statement = create_empty_statement();
+ } else {
+ errorf(HERE, "label at end of compound statement");
+ statement->label.statement = create_invalid_statement();
+ }
return statement;
} else {
if (token.type == ';') {
/* eat an empty statement here, to avoid the warning about an empty
* after a label. label:; is commonly used to have a label before
* a }. */
+ statement->label.statement = create_empty_statement();
next_token();
} else {
statement->label.statement = parse_statement();
return statement;
end_error:
- return NULL;
+ return create_invalid_statement();
}
/**
return statement;
end_error:
- return NULL;
+ return create_invalid_statement();
}
static statement_t *parse_loop_body(statement_t *const loop)
return statement;
end_error:
- return NULL;
+ return create_invalid_statement();
}
/**
return statement;
end_error:
- return NULL;
+ return create_invalid_statement();
}
/**
set_scope(last_scope);
environment_pop_to(top);
- return NULL;
+ return create_invalid_statement();
}
/**
return statement;
end_error:
- return NULL;
+ return create_invalid_statement();
}
/**
return statement;
end_error:
- return NULL;
+ return create_invalid_statement();
}
/**
return statement;
end_error:
- return NULL;
+ return create_invalid_statement();
}
/**
return statement;
end_error:
- return NULL;
+ return create_invalid_statement();
}
/**
return statement;
end_error:
- return NULL;
+ return create_invalid_statement();
}
/**
break;
case ';':
- if (warning.empty_statement) {
+ if(warning.empty_statement) {
warningf(HERE, "statement is empty");
}
+ statement = create_empty_statement();
next_token();
- statement = NULL;
break;
case T_IDENTIFIER:
}
rem_anchor_token(';');
- assert(statement == NULL
- || statement->base.source_position.input_name != NULL);
+ assert(statement != NULL
+ && statement->base.source_position.input_name != NULL);
return statement;
}
while(token.type != '}' && token.type != T_EOF) {
statement_t *sub_statement = parse_statement();
- if(sub_statement == NULL) {
+ if(is_invalid_statement(sub_statement)) {
/* an error occurred. if we are at an anchor, return */
if(at_anchor())
goto end_error;
DEL_ARR_F(environment_stack);
DEL_ARR_F(label_stack);
- if(error_count > 0)
- return NULL;
-
return unit;
}
--- /dev/null
+int main() {
+ ;
+ return 0;
+}