scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

commit 62bae5dc1e64fe94698bb2bc24c400935fffcbb0
parent 104a93bf817eb53ba8431209961c56fd945668be
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Tue, 19 Sep 2017 11:12:34 +0100

[as] Add skeleton for expression evaluator

This skeleton is mainly taken from cc1 expression evaluator but
with different precedence.

Diffstat:
as/Makefile | 2+-
as/as.h | 11+++++++++++
as/expr.c | 203+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 215 insertions(+), 1 deletion(-)

diff --git a/as/Makefile b/as/Makefile @@ -4,7 +4,7 @@ LIBDIR = ../lib/scc include ../config.mk include $(LIBDIR)/libdep.mk -OBJ = main.o emit.o ins.o parser.o +OBJ = main.o emit.o ins.o parser.o expr.o HDR = ../inc/scc.h as.h MOREFLAGS = $(AS_CFLAGS) diff --git a/as/as.h b/as/as.h @@ -43,6 +43,7 @@ typedef struct arg Arg; typedef void Format(Op *, Arg *); typedef struct section Section; typedef struct symbol Symbol; +typedef struct node Node; struct line { char *label; @@ -88,6 +89,13 @@ struct symbol { struct symbol *next; }; +struct node { + char op; + struct symbol *sym; + struct node *left; + struct node *right; +}; + /* emit.c */ extern char *pack(TUINT v, int n, int inc); extern void isections(void); @@ -107,6 +115,9 @@ extern void error(char *msg, ...); extern int nextline(FILE *fp, struct line *linep); #endif +/* expr.c */ +extern Node *expr(void); + /* * Definition of global variables */ diff --git a/as/expr.c b/as/expr.c @@ -0,0 +1,203 @@ +static char sccsid[] = "@(#) ./as/node.c"; + +#include <string.h> + +#include "../inc/scc.h" +#include "as.h" + +#define NNODES 10 + +enum tokens { + IDEN = 1, + CHAR, + STRING, + SHL, + SHR, + GE, + LT, +}; + +static Alloc *arena; +static int yytoken; +static char *yytext; + +#define accept(t) (yytoken == (t) ? next() : 0) + +static Node * +node(int op, Node *l, Node *r) +{ + struct arena *ap; + Node *np; + + if (!arena) + arena = alloc(sizeof(Node), NNODES); + np = memset(new(arena), 0, sizeof(*np)); + np->op = op; + + return np; +} + +static Node * +binary(int op, Node *l, Node *r) +{ + return node(op, l, r); +} + +static Node * +unary(int op, Node *np) +{ + return node(op, np, NULL); +} + +static int +next(void) +{ + return 0; +} + +static void +unexpected(void) +{ + error("unexpected '%s'", yytext); +} + +static void +expect(int token) +{ + if (yytoken != token) + unexpected(); + next(); +} + +/*************************************************************************/ +/* grammar functions */ +/*************************************************************************/ + +static Node * +primary(void) +{ + Node *np; + + switch (yytoken) { + case IDEN: + case CHAR: + case STRING: + np = node(yytoken, NULL, NULL); + next(); + break; + case '(': + next(); + np = expr(); + expect(')'); + break; + default: + unexpected(); + return NULL; + } + + return np; +} + +static Node * +mul(void) +{ + int op; + Node *np; + + np = primary(); + for (;;) { + switch (op = yytoken) { + case '*': + case '/': + case '%': + case SHL: + case SHR: + next(); + binary(op, np, primary()); + break; + default: return np; + } + } +} + +static Node * +add(void) +{ + int op; + Node *np; + + np = mul(); + for (;;) { + switch (op = yytoken) { + case '+': + case '-': + next(); + np = binary(op, np, mul()); + break; + default: return np; + } + } +} + +static Node * +relational(void) +{ + int op; + Node *np; + + np = add(); + for (;;) { + switch (op = yytoken) { + case '<': + case '>': + case GE: + case LT: + next(); + np = binary(op, np, add()); + break; + default: return np; + } + } +} + +static Node * +not(void) +{ + Node *np; + + np = relational(); + while (accept('!')) + np = unary('!', relational()); + return np; +} + +static Node * +and(void) +{ + int op; + Node *np; + + np = not(); + while (accept('&')) + np = binary('&', np, not()); + return np; +} + +Node * +expr(void) +{ + int op; + Node *np; + + np = and(); + for (;;) { + switch (op = yytoken) { + case '|': + case '^': + next(); + np = binary(op, np, and()); + break; + default: return np; + } + } +}