diff options
Diffstat (limited to 'parse.c')
| -rw-r--r-- | parse.c | 351 |
1 files changed, 5 insertions, 346 deletions
@@ -23,6 +23,7 @@ typedef int __builtin_va_list; #include "parse.h" #include "symbol.h" #include "scope.h" +#include "expression.h" void show_statement(struct statement *stmt) { @@ -154,6 +155,7 @@ void show_expression(struct expression *expr) break; case EXPR_SYMBOL: if (!expr->symbol) { + warn(expr->token, "undefined symbol '%s'", show_token(expr->token)); printf("<nosymbol>"); break; } @@ -178,14 +180,6 @@ void show_expression(struct expression *expr) printf(" >"); } -static struct expression *alloc_expression(struct token *token, int type) -{ - struct expression *expr = __alloc_expression(0); - expr->type = type; - expr->token = token; - return expr; -} - struct statement *alloc_statement(struct token * token, int type) { struct statement *stmt = __alloc_statement(0); @@ -193,341 +187,6 @@ struct statement *alloc_statement(struct token * token, int type) return stmt; } -static int match_oplist(int op, ...) -{ - va_list args; - - va_start(args, op); - for (;;) { - int nextop = va_arg(args, int); - if (!nextop) - return 0; - if (op == nextop) - return 1; - } -} - -int lookup_type(struct token *token) -{ - if (token->type == TOKEN_IDENT) - return lookup_symbol(token->ident, NS_TYPEDEF) != NULL; - return 0; -} - -static struct token *comma_expression(struct token *, struct expression **); -static struct token *compound_statement(struct token *, struct statement *); -static struct token *initializer(struct token *token, struct ctype *type); - -static struct token *parens_expression(struct token *token, struct expression **expr, const char *where) -{ - token = expect(token, '(', where); - if (match_op(token, '{')) { - struct expression *e = alloc_expression(token, EXPR_STATEMENT); - struct statement *stmt = alloc_statement(token, STMT_COMPOUND); - *expr = e; - e->statement = stmt; - start_symbol_scope(); - token = compound_statement(token->next, stmt); - end_symbol_scope(); - token = expect(token, '}', "at end of statement expression"); - } else - token = parse_expression(token, expr); - return expect(token, ')', where); -} - -static struct token *primary_expression(struct token *token, struct expression **tree) -{ - struct expression *expr = NULL; - - switch (token->type) { - case TOKEN_INTEGER: - case TOKEN_FP: - case TOKEN_CHAR: - expr = alloc_expression(token, EXPR_CONSTANT); - token = token->next; - break; - - case TOKEN_IDENT: { - expr = alloc_expression(token, EXPR_SYMBOL); - expr->symbol = lookup_symbol(token->ident, NS_SYMBOL); - token = token->next; - break; - } - - case TOKEN_STRING: - expr = alloc_expression(token, EXPR_CONSTANT); - do { - token = token->next; - } while (token->type == TOKEN_STRING); - break; - - case TOKEN_SPECIAL: - if (token->special == '(') { - expr = alloc_expression(token, EXPR_PREOP); - expr->op = '('; - token = parens_expression(token, &expr->unop, "in expression"); - break; - } - default: - ; - } - *tree = expr; - return token; -} - -static struct token *postfix_expression(struct token *token, struct expression **tree) -{ - struct expression *expr = NULL; - - token = primary_expression(token, &expr); - while (expr && token->type == TOKEN_SPECIAL) { - switch (token->special) { - case '[': { /* Array dereference */ - struct expression *array_expr = alloc_expression(token, EXPR_BINOP); - array_expr->op = '['; - array_expr->left = expr; - token = parse_expression(token->next, &array_expr->right); - token = expect(token, ']', "at end of array dereference"); - expr = array_expr; - continue; - } - case SPECIAL_INCREMENT: /* Post-increment */ - case SPECIAL_DECREMENT: { /* Post-decrement */ - struct expression *post = alloc_expression(token, EXPR_POSTOP); - post->op = token->special; - post->unop = expr; - expr = post; - token = token->next; - continue; - } - case '.': /* Structure member dereference */ - case SPECIAL_DEREFERENCE: { /* Structure pointer member dereference */ - struct expression *deref = alloc_expression(token, EXPR_DEREF); - deref->op = token->special; - deref->deref = expr; - token = token->next; - if (token->type != TOKEN_IDENT) { - warn(token, "Expected member name"); - break; - } - deref->member = token; - token = token->next; - expr = deref; - continue; - } - - case '(': { /* Function call */ - struct expression *call = alloc_expression(token, EXPR_BINOP); - call->op = '('; - call->left = expr; - token = comma_expression(token->next, &call->right); - token = expect(token, ')', "in function call"); - expr = call; - continue; - } - - default: - break; - } - break; - } - *tree = expr; - return token; -} - -static struct token *typename(struct token *, struct symbol **); - -static struct token *cast_expression(struct token *token, struct expression **tree); -static struct token *unary_expression(struct token *token, struct expression **tree) -{ - if (token->type == TOKEN_IDENT && - (token->ident == &sizeof_ident || - token->ident == &__alignof___ident)) { - struct expression *sizeof_ex = alloc_expression(token, EXPR_SIZEOF); - *tree = sizeof_ex; - tree = &sizeof_ex->unop; - token = token->next; - if (!match_op(token, '(') || !lookup_type(token->next)) - return unary_expression(token, &sizeof_ex->cast_expression); - token = typename(token->next, &sizeof_ex->cast_type); - return expect(token, ')', "at end of sizeof type-name"); - } - - if (token->type == TOKEN_SPECIAL) { - if (match_oplist(token->special, - SPECIAL_INCREMENT, SPECIAL_DECREMENT, - '&', '*', '+', '-', '~', '!', 0)) { - struct expression *unary = alloc_expression(token, EXPR_PREOP); - unary->op = token->special; - *tree = unary; - return cast_expression(token->next, &unary->unop); - } - } - - return postfix_expression(token, tree); -} - -/* - * Ambiguity: a '(' can be either a cast-expression or - * a primary-expression depending on whether it is followed - * by a type or not. - */ -static struct token *cast_expression(struct token *token, struct expression **tree) -{ - if (match_op(token, '(')) { - struct token *next = token->next; - if (lookup_type(next)) { - struct expression *cast = alloc_expression(next, EXPR_CAST); - - token = typename(next, &cast->cast_type); - token = expect(token, ')', "at end of cast operator"); - if (match_op(token, '{')) - return initializer(token, &cast->cast_type->ctype); - token = cast_expression(token, &cast->cast_expression); - *tree = cast; - return token; - } - } - return unary_expression(token, tree); -} - -/* Generic left-to-right binop parsing */ -static struct token *lr_binop_expression(struct token *token, struct expression **tree, - struct token *(*inner)(struct token *, struct expression **), ...) -{ - struct expression *left = NULL; - struct token * next = inner(token, &left); - - if (left) { - while (next->type == TOKEN_SPECIAL) { - struct expression *top, *right = NULL; - int op = next->special; - va_list args; - - va_start(args, inner); - for (;;) { - int nextop = va_arg(args, int); - if (!nextop) - goto out; - if (op == nextop) - break; - } - va_end(args); - top = alloc_expression(next, EXPR_BINOP); - next = inner(next->next, &right); - if (!right) { - warn(next, "No right hand side of '%s'-expression", show_special(op)); - break; - } - top->op = op; - top->left = left; - top->right = right; - left = top; - } - } -out: - *tree = left; - return next; -} - -static struct token *multiplicative_expression(struct token *token, struct expression **tree) -{ - return lr_binop_expression(token, tree, cast_expression, '*', '/', '%', 0); -} - -static struct token *additive_expression(struct token *token, struct expression **tree) -{ - return lr_binop_expression(token, tree, multiplicative_expression, '+', '-', 0); -} - -static struct token *shift_expression(struct token *token, struct expression **tree) -{ - return lr_binop_expression(token, tree, additive_expression, SPECIAL_LEFTSHIFT, SPECIAL_RIGHTSHIFT, 0); -} - -static struct token *relational_expression(struct token *token, struct expression **tree) -{ - return lr_binop_expression(token, tree, shift_expression, '<', '>', SPECIAL_LTE, SPECIAL_GTE, 0); -} - -static struct token *equality_expression(struct token *token, struct expression **tree) -{ - return lr_binop_expression(token, tree, relational_expression, SPECIAL_EQUAL, SPECIAL_NOTEQUAL, 0); -} - -static struct token *bitwise_and_expression(struct token *token, struct expression **tree) -{ - return lr_binop_expression(token, tree, equality_expression, '&', 0); -} - -static struct token *bitwise_xor_expression(struct token *token, struct expression **tree) -{ - return lr_binop_expression(token, tree, bitwise_and_expression, '^', 0); -} - -static struct token *bitwise_or_expression(struct token *token, struct expression **tree) -{ - return lr_binop_expression(token, tree, bitwise_xor_expression, '|', 0); -} - -static struct token *logical_and_expression(struct token *token, struct expression **tree) -{ - return lr_binop_expression(token, tree, bitwise_or_expression, SPECIAL_LOGICAL_AND, 0); -} - -static struct token *logical_or_expression(struct token *token, struct expression **tree) -{ - return lr_binop_expression(token, tree, logical_and_expression, SPECIAL_LOGICAL_OR, 0); -} - -struct token *conditional_expression(struct token *token, struct expression **tree) -{ - token = logical_or_expression(token, tree); - if (match_op(token, '?')) { - struct expression *expr = alloc_expression(token, EXPR_CONDITIONAL); - expr->op = token->special; - expr->left = *tree; - *tree = expr; - token = parse_expression(token->next, &expr->cond_true); - token = expect(token, ':', "in conditional expression"); - token = conditional_expression(token, &expr->cond_false); - } - return token; -} - -struct token *assignment_expression(struct token *token, struct expression **tree) -{ - token = conditional_expression(token, tree); - if (token->type == TOKEN_SPECIAL) { - static const int assignments[] = { - '=', SPECIAL_ADD_ASSIGN, SPECIAL_MINUS_ASSIGN, - SPECIAL_TIMES_ASSIGN, SPECIAL_DIV_ASSIGN, - SPECIAL_MOD_ASSIGN, SPECIAL_SHL_ASSIGN, - SPECIAL_SHR_ASSIGN, SPECIAL_AND_ASSIGN, - SPECIAL_OR_ASSIGN, SPECIAL_XOR_ASSIGN }; - int i, op = token->special; - for (i = 0; i < sizeof(assignments)/sizeof(int); i++) - if (assignments[i] == op) { - struct expression * expr = alloc_expression(token, EXPR_BINOP); - expr->left = *tree; - expr->op = op; - *tree = expr; - return assignment_expression(token->next, &expr->right); - } - } - return token; -} - -struct token *comma_expression(struct token *token, struct expression **tree) -{ - return lr_binop_expression(token, tree, assignment_expression, ',', 0); -} - -struct token *parse_expression(struct token *token, struct expression **tree) -{ - return comma_expression(token,tree); -} - static struct token *struct_declaration_list(struct token *token, struct symbol_list **list); static void force_default_type(struct ctype *type) @@ -859,7 +518,7 @@ static struct token *parameter_declaration(struct token *token, struct symbol ** return token; } -static struct token *typename(struct token *token, struct symbol **p) +struct token *typename(struct token *token, struct symbol **p) { struct ctype ctype = { 0, }; struct symbol *sym = alloc_symbol(token, SYM_TYPE); @@ -1060,7 +719,7 @@ static struct token *abstract_function_declarator(struct token *token, struct sy static struct token *external_declaration(struct token *token, struct symbol_list **list); -static struct token *compound_statement(struct token *token, struct statement *stmt) +struct token *compound_statement(struct token *token, struct statement *stmt) { while (!eof_token(token)) { if (!lookup_type(token)) @@ -1082,7 +741,7 @@ static struct token *initializer_list(struct token *token, struct ctype *type) return token; } -static struct token *initializer(struct token *token, struct ctype *type) +struct token *initializer(struct token *token, struct ctype *type) { struct expression *expr; if (match_op(token, '{')) { |
