add FILE* to parser

This commit is contained in:
yoyo 2024-09-08 16:52:11 +09:00
parent 0e6bc88cab
commit 3ae8c663e7
5 changed files with 71 additions and 72 deletions

View File

@ -1,7 +1,6 @@
#include "dat.h" #include "dat.h"
#include "fn.h" #include "fn.h"
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <setjmp.h> #include <setjmp.h>

5
fn.h
View File

@ -1,6 +1,7 @@
#include <stdio.h>
/* parser.c */ /* parser.c */
Object* nextexpr(void); Object* nextexpr(FILE*);
void skipline(void); void skipline(FILE*);
/* eval.c */ /* eval.c */
Object* eval(Object *env, Object *expr); Object* eval(Object *env, Object *expr);

1
gc.c
View File

@ -3,7 +3,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <setjmp.h> #include <setjmp.h>
#include <string.h> #include <string.h>
#include <stdio.h>
#include <assert.h> #include <assert.h>
#include <stdint.h> #include <stdint.h>

15
main.c
View File

@ -1,7 +1,6 @@
#include "dat.h" #include "dat.h"
#include "fn.h" #include "fn.h"
#include <setjmp.h> #include <setjmp.h>
#include <stdio.h>
jmp_buf *errptr; jmp_buf *errptr;
GC *gc; GC *gc;
@ -63,16 +62,17 @@ printexpr(Object *obj)
} }
static void static void
loop(void) loop(Object *env, FILE *f)
{ {
Object *env = newenv(gc, &Nil, &Nil, &Nil);
jmp_buf buf; jmp_buf buf;
errptr = &buf; errptr = &buf;
if(setjmp(buf) == 1){ if(setjmp(buf) == 1){
skipline(); if(feof(f))
return;
skipline(f);
} }
while(1){ while(1){
Object *res = nextexpr(); Object *res = nextexpr(f);
printexpr(res); printexpr(res);
res = eval(env, res); res = eval(env, res);
printgc("status", gc); printgc("status", gc);
@ -87,6 +87,7 @@ loop(void)
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
gc = newgc(&argc, 4000); gc = newgc(&argc, 400);
loop(); Object *env = newenv(gc, &Nil, &Nil, &Nil);
loop(env, stdin);
} }

121
parser.c
View File

@ -1,6 +1,5 @@
#include "dat.h" #include "dat.h"
#include "fn.h" #include "fn.h"
#include <stdio.h>
#include <ctype.h> #include <ctype.h>
#include <string.h> #include <string.h>
@ -8,177 +7,177 @@
const char symbolchars[] = "!*/%-=+<>'"; const char symbolchars[] = "!*/%-=+<>'";
static Object* lparlist(void); static Object* lparlist(FILE *);
static Object* list(void); static Object* list(FILE *);
static char static char
get(void) get(FILE *f)
{ {
char c = getchar(); char c = fgetc(f);
if(c == EOF) if(c == EOF)
panic("EOF"); error("EOF");
return c; return c;
} }
static void static void
expect(char x) expect(FILE *f, char x)
{ {
char y = get(); char y = get(f);
if(x != y) if(x != y)
error("expected '%c', actual '%c'", x, y); error("expected '%c', actual '%c'", x, y);
} }
static char static char
lookup(void) lookup(FILE *f)
{ {
char c = get(); char c = get(f);
ungetc(c, stdin); ungetc(c, f);
return c; return c;
} }
/* skip space */ /* skip space */
static char static char
slookup(void) slookup(FILE *f)
{ {
char c = -1; char c = -1;
while(1){ while(1){
c = get(); c = get(f);
if(isspace(c) == 0) if(isspace(c) == 0)
break; break;
} }
ungetc(c, stdin); ungetc(c, f);
return c; return c;
} }
static Object* static Object*
symbol(char c) symbol(FILE *f, char c)
{ {
char buf[SYMBOL_LEN+1] = {0,}; char buf[SYMBOL_LEN+1] = {0,};
int len = 0; int len = 0;
buf[len++] = c; buf[len++] = c;
while(isalnum(lookup()) || strchr(symbolchars, lookup())){ while(isalnum(lookup(f)) || strchr(symbolchars, lookup(f))){
if(len >= sizeof(buf)-1) if(len >= sizeof(buf)-1)
error("Symbol too long"); error("Symbol too long");
buf[len++] = get(); buf[len++] = get(f);
} }
buf[len] = 0; buf[len] = 0;
return newsymbol(gc, buf, len); return newsymbol(gc, buf, len);
} }
static long static long
number(void) number(FILE *f)
{ {
long val = get() - '0'; long val = get(f) - '0';
while(isdigit(lookup())) while(isdigit(lookup(f)))
val = val * 10 + (get() - '0'); val = val * 10 + (get(f) - '0');
return val; return val;
} }
static Object* static Object*
quote(void) quote(FILE *f)
{ {
Object *car = &Quote; Object *car = &Quote;
Object *ccdr = list(); Object *ccdr = list(f);
Object *cdr = newcons(gc, ccdr, &Nil); Object *cdr = newcons(gc, ccdr, &Nil);
return newcons(gc, car, cdr); return newcons(gc, car, cdr);
} }
static Object* static Object*
string(void) string(FILE *f)
{ {
Object *str = newstr(gc, 16); Object *str = newstr(gc, 16);
while(lookup() != '\"'){ while(lookup(f) != '\"'){
str = strputc(str, get()); str = strputc(str, get(f));
} }
expect('\"'); expect(f, '\"');
return str; return str;
} }
static Object* static Object*
atom(char c) atom(FILE *f, char c)
{ {
if(isdigit(c)) if(isdigit(c))
return newint(gc, number()); return newint(gc, number(f));
get(); get(f);
if(c == '-'){ if(c == '-'){
if(isdigit(lookup())) if(isdigit(lookup(f)))
return newint(gc, -number()); return newint(gc, -number(f));
else else
return symbol('-'); return symbol(f, '-');
} }
if(c == '"'){ if(c == '"'){
return string(); return string(f);
} }
if(isalpha(c) || strchr(symbolchars, c)){ if(isalpha(c) || strchr(symbolchars, c)){
return symbol(c); return symbol(f, c);
} }
error("bad char in list '%c'", c); error("bad char in list '%c'", c);
return 0; return 0;
} }
static Object* static Object*
lparlist(void) lparlist(FILE *f)
{ {
Object *car = 0; Object *car = 0;
Object *cdr = 0; Object *cdr = 0;
char c = slookup(); char c = slookup(f);
switch(c){ switch(c){
case '\'': case '\'':
get(); get(f);
car = quote(); car = quote(f);
cdr = lparlist(); cdr = lparlist(f);
return newcons(gc, car, cdr); return newcons(gc, car, cdr);
case '.': case '.':
get(); get(f);
return list(); return list(f);
case '(': case '(':
car = list(); car = list(f);
cdr = lparlist(); cdr = lparlist(f);
return newcons(gc, car, cdr); return newcons(gc, car, cdr);
case ')': case ')':
return &Nil; return &Nil;
} }
car = atom(c); car = atom(f, c);
cdr = lparlist(); cdr = lparlist(f);
return newcons(gc, car ,cdr); return newcons(gc, car ,cdr);
} }
static Object* static Object*
list(void) list(FILE *f)
{ {
char c = slookup(); char c = slookup(f);
switch(c){ switch(c){
case '\'': case '\'':
get(); get(f);
return quote(); return quote(f);
case '(':{ case '(':{
get(); get(f);
Object *obj = lparlist(); Object *obj = lparlist(f);
slookup(); slookup(f);
expect(')'); expect(f, ')');
return obj; return obj;
} }
} }
return atom(c); return atom(f, c);
} }
void void
skipline(void) skipline(FILE *f)
{ {
for(;;){ for(;;){
switch(get()){ switch(get(f)){
case '\n': case '\n':
return; return;
case '\r': case '\r':
if(lookup() == '\n') if(lookup(f) == '\n')
get(); get(f);
return; return;
} }
} }
} }
Object* Object*
nextexpr(void) nextexpr(FILE *f)
{ {
return list(); return list(f);
} }