commit 9539419a2015c425987e74556e2dbf94e1887af5
parent 9c7e1299c8ab117b928e3b53570b33fcdbd8c735
Author: sin <sin@2f30.org>
Date: Wed, 14 May 2014 13:46:29 +0100
Parse pairs/lists
Diffstat:
M | lexer.c | | | 13 | +++++++++++++ |
M | lexer.h | | | 1 | + |
M | parser.c | | | 84 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
3 files changed, 98 insertions(+), 0 deletions(-)
diff --git a/lexer.c b/lexer.c
@@ -30,6 +30,8 @@ static enum state state;
static char *s;
static char *e;
static char buf[MAXTOKSIZE];
+static struct tok lasttok;
+static int pendingtok;
static int
delim(int c)
@@ -44,6 +46,10 @@ gettok(FILE *in)
struct tok tok;
int c;
+ if (pendingtok == 1) {
+ pendingtok = 0;
+ return lasttok;
+ }
again:
state = SSe;
s = e = buf;
@@ -240,3 +246,10 @@ lexeme(struct tok *t)
return strdup(t->s);
return strndup(t->s, t->e - t->s);
}
+
+void
+pushbacktok(struct tok t)
+{
+ lasttok = t;
+ pendingtok = 1;
+}
diff --git a/lexer.h b/lexer.h
@@ -21,3 +21,4 @@ struct tok {
struct tok gettok(FILE *fp);
char *lexeme(struct tok *);
+void pushbacktok(struct tok);
diff --git a/parser.c b/parser.c
@@ -16,6 +16,8 @@ enum objtype {
ONumber,
OCharacter,
OString,
+ OEmptylist,
+ OPair,
};
struct object {
@@ -49,6 +51,11 @@ struct object {
struct {
char *s;
} s;
+ /* pair */
+ struct {
+ struct object *car;
+ struct object *cdr;
+ } p;
} d;
};
@@ -135,6 +142,52 @@ string(char *s)
return o;
}
+static struct object *
+emptylist(void)
+{
+ struct object *o;
+
+ o = newobject();
+ o->type = OEmptylist;
+ return o;
+}
+
+static struct object *
+cons(struct object *car, struct object *cdr)
+{
+ struct object *o;
+
+ o = newobject();
+ o->type = OPair;
+ o->d.p.car = car;
+ o->d.p.cdr = cdr;
+ return o;
+}
+
+static struct object *
+pair(FILE *in)
+{
+ struct object *car, *cdr;
+ struct tok t;
+
+ t = gettok(in);
+ if (t.type == TRparen)
+ return emptylist();
+ pushbacktok(t);
+ car = sexpression(in);
+ t = gettok(in);
+ if (t.type == TDot) {
+ cdr = sexpression(in);
+ t = gettok(in);
+ if (t.type != TRparen)
+ return error("missing right parenthesis");
+ return cons(car, cdr);
+ }
+ pushbacktok(t);
+ cdr = pair(in);
+ return cons(car, cdr);
+}
+
struct object *
sexpression(FILE *in)
{
@@ -161,6 +214,8 @@ sexpression(FILE *in)
return character(l[2]);
case TString:
return string(l);
+ case TLparen:
+ return pair(in);
default:
return error("unhandled token");
}
@@ -182,6 +237,27 @@ eval(struct object *o)
return o;
}
+static void
+printpair(struct object *o)
+{
+ struct object *car, *cdr;
+
+ car = o->d.p.car;
+ cdr = o->d.p.cdr;
+ print(car);
+ if (cdr->type == OPair) {
+ putchar(' ');
+ printpair(cdr);
+ } else if (cdr->type == OEmptylist) {
+ return;
+ } else {
+ putchar(' ');
+ putchar('.');
+ putchar(' ');
+ print(cdr);
+ }
+}
+
void
print(struct object *o)
{
@@ -204,5 +280,13 @@ print(struct object *o)
case OString:
printf("%s", o->d.s.s);
break;
+ case OEmptylist:
+ printf("()");
+ break;
+ case OPair:
+ putchar('(');
+ printpair(o);
+ putchar(')');
+ break;
}
}