static void print_statement(const statement_t *statement);
+static void print_indent(void)
+{
+ for(int i = 0; i < indent; ++i)
+ fprintf(out, "\t");
+}
+
static
void print_const(const const_t *cnst)
{
fprintf(out, ")");
}
+static void print_reference_expression(const reference_expression_t *ref)
+{
+ fprintf(out, "%s", ref->declaration->symbol->string);
+}
+
void print_expression(const expression_t *expression)
{
switch(expression->type) {
print_binary_expression((const binary_expression_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:
statement_t *statement = block->statements;
while(statement != NULL) {
+ print_indent();
print_statement(statement);
statement = statement->next;
}
indent--;
+ print_indent();
fputs("}\n", out);
}
fprintf(out, "return ");
if(statement->return_value != NULL)
print_expression(statement->return_value);
+ fputs(";\n", out);
}
static
} else {
fprintf(out, "?%s", statement->label_symbol->string);
}
+ fputs(";\n", out);
}
static
void print_label_statement(const label_statement_t *statement)
{
- fprintf(out, ":%s", statement->symbol->string);
+ fprintf(out, "%s:\n", statement->symbol->string);
}
static
void print_if_statement(const if_statement_t *statement)
{
- fprintf(out, "if ");
+ fprintf(out, "if(");
print_expression(statement->condition);
- fprintf(out, ":\n");
+ fprintf(out, ") ");
if(statement->true_statement != NULL) {
print_statement(statement->true_statement);
}
if(statement->false_statement != NULL) {
- fprintf(out, "else:\n");
+ print_indent();
+ fprintf(out, "else ");
print_statement(statement->false_statement);
}
}
void print_statement(const statement_t *statement)
{
- for(int i = 0; i < indent; ++i)
- fprintf(out, "\t");
-
switch(statement->type) {
case STATEMENT_COMPOUND:
print_compound_statement((const compound_statement_t*) statement);
break;
}
- fprintf(out, "\n");
}
#if 0
print_storage_class(declaration->storage_class);
print_type(declaration->type, declaration->symbol);
if(declaration->statement != NULL) {
- fprintf(out, "\n");
+ fputs("\n", out);
print_statement(declaration->statement);
} else {
fprintf(out, ";\n");
}
static inline
-const token_t *la(int num)
+const token_t *look_ahead(int num)
{
assert(num > 0 && num <= MAX_LOOKAHEAD);
int pos = (lookahead_bufpos+num-1) % MAX_LOOKAHEAD;
fprintf(stderr, "\n");
}
-static
-void eat_until(int token_type)
+static void eat_block(void)
{
- while(token.type != token_type) {
+ if(token.type == '{')
+ next_token();
+
+ while(token.type != '}') {
if(token.type == T_EOF)
return;
+ if(token.type == '{') {
+ eat_block();
+ continue;
+ }
next_token();
}
- next_token();
+ eat('}');
+}
+
+static void eat_statement(void)
+{
+ while(token.type != ';') {
+ if(token.type == T_EOF)
+ return;
+ if(token.type == '}')
+ return;
+ if(token.type == '{') {
+ eat_block();
+ continue;
+ }
+ next_token();
+ }
+ eat(';');
+}
+
+static void eat_brace(void)
+{
+ if(token.type == '(')
+ next_token();
+
+ while(token.type != ')') {
+ if(token.type == T_EOF)
+ return;
+ if(token.type == '{') {
+ eat_block();
+ continue;
+ }
+ next_token();
+ }
+ eat(')');
}
#define expect(expected) \
if(UNLIKELY(token.type != (expected))) { \
parse_error_expected(NULL, (expected), 0); \
- eat_until(';'); \
+ eat_statement(); \
return NULL; \
} \
next_token();
#define expect_void(expected) \
if(UNLIKELY(token.type != (expected))) { \
parse_error_expected(NULL, (expected), 0); \
- eat_until(';'); \
+ eat_statement(); \
return; \
} \
next_token();
if(token.type != T_IDENTIFIER) {
parse_error_expected("problem while parsing enum entry",
T_IDENTIFIER, 0);
- eat_until('}');
+ eat_block();
return result;
}
entry->symbol = token.v.symbol;
if(token.type != T_STRING_LITERAL) {
parse_error_expected("while parsing assembler attribute",
T_STRING_LITERAL);
- eat_until(')');
+ eat_brace();
break;
} else {
parse_string_literals();
type->unspecified_parameters = 1;
return NULL;
}
- if(token.type == T_void && la(1)->type == ')') {
+ if(token.type == T_void && look_ahead(1)->type == ')') {
next_token();
return NULL;
}
= allocate_type_zero(sizeof(method_type[0]));
method_type->type.type = TYPE_METHOD;
- declaration->context.declarations = parse_parameters(method_type);
+ declaration_t *parameters = parse_parameters(method_type);
+ if(declaration != NULL) {
+ declaration->context.declarations = parameters;
+ }
part->method_type = method_type;
/* TODO */
- if(token.type == '*' && la(1)->type == ']') {
+ if(token.type == '*' && look_ahead(1)->type == ']') {
next_token();
} else if(token.type != ']') {
parse_assignment_expression();
{
declarator_part *part = parse_inner_declarator(NULL, 1);
+ if(part == NULL)
+ return NULL;
+
type_t *result = construct_declarator_type(part, base_type);
obstack_free(&temp_obst, part);
parser_error_multiple_definition(declaration, ndeclaration);
}
+ int top = environment_top();
+ context_t *last_context = context;
+ set_context(&declaration->context);
+
+ /* push function parameters */
+ declaration_t *parameter = declaration->context.declarations;
+ for( ; parameter != NULL; parameter = parameter->next) {
+ environment_push(parameter, context);
+ }
+
statement_t *statement = parse_compound_statement();
+
+ assert(context == &declaration->context);
+ set_context(last_context);
+ environment_pop_to(top);
+
declaration->statement = statement;
return;
}
declaration_t *declaration
= allocate_ast_zero(sizeof(declaration[0]));
parse_declarator(declaration, specifiers->storage_class,
- specifiers->type, 0);
+ specifiers->type, 1);
/* TODO: check for doubled fields */
record_declaration(declaration);
{
reference_expression_t *ref = allocate_ast_zero(sizeof(ref[0]));
- ref->expression.type = EXPR_REFERENCE;
- ref->symbol = token.v.symbol;
+ ref->expression.type = EXPR_REFERENCE;
+ ref->symbol = token.v.symbol;
+
+ if(ref->symbol->declaration == NULL) {
+ parser_print_error_prefix();
+ fprintf(stderr, "unknown symbol '%s' found.\n", ref->symbol->string);
+ }
+ ref->declaration = ref->symbol->declaration;
next_token();
return parse_brace_expression();
}
- /* TODO: error message */
+ parser_print_error_prefix();
+ fprintf(stderr, "unexpected token ");
+ print_token(stderr, &token);
+ fprintf(stderr, "\n");
+ eat_statement();
return NULL;
}
return NULL;
}
+static
+int is_type_specifier(const token_t *token)
+{
+ declaration_t *declaration;
+
+ switch(token->type) {
+ TYPE_SPECIFIERS
+ return 1;
+ case T_IDENTIFIER:
+ declaration = token->v.symbol->declaration;
+ if(declaration == NULL)
+ return 0;
+ if(declaration->storage_class != STORAGE_CLASS_TYPEDEF)
+ return 0;
+ return 1;
+ default:
+ return 0;
+ }
+}
+
static
expression_t *parse_sizeof(unsigned precedence)
{
= allocate_ast_zero(sizeof(sizeof_expression[0]));
sizeof_expression->expression.type = EXPR_SIZEOF;
- if(token.type == '(' /* && LA1 is type_specifier */) {
+ if(token.type == '(' && is_type_specifier(look_ahead(1))) {
next_token();
sizeof_expression->type = parse_typename();
expect(')');
CREATE_BINEXPR_PARSER('>', BINEXPR_GREATER)
CREATE_BINEXPR_PARSER('=', BINEXPR_ASSIGN)
CREATE_BINEXPR_PARSER(T_EQUALEQUAL, BINEXPR_EQUAL)
-CREATE_BINEXPR_PARSER(T_SLASHEQUAL, BINEXPR_NOTEQUAL)
+CREATE_BINEXPR_PARSER(T_EXCLAMATIONMARKEQUAL, BINEXPR_NOTEQUAL)
CREATE_BINEXPR_PARSER(T_LESSEQUAL, BINEXPR_LESSEQUAL)
CREATE_BINEXPR_PARSER(T_GREATEREQUAL, BINEXPR_GREATEREQUAL)
CREATE_BINEXPR_PARSER('&', BINEXPR_BITWISE_AND)
statement_t *parse_if(void)
{
eat(T_if);
+
+ if_statement_t *statement = allocate_ast_zero(sizeof(statement[0]));
+ statement->statement.type = STATEMENT_IF;
+
expect('(');
- parse_expression();
+ statement->condition = parse_expression();
expect(')');
- parse_statement();
+ statement->true_statement = parse_statement();
if(token.type == T_else) {
next_token();
- parse_statement();
+ statement->false_statement = parse_statement();
}
- return NULL;
+ return (statement_t*) statement;
}
static
break;
case ';':
+ next_token();
statement = NULL;
break;
case T_IDENTIFIER:
- if(la(1)->type == ':') {
+ if(look_ahead(1)->type == ':') {
statement = parse_label_statement();
break;
}
DECLARATION_START
statement = parse_declaration_statement();
break;
+
+ default:
+ statement = parse_expression_statement();
+ break;
}
return statement;