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 "fn.h"
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <setjmp.h>

5
fn.h
View File

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

1
gc.c
View File

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

15
main.c
View File

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

121
parser.c
View File

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