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:
M | as/Makefile | | | 2 | +- |
M | as/as.h | | | 11 | +++++++++++ |
A | 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;
+ }
+ }
+}