return res;
}
+static declaration_t *allocate_declaration_zero(void)
+{
+ return allocate_ast_zero(sizeof(*allocate_declaration_zero()));
+}
+
/**
* Returns the size of a statement node.
*
} \
next_token();
-#define expect_fail(expected) \
- if(UNLIKELY(token.type != (expected))) { \
- parse_error_expected(NULL, (expected), 0); \
- eat_statement(); \
- goto fail; \
- } \
- next_token();
-
#define expect_block(expected) \
if(UNLIKELY(token.type != (expected))) { \
parse_error_expected(NULL, (expected), 0); \
incompatible_assign_types:
/* TODO: improve error message */
- errorf(HERE, "incompatible types in %s", context);
- errorf(HERE, "'%T' <- '%T'", orig_type_left, orig_type_right);
+ errorf(HERE, "incompatible types in %s: '%T' <- '%T'",
+ context, orig_type_left, orig_type_right);
}
static expression_t *parse_constant_expression(void)
{
symbol_t *const symbol = symbol_table_insert(name);
- declaration_t *declaration = allocate_ast_zero(sizeof(declaration[0]));
+ declaration_t *const declaration = allocate_declaration_zero();
declaration->namespc = NAMESPACE_NORMAL;
declaration->storage_class = STORAGE_CLASS_TYPEDEF;
declaration->type = type;
return typedef_type;
}
-static const char *parse_string_literals(void)
+static string_t parse_string_literals(void)
{
assert(token.type == T_STRING_LITERAL);
- const char *result = token.v.string;
+ string_t result = token.v.string;
next_token();
- while(token.type == T_STRING_LITERAL) {
- result = concat_strings(result, token.v.string);
+ while (token.type == T_STRING_LITERAL) {
+ result = concat_strings(&result, &token.v.string);
next_token();
}
#endif
static initializer_t *initializer_from_string(array_type_t *type,
- const char *string)
+ const string_t *const string)
{
/* TODO: check len vs. size of array type */
(void) type;
initializer_t *initializer = allocate_initializer_zero(INITIALIZER_STRING);
- initializer->string.string = string;
+ initializer->string.string = *string;
return initializer;
}
case EXPR_STRING_LITERAL:
if (element_type->atomic.akind == ATOMIC_TYPE_CHAR) {
return initializer_from_string(array_type,
- expression->string.value);
+ &expression->string.value);
}
case EXPR_WIDE_STRING_LITERAL: {
if(token.type != '{') {
expression_t *expression = parse_assignment_expression();
+ if (expression->base.datatype == NULL) {
+ /* something bad happens, don't produce further errors */
+ return NULL;
+ }
initializer_t *initializer = initializer_from_expression(type, expression);
if(initializer == NULL) {
- errorf(HERE, "initializer expression '%E', type '%T' is incompatible with type '%T'", expression, expression->base.datatype, type);
+ errorf(HERE,
+ "initializer expression '%E' of type '%T' is incompatible with type '%T'",
+ expression, expression->base.datatype, type);
}
return initializer;
}
}
if(declaration == NULL) {
- declaration = allocate_ast_zero(sizeof(declaration[0]));
-
- if(is_struct) {
- declaration->namespc = NAMESPACE_STRUCT;
- } else {
- declaration->namespc = NAMESPACE_UNION;
- }
+ declaration = allocate_declaration_zero();
+ declaration->namespc =
+ (is_struct ? NAMESPACE_STRUCT : NAMESPACE_UNION);
declaration->source_position = token.source_position;
declaration->symbol = symbol;
declaration->parent_context = context;
return declaration;
}
-static void parse_enum_entries(enum_type_t *const enum_type)
+static void parse_enum_entries(type_t *const enum_type)
{
eat('{');
}
do {
- declaration_t *entry = allocate_ast_zero(sizeof(entry[0]));
-
if(token.type != T_IDENTIFIER) {
parse_error_expected("while parsing enum entry", T_IDENTIFIER, 0);
eat_block();
return;
}
+
+ declaration_t *const entry = allocate_declaration_zero();
entry->storage_class = STORAGE_CLASS_ENUM_ENTRY;
- entry->type = (type_t*) enum_type;
+ entry->type = enum_type;
entry->symbol = token.v.symbol;
entry->source_position = token.source_position;
next_token();
}
if(declaration == NULL) {
- declaration = allocate_ast_zero(sizeof(declaration[0]));
-
- declaration->namespc = NAMESPACE_ENUM;
+ declaration = allocate_declaration_zero();
+ declaration->namespc = NAMESPACE_ENUM;
declaration->source_position = token.source_position;
declaration->symbol = symbol;
declaration->parent_context = context;
append_declaration(declaration);
declaration->init.is_defined = 1;
- parse_enum_entries(&type->enumt);
+ parse_enum_entries(type);
parse_attributes();
}
declaration_t *declarations = NULL;
declaration_t *last_declaration = NULL;
do {
- declaration_t *declaration = allocate_ast_zero(sizeof(declaration[0]));
-
+ declaration_t *const declaration = allocate_declaration_zero();
declaration->source_position = token.source_position;
declaration->symbol = token.v.symbol;
next_token();
const declaration_specifiers_t *specifiers, bool may_be_abstract)
{
type_t *type = specifiers->type;
- declaration_t *declaration = allocate_ast_zero(sizeof(declaration[0]));
+ declaration_t *const declaration = allocate_declaration_zero();
declaration->storage_class = specifiers->storage_class;
declaration->modifiers = specifiers->decl_modifiers;
declaration->is_inline = specifiers->is_inline;
case INITIALIZER_STRING: {
initializer_string_t *const string = &initializer->string;
- cnst->conste.v.int_value = strlen(string->string) + 1;
+ cnst->conste.v.int_value = string->string.size;
break;
}
{
eat(';');
- declaration_t *declaration = allocate_ast_zero(sizeof(declaration[0]));
-
+ declaration_t *const declaration = allocate_declaration_zero();
declaration->type = specifiers->type;
declaration->storage_class = specifiers->storage_class;
declaration->source_position = specifiers->source_position;
type_t *type = make_bitfield_type(base_type, size);
- declaration = allocate_ast_zero(sizeof(declaration[0]));
-
+ declaration = allocate_declaration_zero();
declaration->namespc = NAMESPACE_NORMAL;
declaration->storage_class = STORAGE_CLASS_NONE;
declaration->source_position = token.source_position;
declaration->modifiers = specifiers->decl_modifiers;
declaration->type = type;
-
- record_declaration(declaration);
} else {
declaration = parse_declarator(specifiers,/*may_be_abstract=*/true);
return expression;
}
+/**
+ * Prints an error message if an expression was expected but not read
+ */
static expression_t *expected_expression_error(void)
{
- errorf(HERE, "expected expression, got token '%K'", &token);
-
+ /* skip the error message if the error token was read */
+ if (token.type != T_ERROR) {
+ errorf(HERE, "expected expression, got token '%K'", &token);
+ }
next_token();
return create_invalid_expression();
free_type(ntype);
}
- declaration_t *declaration = allocate_ast_zero(sizeof(declaration[0]));
-
+ declaration_t *const declaration = allocate_declaration_zero();
declaration->storage_class = STORAGE_CLASS_EXTERN;
declaration->type = type;
declaration->symbol = symbol;
expression->expression.kind = EXPR_FUNCTION;
expression->expression.datatype = type_string;
- expression->value = current_function->symbol->string;
return (expression_t*) expression;
}
expression->expression.kind = EXPR_PRETTY_FUNCTION;
expression->expression.datatype = type_string;
- expression->value = current_function->symbol->string;
return (expression_t*) expression;
}
}
/* otherwise we need to create a new one */
- declaration_t *declaration = allocate_ast_zero(sizeof(declaration[0]));
+ declaration_t *const declaration = allocate_declaration_zero();
declaration->namespc = NAMESPACE_LABEL;
declaration->symbol = symbol;
return (statement_t*) statement;
}
+static statement_t *parse_loop_body(statement_t *const loop)
+{
+ statement_t *const rem = current_loop;
+ current_loop = loop;
+ statement_t *const body = parse_statement();
+ current_loop = rem;
+ return body;
+}
+
/**
* Parse a while statement.
*/
statement->statement.kind = STATEMENT_WHILE;
statement->statement.source_position = token.source_position;
- statement_t *rem = current_loop;
- expect_fail('(');
+ expect('(');
statement->condition = parse_expression();
- expect_fail(')');
+ expect(')');
- statement->body = parse_statement();
- current_loop = rem;
+ statement->body = parse_loop_body((statement_t*)statement);
return (statement_t*) statement;
-fail:
- current_loop = rem;
- return NULL;
}
/**
statement->statement.kind = STATEMENT_DO_WHILE;
statement->statement.source_position = token.source_position;
- statement_t *rem = current_loop;
- statement->body = parse_statement();
- expect_fail(T_while);
- expect_fail('(');
+ statement->body = parse_loop_body((statement_t*)statement);
+ expect(T_while);
+ expect('(');
statement->condition = parse_expression();
- expect_fail(')');
- current_loop = rem;
+ expect(')');
expect(';');
return (statement_t*) statement;
-fail:
- current_loop = rem;
- return NULL;
}
/**
expect('(');
- statement_t *rem = current_loop;
int top = environment_top();
context_t *last_context = context;
set_context(&statement->context);
parse_declaration(record_declaration);
} else {
statement->initialisation = parse_expression();
- expect_fail(';');
+ expect(';');
}
} else {
- expect_fail(';');
+ expect(';');
}
if(token.type != ';') {
statement->condition = parse_expression();
}
- expect_fail(';');
+ expect(';');
if(token.type != ')') {
statement->step = parse_expression();
}
- expect_fail(')');
- statement->body = parse_statement();
+ expect(')');
+ statement->body = parse_loop_body((statement_t*)statement);
assert(context == &statement->context);
set_context(last_context);
environment_pop_to(top);
- current_loop = rem;
return (statement_t*) statement;
-fail:
- current_loop = rem;
- return NULL;
}
/**
*/
static statement_t *parse_continue(void)
{
- eat(T_continue);
- expect(';');
-
- statement_t *statement = allocate_ast_zero(sizeof(statement[0]));
- statement->kind = STATEMENT_CONTINUE;
- statement->base.source_position = token.source_position;
-
+ statement_t *statement;
if (current_loop == NULL) {
errorf(HERE, "continue statement not within loop");
- return NULL;
+ statement = NULL;
+ } else {
+ statement = allocate_statement_zero(STATEMENT_CONTINUE);
+
+ statement->base.source_position = token.source_position;
}
+ eat(T_continue);
+ expect(';');
+
return statement;
}
*/
static statement_t *parse_break(void)
{
- eat(T_break);
- expect(';');
-
- statement_t *statement = allocate_ast_zero(sizeof(statement[0]));
- statement->kind = STATEMENT_BREAK;
- statement->base.source_position = token.source_position;
-
+ statement_t *statement;
if (current_switch == NULL && current_loop == NULL) {
errorf(HERE, "break statement not within loop or switch");
- return NULL;
+ statement = NULL;
+ } else {
+ statement = allocate_statement_zero(STATEMENT_BREAK);
+
+ statement->base.source_position = token.source_position;
}
+
+ eat(T_break);
+ expect(';');
+
return statement;
}