aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
-rw-r--r--Makefile10
-rw-r--r--lib.c18
-rw-r--r--parse.c135
-rw-r--r--parse.h10
4 files changed, 137 insertions, 36 deletions
diff --git a/Makefile b/Makefile
index 4b22617b..e6fee791 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,8 @@
CFLAGS=-g -Wall
-all: test-lexing test-parsing
+PROGRAMS=test-lexing test-parsing
+
+all: $(PROGRAMS)
test-lexing: test-lexing.o tokenize.o lib.o
gcc -o $@ test-lexing.o tokenize.o lib.o
@@ -8,10 +10,10 @@ test-lexing: test-lexing.o tokenize.o lib.o
test-parsing: test-parsing.o parse.o tokenize.o lib.o
gcc -o $@ test-parsing.o parse.o tokenize.o lib.o
-test-parsing: token.h
+test-parsing.o: token.h parse.h
test-lexing.o: token.h
tokenize.o: token.h
-parse.o: token.h
+parse.o: token.h parse.h
clean:
- rm -f *.o
+ rm -f *.[oasi] $(PROGRAMS)
diff --git a/lib.c b/lib.c
index d0b9d661..bf498311 100644
--- a/lib.c
+++ b/lib.c
@@ -9,17 +9,25 @@
void warn(struct token *token, const char * fmt, ...)
{
static char buffer[512];
- struct stream *stream;
+ const char *name;
+ int pos,line;
va_list args;
va_start(args, fmt);
vsprintf(buffer, fmt, args);
va_end(args);
- stream = input_streams + token->stream;
- fprintf(stderr, "warning: %s:%d: %s\n",
- stream->name, token->line,
- buffer);
+ name = "EOF";
+ pos = 0;
+ line = 0;
+ if (token) {
+ name = input_streams[token->stream].name;
+ pos = token->pos;
+ line = token->line;
+ }
+
+ fprintf(stderr, "warning: %s:%d:%d: %s\n",
+ name, line, pos, buffer);
}
diff --git a/parse.c b/parse.c
index f8fdc5be..1a2b9253 100644
--- a/parse.c
+++ b/parse.c
@@ -20,20 +20,34 @@ void show_expression(struct expression *expr)
return;
switch (expr->type) {
- case EXPR_IDENT:
- printf("%s", show_token(expr->token));
- break;
case EXPR_BINOP:
- printf("<");
+ printf("< ");
show_expression(expr->left);
printf(" %s ", show_special(expr->op));
show_expression(expr->right);
- printf(">");
+ printf(" >");
+ break;
+ case EXPR_PREOP:
+ printf("( ");
+ printf(" %s ", show_special(expr->op));
+ show_expression(expr->unop);
+ printf(" )");
break;
- case EXPR_UNARY:
- printf("(");
+ case EXPR_POSTOP:
+ printf("( ");
show_expression(expr->unop);
- printf(")");
+ printf(" %s ", show_special(expr->op));
+ printf(" )");
+ break;
+ case EXPR_PRIMARY:
+ printf("%s", show_token(expr->token));
+ break;
+ case EXPR_DEREF:
+ printf("< ");
+ show_expression(expr->deref);
+ printf("%s", show_special(expr->op));
+ printf("%s", show_token(expr->member));
+ printf(" >");
break;
default:
printf("WTF");
@@ -52,35 +66,106 @@ static struct expression *alloc_expression(struct token *token, int type)
return expr;
}
-struct token *cast_expression(struct token *token, struct expression **tree)
+struct token *expect(struct token *token, int op)
+{
+ if (!token ||
+ token->value.type != TOKEN_SPECIAL ||
+ token->value.special != op) {
+ warn(token, "Expected %s", show_special(op));
+ return token;
+ }
+ return token->next;
+}
+
+struct token *primary_expression(struct token *token, struct expression **tree)
{
struct expression *expr = NULL;
- if (token) {
- switch (token->value.type) {
- case TOKEN_IDENT:
- expr = alloc_expression(token, EXPR_IDENT);
- token = token->next;
+ switch (token->value.type) {
+ case TOKEN_IDENT:
+ case TOKEN_INTEGER:
+ case TOKEN_FP:
+ case TOKEN_STRING:
+ expr = alloc_expression(token, EXPR_PRIMARY);
+ token = token->next;
+ break;
+
+ case TOKEN_SPECIAL:
+ if (token->value.special == '(') {
+ expr = alloc_expression(token, EXPR_PREOP);
+ expr->op = '(';
+ token = parse_expression(token->next, &expr->unop);
+ token = expect(token, ')');
break;
- case TOKEN_SPECIAL:
- if (token->value.special == '(') {
- expr = alloc_expression(token, EXPR_UNARY);
- expr->op = '(';
- token = parse_expression(token->next, &expr->unop);
- if (!token || token->value.type != TOKEN_SPECIAL || token->value.special != ')')
- warn(token, "Expected ')'");
- else
- token = token->next;
+ }
+ /* Fallthrough */
+ default:
+ warn(token, "Expected primary expression");
+ }
+ *tree = expr;
+ return token;
+}
+
+struct token *postfix_expression(struct token *token, struct expression **tree)
+{
+ struct expression *expr = NULL;
+
+ token = primary_expression(token, &expr);
+ while (expr && token && token->value.type == TOKEN_SPECIAL) {
+ switch (token->value.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, ']');
+ 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->value.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->value.special;
+ deref->deref = expr;
+ token = token->next;
+ if (!token || token->value.type != TOKEN_IDENT) {
+ warn(token, "Expected member name");
break;
}
- default:
- warn(token, "Syntax error");
+ deref->member = token;
+ token = token->next;
+ expr = deref;
+ continue;
}
+
+ case '(': /* Function call */
+ break;
+ }
+ break;
}
*tree = expr;
return token;
}
+struct token *unary_expression(struct token *token, struct expression **tree)
+{
+ return postfix_expression(token, tree);
+}
+
+struct token *cast_expression(struct token *token, struct expression **tree)
+{
+ return unary_expression(token, tree);
+}
+
/* Generic left-to-right binop parsing */
struct token *lr_binop_expression(struct token *token, struct expression **tree,
struct token *(*inner)(struct token *, struct expression **), ...)
diff --git a/parse.h b/parse.h
index 0a2e2ff8..27421184 100644
--- a/parse.h
+++ b/parse.h
@@ -2,9 +2,11 @@
#define PARSE_H
enum expression_type {
- EXPR_UNARY,
+ EXPR_PRIMARY,
EXPR_BINOP,
- EXPR_IDENT,
+ EXPR_DEREF,
+ EXPR_PREOP,
+ EXPR_POSTOP,
};
struct expression {
@@ -15,6 +17,10 @@ struct expression {
struct binop_arg {
struct expression *left, *right;
};
+ struct deref_arg {
+ struct expression *deref;
+ struct token *member;
+ };
};
};