commit 30bcc78313a2fd2e676ad14f5a62bd6450ec117f
parent 489b9ef2bdc8f84fa6f30e4f84eea475847d8506
Author: sin <sin@2f30.org>
Date: Wed, 14 May 2014 15:59:43 +0100
Add rudimentary parsing for self-evaluating objects
Diffstat:
M | parser.c | | | 158 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | parser.h | | | 13 | ++++++++++++- |
M | repl.c | | | 22 | ++++++---------------- |
3 files changed, 176 insertions(+), 17 deletions(-)
diff --git a/parser.c b/parser.c
@@ -2,6 +2,8 @@
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
+#include "lexer.h"
#include "parser.h"
struct object *
@@ -14,3 +16,159 @@ newobject(void)
return NULL;
return o;
}
+
+struct object *
+error(struct tok *t)
+{
+ struct object *o;
+ char *l;
+
+ l = lexeme(t);
+ if (!l)
+ return NULL;
+ o = newobject();
+ o->type = OError;
+ o->d.err.s = strdup(l);
+ free(l);
+ return o;
+}
+
+struct object *
+eof(struct tok *t)
+{
+ struct object *o;
+ char *l;
+
+ l = lexeme(t);
+ if (!l)
+ return NULL;
+ o = newobject();
+ o->type = OEof;
+ o->d.err.s = strdup(l);
+ free(l);
+ return o;
+}
+
+struct object *
+boolean(struct tok *t)
+{
+ struct object *o;
+ char *l;
+
+ l = lexeme(t);
+ if (!l)
+ return NULL;
+ o = newobject();
+ o->type = OBoolean;
+ if (l[1] == 'f')
+ o->d.b.v = false;
+ if (l[1] == 't')
+ o->d.b.v = true;
+ free(l);
+ return o;
+}
+
+struct object *
+number(struct tok *t)
+{
+ struct object *o;
+ char *l;
+
+ l = lexeme(t);
+ if (!l)
+ return NULL;
+ o = newobject();
+ o->type = ONumber;
+ o->d.c.v = strtol(l, 0, 10);
+ free(l);
+ return o;
+}
+
+struct object *
+character(struct tok *t)
+{
+ struct object *o;
+ char *l;
+
+ l = lexeme(t);
+ if (!l)
+ return NULL;
+ o = newobject();
+ o->type = OCharacter;
+ o->d.c.v = l[2];
+ free(l);
+ return o;
+}
+
+struct object *
+string(struct tok *t)
+{
+ struct object *o;
+ char *l;
+
+ l = lexeme(t);
+ if (!l)
+ return NULL;
+ o = newobject();
+ o->type = OString;
+ o->d.s.s = strdup(l);
+ free(l);
+ return o;
+}
+
+struct object *
+sexpression(FILE *in)
+{
+ struct tok t;
+
+ t = gettok(in);
+
+ switch (t.type) {
+ case TEof:
+ return eof(&t);
+ case TError:
+ return error(&t);
+ case TBoolean:
+ return boolean(&t);
+ case TNumber:
+ return number(&t);
+ case TCharacter:
+ return character(&t);
+ case TString:
+ return string(&t);
+ }
+ return NULL;
+}
+
+struct object *
+eval(struct object *o)
+{
+ return o;
+}
+
+void
+print(struct object *o)
+{
+ if (!o)
+ return;
+ switch (o->type) {
+ case OError:
+ printf("%s\n", o->d.err.s);
+ break;
+ case OEof:
+ printf("%s\n", o->d.eof.s);
+ break;
+ case OBoolean:
+ printf("#%c\n", o->d.b.v == false ? 'f' : 't');
+ break;
+ case ONumber:
+ printf("%ld\n", o->d.n.v);
+ break;
+ case OCharacter:
+ printf("#\\%c\n", o->d.c.v);
+ break;
+ case OString:
+ printf("%s\n", o->d.s.s);
+ break;
+ }
+}
diff --git a/parser.h b/parser.h
@@ -1,7 +1,9 @@
/* See LICENSE file for copyright and license details. */
enum objtype {
+ OError = -2,
+ OEof = -1,
OIdentifier,
- OBool,
+ OBoolean,
ONumber,
OCharacter,
OString,
@@ -10,6 +12,12 @@ enum objtype {
struct object {
enum objtype type;
union {
+ struct {
+ char *s;
+ } err;
+ struct {
+ char *s;
+ } eof;
/* identifier */
struct {
char *s;
@@ -34,3 +42,6 @@ struct object {
};
struct object *newobject(void);
+struct object *sexpression(FILE *);
+struct object *eval(struct object *);
+void print(struct object *);
diff --git a/repl.c b/repl.c
@@ -1,24 +1,14 @@
/* See LICENSE file for copyright and license details. */
+#include <stdbool.h>
#include <stdio.h>
-#include "lexer.h"
-#include "debug.h"
-
-static void
-lexertest(FILE *in)
-{
- struct tok tok;
-
- do {
- tok = gettok(in);
- printtok(&tok);
- putchar('\n');
- fflush(stdout);
- } while (tok.type != TEof && tok.type != TError);
-}
+#include "parser.h"
int
main(void)
{
- lexertest(stdin);
+ do {
+ print(eval(sexpression(stdin)));
+ } while (1);
+ /* not reachable */
return 0;
}