aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/parse.c
diff options
Diffstat (limited to 'parse.c')
-rw-r--r--parse.c351
1 files changed, 5 insertions, 346 deletions
diff --git a/parse.c b/parse.c
index a97762f7..5aed9c5f 100644
--- a/parse.c
+++ b/parse.c
@@ -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, '{')) {