diff options
| author | Linus Torvalds <torvalds@penguin.transmeta.com> | 2003-03-21 13:05:06 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-07 20:59:34 -0700 |
| commit | 64813fc70ff51f446c45baf3061b76952294dbe3 (patch) | |
| tree | 7a1d5408d57b4156104e22127493f3a16a999524 | |
| parent | a037a64f9f31465265086543cf1cb079ca6d1b7d (diff) | |
| download | sparse-dev-64813fc70ff51f446c45baf3061b76952294dbe3.tar.gz | |
Split up the expression parsing in "parse.c" into a file of
its own - expression.c.
| -rw-r--r-- | Makefile | 4 | ||||
| -rw-r--r-- | expression.c | 347 | ||||
| -rw-r--r-- | expression.h | 44 | ||||
| -rw-r--r-- | parse.c | 351 |
4 files changed, 398 insertions, 348 deletions
@@ -2,8 +2,8 @@ CC=gcc CFLAGS=-g -Wall PROGRAMS=test-lexing test-parsing -HEADERS=token.h parse.h lib.h symbol.h scope.h -COMMON=parse.o tokenize.o pre-process.o symbol.o lib.o scope.o +HEADERS=token.h parse.h lib.h symbol.h scope.h expression.h +COMMON=parse.o tokenize.o pre-process.o symbol.o lib.o scope.o expression.o all: $(PROGRAMS) diff --git a/expression.c b/expression.c new file mode 100644 index 00000000..fe054bc6 --- /dev/null +++ b/expression.c @@ -0,0 +1,347 @@ +/* + * sparse/expression.c + * + * Copyright (C) 2003 Linus Torvalds, all rights reserved. + * + * This is the expression parsing part of parsing C. + */ +#include <stdarg.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <unistd.h> +#include <fcntl.h> + +#include "lib.h" +#include "token.h" +#include "parse.h" +#include "symbol.h" +#include "scope.h" +#include "expression.h" + +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; + } +} + +static struct token *comma_expression(struct token *, struct expression **); + +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); +} + +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 *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; +} + +static 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); +} + + diff --git a/expression.h b/expression.h new file mode 100644 index 00000000..977c3e15 --- /dev/null +++ b/expression.h @@ -0,0 +1,44 @@ +#ifndef EXPRESSION_H +#define EXPRESSION_H +/* + * sparse/expression.h + * + * Copyright (C) 2003 Linus Torvalds, all rights reserved + * + * Declarations and helper functions for expression parsing. + */ + +/* Expression parsing */ +struct token *parse_expression(struct token *token, struct expression **tree); +struct token *conditional_expression(struct token *token, struct expression **tree); +struct token *primary_expression(struct token *token, struct expression **tree); +struct token *parens_expression(struct token *token, struct expression **expr, const char *where); +struct token *assignment_expression(struct token *token, struct expression **tree); + +static inline struct expression *alloc_expression(struct token *token, int type) +{ + struct expression *expr = __alloc_expression(0); + expr->type = type; + expr->token = token; + return expr; +} + +/* Type name parsing */ +struct token *typename(struct token *, struct symbol **); + +static inline int lookup_type(struct token *token) +{ + if (token->type == TOKEN_IDENT) + return lookup_symbol(token->ident, NS_TYPEDEF) != NULL; + return 0; +} + +/* Statement parsing */ +struct statement *alloc_statement(struct token * token, int type); +struct token *initializer(struct token *token, struct ctype *type); +struct token *compound_statement(struct token *, struct statement *); + +/* The preprocessor calls this 'constant_expression()' */ +#define constant_expression(token,tree) conditional_expression(token, tree) + +#endif @@ -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, '{')) { |
